Browsing the archives for the Uncategorized category.


The Human Stain

Uncategorized

Just started reading Philip Roth’s famous novel The Human Stain and am already enchanted by the language he uses, and the direct, true way that he describes the human condition. Take for example, this paragraph:

There is something fascinating about what moral suffering can do to someone who is in no obvious way a weak or feeble person. It’s more insidious even than what physical illness can do, because there is no morphine drip or spinal block or radical surgery to alleviate it. Once you’re in its grip, it’s as though it will have to kill you for you to be free of it. Its raw realism is like nothing else.

That last sentence could describe the whole book thus far.

I’m only a quarter of the way through but just had to share my early love for this novel. Roth uses such evocative phrases – “the contamination of desire” is wonderful – that I will be sure to read his other novels when finished with The Human Stain.

No Comments

PowerShell Community Extensions for PowerShell 2 CTP 3

Software, Uncategorized

PowerShell Community Extensions:

is aimed at providing a widely useful set of additional cmdlets, providers, aliases, filters, functions and scripts for Windows PowerShell that members of the community have expressed interest in.

Short answer: you want this, if you’re a PowerShell user. However, there are some initial gotchas that may cause you problems. I’m running Windows Vista Ultimate 32-bit, and had to do a bit of tweaking to get the install working properly. Here are the notes from my session:

First, go to the PSCX website to get the latest download (version 1.1.1 at the time of this writing).

Next, run the following script one time in the ISE:

$path = "$((get-pssnapin -r pscx).applicationbase)\typedata\filesystem.ps1xml"
$config = [xml](gc $path)
$config.Types.removechild($config.Types.Type[1])
$config.get_outerXML() > $path
update-typedata

Close the ISE and relaunch it.

You’ll see a bunch of errors like the following:

Set-Alias : Alias is not writeable because alias measure is read-only or constant and cannot be written to.

For some reason, some of the PSCX aliases are set to read-only and need the -Force parameter to get them to work.

Instructions for fixing each of the issues:

C:\Program Files\PowerShell Community Extensions\Profile\GenericAliases.ps1
Line 8
Set-PscxAlias measure MeasureObject -Force

C:\Program Files\PowerShell Community Extensions\Profile\PscxAliases.ps1
Line 28
Set-PscxAlias start Start-Process -Force

C:\Program Files\PowerShell Community Extensions\Profile\Debug.ps1
Line 72
set-alias gcs Get-CallStack -Option AllScope -Description "PSCX function alias" -Force
Line 89
set-alias ebp Enable-Breakpoints -Option AllScope -Description "PSCX function alias" -Force
Line 103
set-alias dbp Disable-Breakpoints -Option AllScope -Description "PSCX function alias" -Force

No Comments

Slogan Fail

Uncategorized

I think I mentioned that last week I heard Scott Porad, the CTO of Pet Holdings, speak at the monthly Seattle Tech Startups meeting. After hearing him talk I started poking around FAIL Blog again after a lengthy hiatus.

Found this gem on there today: “Slogan Fail”. Take a gander and prepare to ride the roflcopter!

No Comments

On Achieving Goals

Uncategorized

Thinking today about goals – specifically, what is a good goal to have?  And how does one go about achieving the goal(s) you’ve set out for yourself?  I’m sort of in this place right now where I’m pretty sure what I want, but have no idea the specific steps that I need to take in order to make it happen.  Also, I’m not certain how much of the goal depends on my efforts, vs. other serendipitous events falling into place.  So, it’s a bit of a conundrum.  Blogs are good places to work out conundrums, and maybe by the end of this post, you’ll have a nugget or two of advice to give me.

First: what’s a good goal?  There’s the well-known dictum about SMART goals – Specific, Measurable, Achievable, Realistic, and Timeboxed (the terminology varies somewhat, but that’s a typical construction).

So let’s take my mystery goal and apply the SMART test.

Specific?  Oh, very.  I have it all laid out perfectly in my mind.

Measurable?  Yes, any objective observer could determine if this goal was achieved or not.

Achievable?  This is thornier.  I mentioned that I didn’t know how much my efforts could actually contribute to success – it depends in large part on other people – some specific, some general.

Realistic?  Again, I’m not quite sure.  I hope – with every ounce of my being – that this goal is realistic, but there’s a lot that could go wrong, and I’m not privy to all of the information necessary to really know if this thing can be done.

Timeboxed?  A big FAIL on this one. I have no idea what the best timeframe would be, and again, it depends on other people.

So, looking back over this analysis, how could I make sure the goal is realistic?  Hm. I could start asking questions about those areas of which I’m currently ignorant.  Sometimes, however, and with some people, that gets a little touchy, particularly if one is dealing with sensitive information.  And I wonder – how important is it for a goal to be 100% realistic anyway?  Some of humankind’s most remarkable achievements – climbing Mt. Everest, landing a man on the moon, the perfect World Series game – probably seemed unrealistic to most observers.  The important part was that the participants believed they could do it.

Maybe the important part is either (a) absence of doubt on the part of the goal-setter, or (b) the absolute desire for the outcome.  Or both.

Let’s move on to timeboxed.  Could I set a date by which, without fail, I could achieve this goal, assuming all other parts came together?  Thinking about it, I suppose I could.  The rationale for this characteristic in the SMART system is to get your ass off the couch and start working toward the goal.  I read a recent article in Newsweek magazine titled “Why We Procrastinate and How to Stop that describes the phenomenon of “psychological distance” the notion that vague/abstract tasks are easier to put off than specific/concrete tasks. This is at the root of the S and M in the SMART process, but the article also talks about you can also consider a timebox – “I will finish this task by 12:31 PM on Monday, May 25th” – as another way to get your task into the specific/concrete arena.

You’ll notice that throughout this post I haven’t mentioned what my goal was.  Some of those close to me will be able to guess, but the point I’m trying to make is about goals in general.  My next mental excursion may talk about how different types of goals – career, fitness, relationship, hobbies – may need to be treated differently than the classic SMART definition would have us operate.

No Comments

Boats and Butterflies

Uncategorized

The world is experiencing a series of tremendous disruptions – in entertainment, in journalism, in retail, in manufacturing, in medicine, and many more.  Maybe you are experiencing a disruption of your own.

You can adjust to these rapid-fire (and sometimes unwelcome) changes in one of two ways. I’ll call this the Parable of the Boat and the Butterfly.

[...]

One day, after a long period of calm weather, the wind started gusting.  Over the course of the morning, the wind blew harder and harder.  It shook the houses.  It knocked over recycle bins and sent newspapers flying down the street.  No one in town had ever seen wind like this.

At the harbor the wind caused huge waves to crush into the piers, which rattled the docks and sent the merchant fisherman scrambling for cover.  Out in the middle of the harbor, a lone boat which had become unmoored floated amidst the huge waves.  But despite the howling wind and roaring waves, the boat did not capsize.  It flowed with the forces acting on it.  When the waves crested, the boat rose.  When a trough came, the boat dipped.  Having no sail and no hand on the tiller, the boat floated where it would, not fighting the chaos but temporarily merging with it.

At one precise moment, a butterfly, blown in from who knows where, was fluttering out at sea.  The butterfly kept flapping his wings, trying – vainly – to go in this direction or that direction, but was stymied at every attempt by the overwhelming power of the wind.  The butterfly flapped left – and went straight.  He flapped right – and went straight.  Up and down – he went straight.  He tried so hard to go in different directions other than with the prevailing wind that he finally tired and, unable to keep himself aloft, folded his wings in and was crushed into the roiling waters.

Eventually the wind died down, and the little boat was recovered and brought back to land by the fishermen.  Aside from getting wet, there was no damage.

End of parable.

No Comments

Seattle Tech Startups Recap: May 13 2009

Uncategorized

UPDATE:Here are Vanessa Fox’s slides and here is Scott Porad’s slide deck.

Last night at STS Vanessa Fox of Nine By Blue gave a great talk on SEO – she really, *really* knows her stuff and is one of the acknowledged worldwide experts on the topic. Scott Porad of Pet Holdings (I Can Has Cheezburger, and other sites) then talked about User-Generated Content and wove together a lot of great thoughts into a very interesting presentation.

Mike Koss of StartPad has posted both videos here for your viewing pleasure. Highly recommended!

No Comments

Catchy Tune

Uncategorized

This song by Landon Pigg is warm and wonderful:

No Comments

Click To Call Example For Twilio

Uncategorized

Twilio is a local company that has developed some very spiffy telephony technology that takes 99% of the pain out of integrating telephone calling capabilities into your application.

I’ve previously demoed some easy examples of getting your feet wet with the Twilio API. In this post I’ll take on a more challenging example: implementing a web-based click-to-call function.

What is click-to-call (aka C2C)? This is a feature that lets your customer flag you and say (for example) “Hey, I’m interested in talking to somebody about this product I’m looking at. Here’s my phone number; have a specialist call me as soon as one becomes available.”

This is a big win for the customer because they don’t have to wait on hold; it’s a big win for you, the application vendor, because you get a happier, less stressed out customer. Also, as we will see, you can use the magic of server-side programming to send important information to your agents, prepping them for the call. You can even route calls to the most knowledgeable agents based on which web page(s) your customer is viewing when they initiate the request!

Here’s a diagram that shows the sequence of events (click for larger version):

twilio-click-to-call-example

Click here to view my public Twilio Click-to-Call demo website to follow along as you read through this post.

The first thing to do is to build a page that your customer interacts with. We’ll call this first page in the process default.aspx and make it the default startup page for our web project. In our sample, we’ve dummied up this page to show fictional product details for the Jawbone Bluetooth headset. Featured prominently on the page is a big “Click to Call” button. When the customer clicks that button, we want to fire off the request to Twilio and get the ball moving.

There are two main parts to the code-behind: actually interacting with the Twilio API to make the outbound call to the customer, and setting up the handler that we want Twilio to use once the customer is connected.

Let’s take those in reverse order and talk about the handler first. This is a web page that serves up TwiML, a domain-specific XML dialect, that Twilio interprets and uses to run additional actions when a phone call is connected.

In our case, we’ll want the customer to hear something like “We’re connecting you now”, and then we’ll want to dial our customer service representative to connect them to the customer. TwiML provides two handy verbs, <Say> and <Dial>, that exactly serve our purpose.

A simplified version of our handler would return something like this as an XML response document:

<Response>
<Say>We’re connecting you now.</Say>
<Dial>206.555.1212</Dial>

For the purposes of our initial product page, default.aspx, we only need the URL to point Twilio to. So there is some code-behind that builds the URL, and passes along the product name (“Jawbone”), which we will take advantage of later.

1
2
3
4
5
6
7
8
9
10
11
12
13
protected virtual string GetBaseUrlPath()
{
string baseUrl = Request.Url.Scheme + "://" + Request.Url.Authority + Request.ApplicationPath.TrimEnd('/');
return baseUrl;
}
protected virtual string GetDialHandlerUri(string product)
{
string baseUrl = this.GetBaseUrlPath();
string handlerPath = "/c2c/user.aspx";
string url = baseUrl + handlerPath;
string qs = String.Format("?product={0}", product);
return url + qs;
}

There’s some plumbing code to make sure we’re getting the right URL base path, and then we construct the actual URL to our handler page – in this case, http://twilio.xidey.com/c2c/user.aspx?product=Jawbone.

Now let’s talk about initiating the outbound phone call to the customer. Twilio does this for us when we make a special request to their REST API. Specifically, we make a POST request to our “Calls” resource, with three parameters:

  1. The number we want to call
  2. The number we are calling from (for Caller ID purposes)
  3. The URL of our handler document, as described above

We’ll use the Twilio REST Helper Library that is provided for you on their website (need URL here Anthony). This library provides a ready-made Account class that you can use to make this POST request.

Here’s the code-behind in our product page to make the call:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// calls the customer at the phone number passed in as a parameter
protected void CallPhoneNumber(string phoneNumber)
{
string product = "Jawbone";  // product on current page
// construct our handler URL
string handler = this.GetDialHandlerUri(product);
string caller = "2064098427"; // use your caller ID here
// set up the POST parameters
Hashtable vars = new Hashtable();
vars.Add("Url", handler);
vars.Add("Caller", caller);
vars.Add("Called", phoneNumber);
// construct the URI to your “Calls” resource
string url = string.Format("{0}/Accounts/{1}/Calls", API_VERSION, ACCOUNT_SID);
string method = "POST";
Twilio.Vb.Api.Account a = new Account(ACCOUNT_SID, AUTH_TOKEN);
string result = a.Request(url, ref method, vars);
}

This is all pretty simple, right? Figure out what the customer is viewing; get their phone number; and make a special request to Twilio to call that customer. Our handler document will take care of the 2nd part – connecting the customer to a customer service representative so they can chat.

Let’s revisit our handler document, and extend our previous simple example. Twilio provides a neat facility that allows you to dial multiple phone numbers when trying to make a connection. For example, let’s say you had three Jawbone product experts manning the phones. You can instruct Twilio to call all three, and the first one to pick up “wins” and the other two connection attempts are cancelled. We can get customer service phone numbers from a simple DB lookup, as follows:

1
2
3
4
5
6
7
8
9
10
11
protected virtual IList<string> GetCustomerServicePhoneNumbers()
{
IList items = null;
string connString = ConfigurationManager.ConnectionStrings["twilio_demoConnectionString"].ConnectionString;
using (click_to_callDataContext dc = new click_to_callDataContext(connString))
{
items = (from csp in dc.customer_service_persons
select csp.phone_number).ToList();
}
return items;
}

Here we’re using LINQ-to-SQL to establish a connection to a SQL Server database and get a list of all the customer service representatives’ phone numbers.

Further, just like in our product page, we can specify an action that we want Twilio to take when we call the customer service representatives. In our case, we’ll probably want to give them detailed information about the customer, or the product they are viewing, or other essential details that may help the conversation. For now, it’s enough to know that we can specify an action URL for each <Dial> request.

Here’s the code to generate the URL for the handler document; it looks suspiciously like the code we used to generate the handler URL for the original POST to our Calls resource.

1
2
3
4
5
6
7
8
protected virtual string GetCsrUri(string product)
{
string baseUrl = this.GetBaseUrlPath();
string handlerPath = "/c2c/csr.aspx";
string url = baseUrl + handlerPath;
string qs = String.Format("?product={0}", product);
return url + qs;
}

Only the page name has changed: in this case, our handler will be csr.aspx instead of user.aspx.

Our extended handler document now looks more like this:

<Response>
<Say>Please wait; we’re connecting you now…</Say>
<Dial action="http://twilio.xidey.com/c2c/user.aspx?product=Jawbone" method="GET">206.555.1212</Dial>
<Dial action="http://twilio.xidey.com/c2c/user.aspx?product=Jawbone" method="GET">206.555.8989</Dial>
<!--—more DIAL entries here, if you want –-->
</Response>

* Note: I’m showing the URLs as unencoded for clarity. In real life you want to UrlEncode your URLs. *

That action attribute of the Dial element tells Twilio, “When you connect the customer service representative, use this URL as your handler document to tell you what to do next.” Note that the action handlers are the same in our sample – this isn’t necessary, however. You could have custom actions for each CSR in your database if you wanted.

How do we actually write out the handler document? We’ll use a simple .NET XMLDocument, as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected virtual XmlDocument CreateHandlerDocument(string product, IEnumerable phoneNumbers)
{
XmlDocument doc = new XmlDocument();
XmlNode documentElement = doc.AppendChild(doc.CreateElement("Response"));
XmlNode sayElement = documentElement.AppendChild(doc.CreateElement("Say"));
sayElement.AppendChild(doc.CreateTextNode("Please wait while we connect you to a customer service representative."));
foreach (string phoneNumber in phoneNumbers)
{
XmlNode dialElement = documentElement.AppendChild(doc.CreateElement("Dial"));
XmlNode actionAttribute = dialElement.Attributes.Append(doc.CreateAttribute("action"));
actionAttribute.Value = Server.UrlEncode(this.GetCsrUri(product));
XmlNode methodAttribute = dialElement.Attributes.Append(doc.CreateAttribute("method"));
methodAttribute.Value = "GET";
dialElement.AppendChild(doc.CreateTextNode(phoneNumber));
}
return doc;
}

To recap where we’re at: Our first page (default.aspx) told Twilio to call the customer, and when they answer, Twilio should use the contents of this handler page (user.aspx) to determine next actions. In this case, we’ll tell the user to wait, and then we’ll ask Twilio to dial our customer service representatives. When the CSR answers the phone, we’ll use a third page (csr.aspx) to tell Twilio what to do when the CSR answers.

Let’s get to the details of the CSR handler document. In our sample project, this is a TwiML document that informs the CSR what product the customer is looking at, so they can say something really smart and contextual like “Hi there! My name is John Smith. I’d be happy to answer any questions you may have about the Jawbone – and did you know that today only we’re offering 15% off?”

<Response>
<Say>You have a customer calling about the product Jawbone.</Say>
</Response>

The code to write out this handler document (csr.aspx) is essentially the same model as the code we used to write out the first handler document (user.aspx), and we’ll omit it here for clarity, but check out the attached source code for details.

Now we have an end-to-end solution. Recapping our original process diagram:

  1. Customer views a product page on your website.
  2. Customer clicks a “Call me!” button on your page, asking for a phone call.
  3. Your web application makes a POST request to Twilio, requesting an outbound call to the customer.
  4. When the customer answers, Twilio inspects your first handler document (user.aspx), says something to the customer, and then dials your CSRs.
  5. When the first CSR answers, Twilio inspects your second handler document (csr.aspx), and tells the CSR which product the customer is calling about.
  6. Twilio then connects the customer with the CSR, and they are off and running.

There are a few takeaways from this example that are worth highlighting:

  1. Learning TwiML and the Twilio REST API is easy. Really easy.
  2. You can “chain” requests to Twilio via a succession of handler documents.
  3. You can pass dynamic information in to your handler documents via request parameters (GET or POST). In our case, information about the product that the customer was looking at was carried along through two handler documents, to finally be repeated to the CSR when they picked up the phone.

However, not everything always goes as planned, so you have a few tools at your disposal, aside from the normal Visual Studio compilation and debugging environment:

First, there is the Twilio documentation website that provides lots of essential detail about TwiML, the REST API, and has sample code and helper libraries. On your Account page, Twilio provides a call log that lets you see what calls were made in response to your API requests. There’s also a Twilio debugger that lets you see any problems that Twilio encountered while making the outbound calls. Then there are the Twilio Get Satisfaction forums that are manned by Twilio developers and community representatives. There’s a Twilio help e-mail alias. Last but not least, you can find Twilio on Twitter at @twilio.

So, what’s stopping you from integrating telephony into your apps? Not much, not anymore. Jump into Twilio and get your feet wet!

4 Comments

Daily Digest for March 5th

Uncategorized
twitter (feed #2) 10:41pm Posted a tweet on Twitter.
Decided that I’m going to head into work today – feeling like it’s time. [#]

No Comments

Daily Digest for March 5th

Uncategorized
twitter (feed #2) 9:16pm Posted a tweet on Twitter.
@dacort That’s 98,000 tears that baby Jesus will shed today. [#]

No Comments
« Older Posts