Develop and deploy Silverlight + SharePoint 2010 Solutions (part 2)

A quick summary of part 1:

  1. Environment (tools)
  2. Creating Silverlight project
  3. Creating XAML
  4. Hooking up Silverlight databinding to mock data
  5. Implement real SharePoint query via Microsoft's Client Object Model
  6. Quick discussion of the deploy to document library deployment strategy - I dubbed this XAP-deployment

Part 2 is all about Debugging and Tuning our service calls and see how much fine-grained control we have in talking to SharePoint.  Read on - it's really awesome. 

 

TIMER UPDATE (RE-QUERY)

First problem we have is that the Silverlight application does not re-query the service.  It runs, queries SharePoint once, and then stops.

  1. Let's make it query SharePoint on a periodic basis.  There are various timers available in Silverlight, the easiest to use is the System.Windows.Threading.DispatcherTimer:
  2.         public SharePointChart()
            {
                InitializeComponent();
                sharepointContext = ClientContext.Current;
    
                DispatcherTimer timer = new DispatcherTimer();
                timer.Interval = new TimeSpan(0, 0, 5);
                timer.Tick += new EventHandler(timer_Tick);
                timer.Start();
            }
            private void timer_Tick(object sender, EventArgs e)
            {
                if (sharepointContext == null)
                {
                    GetData();
                }
                else
                {
                    QueryDataFromSharePoint();
                }
            }
  3. Notes:
    • Create a DispatcherTimer, set it to tick every 5 seconds
    • On each tick - query data from SharePoint
    • By magic of the earlier work we did with databinding in XAML - there is no UI update code required.  The code (controller) updates the data (model) and the UI (view) updates automatically.  This is best practice to move towards full MVVM in Silverlight, and the least amount of headaches down the road.

DEBUGGING SILVERLIGHT

As Silverlight is running in the Browser, debugging the Silverlight application can be done via Attaching the debugger to a running browser process.

image

image

In the list of processes - look for the browser process that has Silverlight run time loaded.

image

You can attach to other browsers as well.

Key notes:

  • Client side debugging Silverlight is superior:
  • Managed Code - not Javascript
  • Browser-independent - no fiddling with different DOM or browser behaviours
  • Server-independent - you could be talking to your development, test, UAT or Production server, the server could be on-premise or in-the-cloud (SharePoint Online).  You are still, debugging the Silverlight that's running on your own machine, calling the server via published services.

 

TUNING SILVERLIGHT

Let's see what Silverlight is doing under the hood.  Run our favourite HTTP sniffer Fiddler 2 (you can also use FireBug or Wireshark - whichever you are familiar with):

image

Since our Silverlight is faithfully re-polling the server every 5 seconds, we see this particular HTTP connection repeating - for as long as the Silverlight app is running (close browser window to stop it)

image

Notice the return traffic is 1.3K - relatively tiny in the scheme of things.  By comparison:

image

  • Full page reload starts at 30k for bare page
  • AJAX web parts are about 20k (rough estimates)

 

Digging in a bit more on the traffic

image

 

 

 

The request is XML

image

The response is gzipped-compressed JSON (Javascript Object Notation)

 

TWEAKING THE QUERY IN LINQ

This next part is tricky but interesting.  The code first.

        private const string ListName = "Football";
        private const string InternalFieldName = "FavouriteCountry";
        private ListItemCollection listItems;
        private IEnumerable<ListItem> listItems2;

        private void QueryDataFromSharePoint()
        {
            Web web = sharepointContext.Web;
            // get our list
            List list = web.Lists.GetByTitle(ListName);
            // get items in our list
            listItems = list.GetItems(CamlQuery.CreateAllItemsQuery());

            
            // still need the earlier syntax to tell sharepoint where to get it
            listItems2 = sharepointContext.LoadQuery(
                listItems.Include(
                    item => item["Title"],
                    item => item[InternalFieldName])
                );

            // but don't actually load it!
            //sharepointContext.Load(listItems);

            // execute the load asynchronously
            sharepointContext.ExecuteQueryAsync(SucceededCallback, FailedCallback);
        }

Notes:

  • We still need a reference to the ListItems Collection via List.GetItems(CamlQuery.CreateAllItemsQuery());
  • We use it as a reference point to begin our LINQ Query
  • The SharePoint ClientContext has a separate LoadQuery method, that returns a new ListItems collection - listItems2, we start from the CAML definition, and further refine it to ONLY include the Title and FavouriteCountry fields.
  • But we don't actually ever call Load on ListItems

Result:

image

We've shrunk the data load from 1.7k down to 359 bytes!

image

The returned JSON object is a lot lighter - and contains only a few of the required fields (ID, ObjectType, ObjectVersion), as well as our Title and FavouriteCountry.

 

MAKE YOUR SERVER DO WORK

Imagine the list is thousands of items.  We don't always want to bring back every list item.  What we should always consider is how to use SharePoint to do much of the work for us, and keep our connection traffic low.

            listItems2 = sharepointContext.LoadQuery(
                listItems.Include(
                    item => item["Title"],
                    item => item[InternalFieldName])                    
                .Where(
                    // add where clause for server to execute
                    item => (string)item["Title"] == "john")
                );

Notes:

  • I'm inserting here a Where clause to my LINQ query.  The Query is to be executed on the server.
  • IMPORTANT: do not use Where clause on the Load method - because that is a LINQ to objects filter and is very bad:  imagine bringing down 1000 items and then do your filtering in memory on the client side…

Result:

image

Only pulling back 1 record.

image

Check out the Request XML - includes the Where clause filter.

SUMMARY

  • How to attach debugger, check network traffic with Fiddler
  • Do your VIEWFIELDS, FILTER and SORT on the server
  • LINQ is converted to CAML beneath the hood - but you can avoid CAML…  almost
  • Trim your service call
  • You probably don't need to poll the server every 5 seconds as well

 

NEXT UP

Wrapping up in the next part for:

  • Deployment considerations
  • Out of Browser
  • REST interface
  • Silverlight initParam

Update: Part 3 (final) is now up.

Silverlight + SharePoint: helper classes

While composing my earlier blog about Silverlight + SharePoint +CAML best practices, it dawns on me that it would be quite possible to build a helper library to assist the user in cleaning up the LINQ statements before sending it off to the server, similar to how the client object model tries to convert LINQ to CAML beneath the hood.

Similarly, there are a few useful properties in the Server object model that is missing in the client object model.  These could be provided via a helper class as well.

This would make a nice little weekend project.

Outlook (and blogs) are for code

After being annoyed with Outlook... well, forever... for always autocorrecting my code in my emails, it suddenly strikes me to find the auto correct settings to just stop this once and for all.

So apologies in advance from now until the end of time - if my "quotes" actually be doublequotes and my - (minus or hyphen) actually be a minus and not a dash.

Both are very important in being able to correctly paste code, I figure my human recipients could live with less than perfect typography ;-)

Turn off:

  1. "Straight quotes" with "smart quotes"
  2. "Hyphens (--) with dash (-)

Auto Correct options

In Outlook

 

image

in Windows Live Writer

This is something extremely simple, and I wonder I couldn't be the only person that has done this.  I can't understand why it took me 10 years... of pressing Undo right after pasting code into an email…  Goes to show you that most people never tweak the out of the box settings.

Windows 7 Troubleshooting Wizard is not a myth

I know this sounds crazy.   The network troubleshooting wizard actually works.

So I was on a designer’s machine and she was really having trouble with her wireless card – it’s reporting an IP Address conflict.

We figured that a simple:

ipconfig /release
ipconfig /renew

Should do the trick, but it was skipping the wireless adapter.  Confused – we stumbled across the wizard and clicked “Windows Network Diagnostics”.

To our amazement it asks us if we want it to fix the network for us. 

Behold!

clip_image002

Also explained why it wasn’t working before.

Apple iPhone drivers are pos

Exhibit A: Windows Explorer looking at the pictures in my iPhone.

Exhibit A: Windows Explorer looking at the pictures in my iPhone. 

 

Notice that almost ALL of them are upside down, this happens very often when I take pictures sideways.  At a glance – you probably think (and I as well) ah you must have held your camera upside down.

But stop for a second.  When I view the pictures in iPhone, it always know which way is UP.  Imagine if you were trying to look at your pictures in your iPhone and they were upside down…  You’d try to flip the phone… but then iPhone will flip the pictures upside down again!  The whole Pictures library will be unusable.  People would get upset!

That means the iPhone knows intrinsically which way is UP, for each picture.

So WTF is it doing when it shows the picture through their drivers on Windows Explorer?

My educated guess and conclusion really is just this:

Apple don’t care if you use an application that’s outside of their ecosystem.  They simply don’t care if you have the absolutely shittiest experience.  Why, it must be Windows’ fault if it can’t render pictures correctly… 

I hate this arrogant side of Apple.  Pisses me off when their engineers can do such a great piece of art and yet at the same time piss on other engineers’ work.