Archive for the ‘Silverlight 4’ Category

Adding Cookies to a Windows Phone 7 HttpWebRequest

1 Comment »

I just spent a couple days on this and, in the end, I didn’t really figure it out. Someone else at my work (the brilliant Rylan Barnes) showed me the workaround for it.

So… you want to add a cookie to your Windows Phone 7 Silverlight HttpWebRequest. Guess what? It sucks to be you! Or, at least, it sucked to be me because I couldn’t find anything on how to do this that worked.

I was working on a project that requires the user to authenticate and, on authentication, sends back a token (unique to that user) to be attached as a cookie for further authentication. However, when I attached the cookie and made my next request, it made that request without the authorization header. Our server said “Hey, looks like you’re not authenticated, I will now forget about that last cookie because you obviously didn’t get it. Have a new one!”

First I’m going to show you things that don’t work.

Didn’t Work: Adding An Empty Cookie Container to the Request

public void DoSomeCRUD(string userName, string pass)
{
    HttpWebRequest request = System.Net.HttpWebRequest.Create("https://myurl.com") as HttpWebRequest;
    if (HasSavedCookieContainer)
        request.CookieContainer = SavedCookieContainer();
    else
        request.CookieContainer = new CookieContainer();
    request.Credentials = new NetworkCredential(userName, pass);
    request.BeginGetResponse(new AsyncCallback(GetMyResponse), request);
}

private void GetMyResponse(IAsyncResult MyResponseAsync)
{
    HttpWebRequest request = (HttpWebRequest)MyResponseAsync.AsyncState;
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(MyResponseAsync);
    // this method save the cookie container to IsolatedStorage 
    // so I can attach it to the request the next time I open the app.
    SaveCookieContainer(request.CookieContainer);
}

The saving worked, the cookie container came back just as I saved it. And then… it didn’t work. It was as if the cookie didn’t exist.

Didn’t Work: Ripping The Token Out Of the “Set-Cookie” Header

public void DoSomeCRUD(string userName, string pass)
{
    HttpWebRequest request = System.Net.HttpWebRequest.Create("https://myurl.com") as HttpWebRequest;
    if (IsolatedStorageSettings.ApplicationSettings.Contains["MyToken"])
    {
        string myToken = (string)IsolatedStorageSettings.ApplicationSettings["MyToken"];
        Cookie c = new Cookie("MyCookieName", myToken, "[valid path]", "[valid domain]");
        request.CookieContainer = new CookieContainer();
        request.CookieContainer.Add(new Uri("http://myurl.com"), c);
    }
    else
        request.CookieContainer = new CookieContainer();
    request.Credentials = new NetworkCredential(userName, pass);
    request.BeginGetResponse(new AsyncCallback(GetMyResponse), request);
}

private void GetMyResponse(IAsyncResult MyResponseAsync)
{
    HttpWebRequest request = (HttpWebRequest)MyResponseAsync.AsyncState;
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(MyResponseAsync);
    // this method looked for "Set-Cookie" information in the header
    // and the pulls out the token data by brute force and save the
    // token as a string
    if (ResponseHasSetCookieInHeader(response))
    {
        string rawToken = GetTokenFromResponse(response);
        IsolatedStorageSettings.ApplicationSettings["MyToken"] = rawToken;
        IsolatedStorageSettings.ApplicationSettings.Save();
    }
}

The save worked here too, but the same result… it was like the cookie didn’t exist.

This Worked: Adding the Cookie as a Header

Finally we added the token and the credential information as header items. This finally worked.

public void DoSomeCRUD(string userName, string pass)
{
    HttpWebRequest request = System.Net.HttpWebRequest.Create("https://myurl.com") as HttpWebRequest;
    if (IsolatedStorageSettings.ApplicationSettings.Contains["MyToken"])
        request.Headers["Cookie"] = "MyTokenName=" + (string)IsolatedStorageSettings.ApplicationSettings["MyToken"];

    request.Headers["Authentication"] = "Basic " + Convert.ToBase64String(StringToAscii(userName, pass));
    request.BeginGetResponse(new AsyncCallback(GetMyResponse), request);
}

private void GetMyResponse(IAsyncResult MyResponseAsync)
{
    HttpWebRequest request = (HttpWebRequest)MyResponseAsync.AsyncState;
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(MyResponseAsync);
    // this method looks for "Set-Cookie" information in the header
    // and the pulls out the token data, saving it to Isolated Storage
    if (ResponseHasSetCookieInHeader(response))
    {
        string rawToken = GetTokenFromResponse(response);
        IsolatedStorageSettings.ApplicationSettings["MyToken"] = rawToken;
        IsolatedStorageSettings.ApplicationSettings.Save();
    }
}

For the sake of giving credit, here is the StringToAscii method for the Authentication, tweaked from this StackOverflow answer from Hans Passant

public static byte[] StringToAscii(string userName, string pass)
{
    string s = userName + ":" + pass;
    byte[] retval = new byte[s.Length];
    for (int ix = 0; ix < s.Length; ++ix)
    {
        char ch = s[ix];
        if (ch <= 0x7f) retval[ix] = (byte)ch;
        else retval[ix] = (byte)'?';
    }
    return retval;
}

Finding the Unique Device ID in Windows Phone 7 (And Device Manufacturer And Anonymous Windows Live ID)

2 Comments »

I’m tired of trying to find things about Windows Phone 7 development, so I’m just going to post links that I find helpful so I can find them later.

Here’s Nick Harris with a handy set of static methods for getting the following unique IDs:

  • Device Manufacturer ID
    • DeviceExtendedProperties.TryGetValue(“DeviceManufacturer”, out someObject);
    • example: “HTC”
  • Device ID
    • DeviceExtendedProperties.TryGetValue(“DeviceUniqueId”, out someObject);
    • requires ID_CAP_IDENTITY_DEVICE in the app manifest which will trigger a warning to users when they install the app
    • a byte[], converter to a string will looks like
      “12345678901234567890123456789012345678901234567890123”
  • Anonymous Windows Live ID
    • A 32 character subset at offset 2  of the results of
      “UserExtendedProperties.TryGetValue(“ANID”, out someObject)
    • requires ID_CAP_IDENTITY_USER in the app manifest which will trigger a warning to users when they install the app
    • looks like “00FF00FF00FF00FF00FF00FF00FF00FF”

However, if you just need any unique identifier (not necessarily a device ID), you can always set and store a new global unique identifier using:

Guid.NewGuid();

which will return a 128-bit integer that will look something like this:

“e81644f1-46b6-4994-2903-1d1f1440c130″

This will not cause warnings to appear when the app is downloaded because it isn’t a constant identifier to that specific device.


Silverlight 4 Binding and StringFormat in XAML

25 Comments »

I discovered this amazing feature almost by accident and it has made this one part of my design so much easier that I had to share it.

A new feature in Silverlight 4 is the ability to using the StringFormat feature when binding. Previously, if I wanted to have a piece of text that said “Your name is [username]” I could either use the old Horizontal-Stack-Panel-And-2-TextBlocks trick (as seen below)…
<StackPanel Orientation=”Horizontal”>
<TextBlock Text=”Your name is” Margin=”0,0,4,0″/>
<TextBlock Text=”{Binding username}“/>

</StackPanel>

…or write a value converter (not going to be seen below because there’s a great example of it over here. Incidentally, that example is totally irrelevant if you’re going to use StringFormat, but more on that in a second).

The StringFormat option in Silverlight 4 allows you put all that information into a single field, which is extremely useful not only for TextBlocks, but for Content fields in a Button. In fact, let’s use that as an example.

Let’s say you want to create a Button to log out, so you want it to say “Log Out of <Username> Account”. (A bit clumsy, but the technique is the important part.) All you would have to do is the following:

<Button Content=”{Binding username, StringFormat=’Log Out of \{0\} Account’}“/>

This gets even better for things like number formatting. Let’s say we want the user to enter an amount of money (for example, $1,593.29) into a TextBox (maybe in a PayPal application). If we have bound that value to a numeric format, we can express that format through binding and when the TextBox loses focus, the StringFormat will take the number entered and format in a currency format.

<TextBox Text=”{Binding paymentAmount, StringFormat=\{0:C2\}}/>

The only issue with numerical and date formats is they the MUST be bound to a number or date.

With that in mind, here is a sampling of StringFormat options, stolen mostly from Kathy Kam. For more complete options, check out the MSDN articles on String.Format and trial-and-error your way through things. If you want to play around with this, download my StringFormat project or look at the Silverlight sample app at the bottom of this page.

Strings

For a string with the value “Silverlight”

Using \{0\,#\} effectively forces the string to be at least # characters long, using spaces to pad it to the requested length.

StringFormat=\{0\,20\} : “                  Silverlight”
StringFormat=\{0\,-20\} : “Silverlight                  ”
StringFormat=’I just typed &quot;\{0\}&quot;.’ : “I just typed “Silverlight”.”

MSDN article on Composite Formatting

Numbers

For a double with the value : “38293.53”

StringFormat=c : “$38,293.53” – Use ‘c’ for currency
StringFormat=e : “3.829353e+004” – Use ‘e’ for exponential (scientific)
StringFormat=n : “38,293.53” – Use n for number

You can also use these in the following format:

\{0:(letter)(number)\}

where (number) indicates how many decimal places there should be. The format will use standard rounding rules to determine the last digit. For example:

StringFormat=\{0:c0\} : “$38,294”
StringFormat=\{0:n4\} : “38,293.5300”
StringFormat=You have \{0:c1\} : “You have $38,293.5”

MSDN article for standard number formatting
MSDN article for custom number formatting

Dates

The date formatting has a huge range of options.

For the DateTime of “April 17, 2004, 1:52:45 PM”

You can either use a set of standard formats (standard formats)…
StringFormat=f : “Saturday, April 17, 2004 1:52 PM”
StringFormat=g : “4/17/2004 1:52 PM”
StringFormat=m : “April 17”
StringFormat=y : “April, 2004”
StringFormat=t : “1:52 PM”
StringFormat=u : “2004-04-17 13:52:45Z”
StringFormat=o : “2004-04-17T13:52:45.0000000”

… or you can create your own date formatting using letters (custom formats)

StringFormat=’MM/dd/yy’ : “04/17/04”
StringFormat=’MMMM dd, yyyy g’ : “April 17, 2004 A.D.”
StringFormat=’hh:mm:ss.fff tt’ : “01:52:45.000 PM”

MDSN article for standard date formatting
MSDN article for custom date formatting

Sample App


Follow me: matthiasshapiro