Bring It update

I just submitted a new version of my shipment tracking application for Windows Phone 7 for testing and hopefully it will be available within a day or two. The big new feature is push notification where you’ll get status updates on your shipment (courtesy of my new Azure service that I mentioned in my previous post).

As I don’t have the means to do large scale testing it will be interesting to see how it holds up when users get the update and start using it.

permission

This feature brings with it the possibility to turn on and off push notification (as required by Microsoft) and for every shipment you wish to track you can specify the level of notification you wish to have. This is configured at the edit screen displayed below.

addpackagelevels

Tile update only specifies that only the number of updates available will be displayed on the tile itself (requires that the application is pinned to the start menu). The rest will send toast notifications.

Also, I added a little graphical update just to freshen up the UI a bit. This is also theme dependant like the rest of the application.

mainscreendetailsevents

 

Any feedback would be appreciated Smilefjes

Azure impressions

So, I decided to do something proper with my free Azure subscription (bundled with my MSDN account) and create a cloud service for my Windows Phone 7 application. It’s been a while since I worked with Azure and I was really impressed by the current version; the ease of deployment and online management.

The Silverlight management tools at http://windows.azure.com is very comfortable to work with and creating simple SQL Azure databases via a web browser is just, well, easy Smilefjes The Visual Studio 2010 Azure templates are equally great and gets you up and running within minutes.

In simple terms: Created a web service role for my WP7 application to talk to, used Entity Framework to connect to the Azure SQL database, created a worker role that (in this case) checks shipment statuses and sends push notifications back to the WP7 app and voila: Cloud-enabled appSmilefjes

The local debugging capabilities (Compute and Storage emulators) are all wired up for you and a quick F5 gets you going.

Basically, that’s my impressions for the current version of Azure and thus far I’m (obviously) pleased with itSmilefjes

SharePoint FBA & Reactive Extensions

Some of the dangers with new toys is to overuse them, I fear I might be doing that with reactive extensions but oh well.. It’s all about the learningSmile

Today I did a test to do Form Based Authentication with SharePoint using reactive extensions. This is the first attempt, it can probably be made more streamlined as I figure out more about Rx.

Oh, apologize for the syntax coloring in the code, I really need to find some better CSS for this…

I have two classes: One for doing the FBA (which also holds the cookie jar as we will get a cookie once the FBA is successful and need to pass this along to the next web service call) and one for doing web service calls.

public class FormsBasedAuthentication {
    public static CookieContainer CookieJar = new CookieContainer();
    private const string AuthEnvelope = @"<?xml version=""1.0"" encoding=""utf-8""?>
                <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
                  <soap:Body>
                    <Login xmlns=""http://schemas.microsoft.com/sharepoint/soap/"">
                      <username>{0}</username>
                      <password>{1}</password>
                    </Login>
                  </soap:Body>
                </soap:Envelope>";

    public static IObservable<string> Authenticate(string server, string username, string password) {
        Uri authService = new Uri(string.Format("{0}/_vti_bin/authentication.asmx", server));
        HttpWebRequest authRequest = WebRequest.Create(authService) as HttpWebRequest;
        authRequest.CookieContainer = CookieJar;
        authRequest.Headers["SOAPAction"] = "http://schemas.microsoft.com/sharepoint/soap/Login";
        authRequest.ContentType = "text/xml; charset=utf-8";
        authRequest.Method = "POST";
        return (from request in Observable.FromAsyncPattern<Stream>(authRequest.BeginGetRequestStream, authRequest.EndGetRequestStream)().Do(stream => {
            UTF8Encoding encoding = new UTF8Encoding();
            string envelope = string.Format(AuthEnvelope, username, password);
            byte[] bytes = encoding.GetBytes(envelope);
            stream.Write(bytes, 0, bytes.Length);
            stream.Close();
        })
                from response in Observable.FromAsyncPattern<WebResponse>(authRequest.BeginGetResponse, authRequest.EndGetResponse)()
                select HandleResponse(response, authRequest));
    }

    private static string HandleResponse(WebResponse response, HttpWebRequest request) {
        var httpResponse = response as HttpWebResponse;
        if (httpResponse != null){
            var result = XDocument.Load(response.GetResponseStream());
            var code = result.Descendants(XName.Get("ErrorCode", "http://schemas.microsoft.com/sharepoint/soap/")).FirstOrDefault();
            if (code != null)
                return code.Value;
        }
        return "ErrorOccured";
    }

}

This will return an observable that will return the authentication result – if the login was successful, the published value will be NoError.

Next we have our web service class:

public class BaseWebService {
       private static string soapEnvelope =
           @"<soap:Envelope
                           xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
                           xmlns:xsd='http://www.w3.org/2001/XMLSchema'
                           xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
                   <soap:Body>{0}</soap:Body></soap:Envelope>";

       private XDocument soapEnvelopeXml;
       public string BaseUrl { get; set; }
       #region Helper methods
       private XDocument CreateSoapEnvelope(string content) {
           var envelope = string.Format(soapEnvelope, content);
           XDocument soapEnvelopeXml = XDocument.Parse(envelope);

           return soapEnvelopeXml;
       }

       private HttpWebRequest CreateWebRequest(string url, string action) {
           Uri serviceUrl = new Uri(url, UriKind.Absolute);
           var webRequest = WebRequest.Create(serviceUrl) as HttpWebRequest;
           webRequest.Headers["SOAPAction"] = action;
           webRequest.ContentType = "text/xml;charset=\"utf-8\"";
           webRequest.Accept = "text/xml";
           webRequest.Method = "POST";
           webRequest.CookieContainer = FormsBasedAuthentication.CookieJar;
           return webRequest;
       }
       #endregion

       public IObservable<XDocument> CallService<T>(string url, string action, string soapContent) {
           soapEnvelopeXml = CreateSoapEnvelope(soapContent);
           HttpWebRequest webRequest = CreateWebRequest(url, action);
           var call = (from request in Observable.FromAsyncPattern<Stream>(webRequest.BeginGetRequestStream, webRequest.EndGetRequestStream)().Do(stream => {
                                                                                                                                                       soapEnvelopeXml.Save(stream);
                                                                                                                                                       stream.Close();
                                                                                                                                                   })
                       from response in Observable.FromAsyncPattern<WebResponse>(webRequest.BeginGetResponse, webRequest.EndGetResponse)()
                       select Handle(response));
           return call;
       }
       private XDocument Handle(WebResponse response){
           var doc = XDocument.Load(response.GetResponseStream());
           return doc;
       }
   }

This produces an observable which will publish a XDocument with the result of the web service call. As you can see, we are using our cookie jar from the FBA class (see the CreateWebRequest method) so that our authentication token gets passed along.

To put this together and do an authenticated call to the Lists.asmx web service in SharePoint, we need two small methods.

private static void GetList(string authStatus){
            if (authStatus == "NoError"){
                BaseWebService webService = new BaseWebService();
                webService.CallService<XDocument>(“<url>/_vti_bin/Lists.asmx”, ActionGetList, string.Format(SoapGetList, "Pages")).Subscribe(Handle);
            }
        }

This method gets the published value from the FBA class and checks that we can proceed with our next call.

Oh, must not forget the SoapAction and content of the envelope:

private const string ActionGetList = "http://schemas.microsoft.com/sharepoint/soap/GetList";
private const string SoapGetList = @"<GetList xmlns='http://schemas.microsoft.com/sharepoint/soap/' xmlns:i='http://www.w3.org/2001/XMLSchema-instance'><listName>{0}</listName></GetList>";

 

private static void Handle(XDocument doc){
            Console.WriteLine(doc.ToString());
        }

And this one handles the result from the call to Lists.asmx (not doing much at this point).

So, to start it all off, we need to get our FBA observable set up:

var auth = FormsBasedAuthentication.Authenticate("<url to sharepoint site>", "<user>", "<password>");

Next we start it off:

auth.Do(GetList).Start();

What this does is that our FBA observable will call GetList for every published value that the FBA observable gives us (which should be just one) and to fire the entire process off we turn the ignition and .Start() Smile

This is all then done asynchronously.

Getting controls from inside a DataTemplate

Today I had to access a control which resided inside a DataTemplate used by a PivotItem (WP7) and there’s no straight forward way to do this as far as I know.

Thing is that pivotControl.Items[idx] returns the databound item and pivotControl.ItemContainerGenerator.ContainerFromItem(item) yields a PivotItem. But I figured that pivotItem.Content would contain the controls defined in the DataTemplate – wrong, it gives back the databound item.

So, my next try was to use the pivotItem.ContentTemplate.LoadContent() which actually did give me my controls – but LoadContent() actually creates a new object and doesn’t give you the reference to the actual live object on your screen.

Of course, the solution is rather simple if you can just think of it right off the batWinking smile

First, get the container:

DependencyObject container = pivotControl.ItemContainerGenerator.ContainerFromItem(item);

Then we use the VisualTreeHelper to take a walk around and find the control we want (by name).

var details = container.GetChild<Detail>("details");

This is all possible with this little extension method:

public static T GetChild<T>(this DependencyObject parent, string name) where T:DependencyObject{
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) {
                DependencyObject child = VisualTreeHelper.GetChild(parent, i);

                if (child.GetType() == typeof(T) && ((FrameworkElement)child).Name == name)
                    return (T)child;

                if (child.GetChild<T>(name) != null)

                    return child.GetChild<T>(name);
            }
            return null;
        }

If there’s a simpler solution to this, please let me knowSmile

Bring It preview

Just a quick little preview of my package tracking app. Added a little fun gimmick where you can see where the last transport event took place using Bing maps. Still some styling left to do and get it all prettified, but it’s starting to come together.

http://player.vimeo.com/video/16043460

Bring It Preview from Frode Hus on Vimeo.

Using reactive extensions with WebRequest

I’ve recently started looking at the Rx library from Microsoft labs and it’s very interesting stuff, even though I have to admit I have a hard time wrapping my head around it. But it starts to sink in, bit by bit 🙂


When working with Windows Phone 7 development and my SharePoint library for WP7, I do a lot of asynchronous calls to web services. This code can often get a bit messy with all the callback methods so I tried to refactor it using reactive extensions and I am pretty pleased with the result:) I’m no expert on the field so I won’t guarantee that this is the best way to do it, but it works.

Here’s a sample of how to do a call to the Lists.asmx web service in SharePoint:
string Envelope = @"<?xml version=""1.0"" encoding=""utf-8""?>
                                    <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
                                        <soap:Body>
                                            <GetList xmlns=""http://schemas.microsoft.com/sharepoint/soap/"">
                                                <listName>{0}</listName>
                                            </GetList>
                                        </soap:Body>
                                    </soap:Envelope>";

        public void GetList(string server, string name, Action<XDocument> handler)
        {
            HttpWebRequest req = WebRequest.Create(string.Format("{0}/_vti_bin/lists.asmx", server)) as HttpWebRequest;
            req.Headers["SOAPAction"] = "http://schemas.microsoft.com/sharepoint/soap/GetList";
            req.ContentType = "text/xml; charset=utf-8";
            req.Method = "POST";
            var listRequest = (from request in Observable.FromAsyncPattern<Stream>(req.BeginGetRequestStream, req.EndGetRequestStream)().Do(stream =>
            {
                UTF8Encoding encoding = new UTF8Encoding();
                string e = string.Format(Envelope, name);
                byte[] bytes = encoding.GetBytes(e);
                stream.Write(bytes, 0, bytes.Length);
                stream.Close();
            })
                     from response in Observable.FromAsyncPattern<WebResponse>(req.BeginGetResponse, req.EndGetResponse)()
                     select HandleResponse(response)).Subscribe(handler);
        }
        private void DoStuff(XDocument xml)
        {
                //parse the xml result here
        }
        private XDocument HandleResponse(WebResponse response)
        {
            HttpWebResponse res = response as HttpWebResponse;
            if (res != null && res.StatusCode == HttpStatusCode.OK)
            {
                XDocument doc = XDocument.Load(response.GetResponseStream());
                return doc;
            }
            return null;
        }

Then of course we call the method:

GetList("http://spserver.com", "Pages", DoStuff);

In Windows Phone 7 we could add .ObserveOnDispatcher() before our .Subscribe() in the LINQ query so that the current Dispatcher is used when notifying observers.

We could also generalize the method so that it returns a IObservable<T> instead which we can subscribe to.

The Empire strikes back

I shamelessly stole a tweet for the title of this entry (hope you don’t mind, chetansharma) as I found it very fitting for what transpired today in New York at the Windows Phone 7 keynote.

First off, I’ll get my pet peeves off my chest regarding Windows Phone 7:

  • No cut and paste (slated for early 2011, so at least it’s coming – yes Microsoft, we do use this functionality still)
        • No multitasking
        • Certain functionality missing from the API which I won’t get into here

Now, I do understand that certain things had to be cut for the first release in order to provide a good and stable experience and so I hope that the rest will come in (near) future updates. The approach to do quality over quantity is a good one if this new platform is to stick, we don’t need for WP7 to fail right out of the gate.

So, all that settled, let’s get to the real news: WP7 has launched and the devices has done their stroll down the catwalk! I find myself in a pickle; I don’t know which device I want as they all seem so tastySmile

I do hope that WP7 marks Microsoft’s comeback into the smartphone marked and not a complete failure like, for example, Gartner predicts. Microsoft has done a solid piece of work; they started completely fresh (pretty gutsy and costly) and even came up with their own interface or as the keynote promoted: A different kind of phone. I won’t get into all the features as plenty of articles out there do indepth reviews of them shortly, I assume, but the idea of aggregating information from different sources and placing the data at your fingertips via the tiles is an interesting approach and I think it will work delightfully.

The Metro design is a matter of taste, I’m a big fan of graphically esthetic interfaces and I love the transition effects they do. I know some think they’ve overdone it and some even say its just stupid and a poor attempt at doing something to win over the masses. I’ll just say that my personal opinion is that I love my phone to be all pretty and fancy and leave it at that.

Also, Microsoft finally did what they should have done way earlier: Set some hardware requirements for their OS to ensure smooth running and good user experience across vendors. That’s one of the main advantages a certain fruit has had as they had firm control over the hardware their OS would run on.

I have one little nuisance nagging me and that’s the availability of certain services in my country. As far as I know, there will be no Xbox Live, no Zune and no Marketplace in Norway the day the devices are out in stores. I’m rather tired of fun functionality being available only in the US such as movie rentals etc but that’s an annoying licensing matter.

But, WP7 delivers what I’ve been waiting for: A development platform where I can use Silverlight and XNA and most importantly, Visual Studio. It’s easy for beginners to get into and for more advanced developers to have fun with. That’s where the nameless fruit fails horribly. I just hope that it will get firm footing in the marked and developing WP7 applications won’t become something rare and for especially interested.

And that’s my little comment on today’s keynote.
Wonderfully and delightfully yours.