Rants Tagged with “Silverlight”

1  2  3  4  5  6  7  8  9  10  11  +  >  >>  (Total Pages: 14/Total Results: 131)

Using Closures to Simplify Asynchronous Programming

Silverlight Logo

When I teach Silverlight, some of the students lament at the requirement to make all network requests in an asynchronous manner. While I explained my opinion on the manner back in March of this year, I didn't get into how to make this easier. Lambdas and closures are the key to simplifying that code in my opinion. 

Quick caveat!  This does not work in Visual Basic (yet). VB10 has announced support for closures and lambdas that do not return values (e.g. Sub() instead of Function()), if you are using Visual Basic, I can't help you make it easier until VB10 ships.

Let's take the example of making a call to a simple web service.  I will show you two examples to try and get my idea across.  First we have a simple web service that returns a list of Game objects based on a single criterion (the genre).  Calling this service is simply a matter creating the client, registering the event handler and calling the asynchronous method:

// Create the client
GamesClient client = new GamesClient();

// Register the handler
client.GetGamesCompleted += 
  new EventHandler<GetGamesCompletedEventArgs>(client_GetGamesCompleted);

// Start the operation
client.GetGamesAsync("Shooter");

In the event handler we can just check the errors and set the result to our UI:

void client_GetGamesCompleted(object sender, GetGamesCompletedEventArgs args)
{
  // Complete the operation
  if (args.Error == null && !args.Cancelled)
  {
    theList.ItemsSource = args.Result;
  }
}

This code is pretty simple but we can use a lambda to avoid littering our code with unnecessary methods:

// Create the Client
GamesClient client = new GamesClient();

// Handle the event with a Lambda
client.GetGamesCompleted += (source, args) =>
{
  if (args.Error == null && !args.Cancelled)
  {
    theList.ItemsSource = args.Result;
  }
};

// Execute the Service Call
client.GetGamesAsync("Shooter");

Using the lambda (=>) creates an inline anonymous method for handling of the event.  Since this will only be used by our client and the client is short-lived (see issues with anonymous methods and long-lived objects here), this works well to simplify the code. 

This code becomes more difficult if you have to pass it data as developers tend to move that data to instance level (e.g. class level) variables to share it with the resulting code.  In other places (like AsyncCallback objects), they allow you to pass in a payload of data.  But this ends up with pretty ugly code.  For example, lets use the HttpRequest style of this same code;

// Interface to the HttpWebRequest-style interface
Games request = new GamesClient() as Games;

// Make the request
request.BeginGetGames("Shooter",
                      new AsyncCallback(OnGetGamesComplete), 
                      request);

In this style of the request, you would use a AsyncCallback to specify a method to callback and then pass in some state (in this case the request we made so we can use it in the callback. This results in the callback having to do some casting to get our object back;

void OnGetGamesComplete(IAsyncResult result)
{
  // Cast the passed in state
  Games theRequest = (Games)result.AsyncState;

  // Get the games
  IEnumerable games = theRequest.EndGetGames(result);
}

This grabbing of the state always annoyed me, but I figured it was necessary.  Or is it.  In this case our use of a lambda allows us to use a feature called closures.  With closures you can see local variables declared outside the anonymous method inside the method. For example:

// Interface to the HttpWebRequest-style interface
Games request = new GamesClient() as Games;

// Make the request
request.BeginGetGames("Shooter",
  new AsyncCallback(
    (result) =>
      {
        // Get the results
        IEnumerable<Game> games = request.EndGetGames(result);
      }
    ), null);

In this example we can use the request object create outside the anonymous method because the closure allows this.  This really simplifies the code. In fact, since the HttpRequest style is called on a non-UI thread, we can nest the lambdas and closures to call to the UI thread (using the Dispatcher, see my post on that here):

// Interface to the HttpWebRequest-style interface
Games request = new GamesClient() as Games;

// Make the request
request.BeginGetGames("Shooter",
  new AsyncCallback(
    (result) =>
      {
        // Get the results
        IEnumerable<Game> games = request.EndGetGames(result);

        // Use another Lambda and closure to update the list on the UI thread!
        Dispatcher.BeginInvoke( 
          () =>
            {
              theList.ItemsSource = games.ToList();
            }
          );
      }
    ), null);

Hopefully, this will help you in using the asynchronous model that is required in Silverlight 2. Note that this is the same as it is for non-Silverlight projects, but I find it really useful for students that have not had the opportunity to do asynchronous communication in their desktop applications.

You can download the code and play with it yourself.  Each of these methods are show in the project's page.xaml.cs file (see the #defines at the top of the file to switch between different versions):

AsynchronousClosures.zip

Silverlight Tour Now includes Coverage of the Silverlight Toolkit

Silverlight Logo

We are proud to announce that starting with our January 5th class, the Silverlight Tour will now cover the Silverlight Toolkit. This coverage will include examples of using the "Stable" band controls as well as charting and theme support.

This is the last big change to the Silverlight Tour before we start teaching our new Silverlight 3 when it is announced. Keep an eye here for news about changes coming in the next version of Silverlight!

The Silverlight Tour is a three-day workshop covering the basics of design and development on the Silverlight platform including XAML, managed code, control development, data access and server interactions.

The Silverlight Tour is coming to Paris!

Silverlight Logo

Our partners at RunAtServer Consulting are coming to Paris to teach the Silverlight Tour (en français) this January 19th-21st. If you have been waiting for a French-speaking stop in Europe, this is your chance to learn Silverlight 2 from soup to nuts!

ADO.NET Data Services for Multiple Databases?

Silverlight Logo

This all started with an innocent question by Bob Archer on Twitter. Bob wondered whether he could use ADO.NET Data Services in an application that was being touted as "Software as a Service" (SaaS). His concern was the apparent hard wiring of the Data Source in the DataService definition. This design might assume that you had to connect to a single database for all requests.

In his case, the Entity Framework metadata was the same but the connection string might choose a different physical server and database name. I thought that it shouldn't be too difficult. My first attempt to help him was to suggest interceptors for every entity type and manually change the database string based on some data in the request. This felt hacky so I asked Pablo Castro (at Microsoft) for some advice on the problem. He of course had the solution.

The solution was to override the protected CreateDataSource method on the Service. This method is called during each request to create the Data Source. This happens in the pipeline after the request information has been parsed so you can use request parameters to decide what Data Source to create.  You still need to return a Data Source that is the same type as the generic parameter but this means you can determine how to create the object. For example:

public class ProductService : DataService<ProductEntities>
{
  // ...

  protected override ProductEntities CreateDataSource()
  {
    HttpRequest req = HttpContext.Current.Request;

    if (req.IsAuthenticated)
    {
      return new ProductEntities("Authenticated DB Connection String");
    }
    else
    {
      return new ProductEntities("Anonymous DB Connection String");
    }
  }

}

This sample shows that you would need to return a ProductEntities data source, but you can determine how the creation of the data source happens. In the case of how ADO.NET Data Services works, this is called on each and every request separately and not cached so you can safely create a data source based on your current request as shown above.  Thanks Pablo, you made me look good again!

SDN Conference - Demo Code

Silverlight Logo

I just finished up with my four talks at the SDN Conference outside of Amsterdam and I had a great time. For anyone who missed it, you missed a great time. Amsterdam 026

I had four sessions ranging from cloud computing to Silverlight 2. For the attendees I wanted to give you a chance to download the demo source code I wrote for the sessions.  You can find it here:

If you have any questions, drop me a line.

Silverlight and ADO.NET Data Service Operations

Silverlight Logo

In building my Silverlight RC example using ADO.NET Data Services for Entity Framework and NHibernate I ran into what I think is a common pattern.  I am writing an editor for XBox game data. The model for this data uses decorator tables in the database which are modeled as a common "Product" class and derived "Game", "Console" and "Accessory" classes.  In the application I am using paging to only look at fifty results at once. This works fine on both sides. 

But one of the pieces of information I wanted was a list of all the Game Genre.  This became problematic as ADO.NET Data Services wanted me to retrieve all 880 games in order to get a list of these Genres (of which there are only 20 some odd). The whole idea of using paging is go avoid the huge overhead of bringing down the whole entity. Interestingly when I executed a LINQ query that used projection into non-entities, the query wasn't supported as projection isn't allowed in the ADO.NET Data Services URI model (which the client uses).

What ADO.NET Data Services does allow is to create Service Operations (e.g. WebGet or WebInvoke) on the Data Service to extend the model for specific cases. There are some limitations (must return IEnumerable<T>, IQueryable<T> or void) but this works pretty well. The difference between returning IEnumerable and IQueryable is whether system queries can be applied to them.  Returning a fixed list (my need) meant to return a IEnumerable<T> list. Intersting that ADO.NET Data Services support returning an IEnumerable<T> of primitive types.  For example my operation was spec'd as:

[WebGet]
public IEnumerable<string> Genres()
{
}

This works and returns a simple XML file with the primitive values.  But alas the Silverlight Data Service Client doesn't support non-entities. I tried using the DataServiceContext.BeginExecute() to call this service and it threw an exception that it couldn't materialize non-entity classes. Hrmph!

This was a case where adding a quick web service call to get this data on the server and return it would have been the easy road, but that's not how I roll, is it?

After confirming this behavior with the Data team, I decided to write an extension to the DataServiceContext class to support this.  In this little piece of code, the same pattern of calling DataServiceContext.BeginXXX is used. To make this work I simply use the HttpWebRequest class to do a simple GET to the server's URI syntax and use LINQ to XML to convert the data into the simple types (String in my case).

I've started to help out with some new ideas on the CodePlex SilverlightContrib project so I thought this was the perfect place for this code.  Its not packaged up yet in a build (and probably won't be until sometime after RTW ships) but if you want to grab it you can grab the latest checkin I made:

SilverlightContrib ChangeSet 41005

I'll be shipping this new demo as soon as RTW ships (its not done yet). Look for the announcement here.

Silverlight.js Fix for Firefox 3 + Silverlight 1.0 Woes

Silverlight Logo

If you deployed a Silverlight 1.0 application and are having trouble with it working well in Firefox 3.0, Tim Heuer has a fix for you. The fix is to replace the Silverlight.js from the Silverlight 2 SDK with the old 1.0 one. Its a little more elaborate than just that, and go to Tim's blog entry to read about how it works. 

Silverlight and Line of Business Applications

Silverlight Logo

In case you didn't catch it, I participated in a webcast called geekSpeak.  This webcast was hosted by Glen Gordon and Chad Brooks. The topic today was "Silverlight and Line of Business Applications". While geekSpeak's usually focus on hands-on examples of creating code, we took a different tact today and discussed the larger topic of where Silverlight fits in the development ecosystem (at least Microsoft's ecosystem).

For my money, the real benefit in Silverlight is for applications that cross the firewall. This means Line of Business applicaitons are really for B2B and B2C solutions. Unfortunately, what I hear from the community is that people see Silverlight as a solution for porting their desktop and traditional 3-tier applications to the web. Is this a good idea? I don't think so. The problem is that desktop development usually involves business objects that tend to have a direct connection to the database. Moving these sorts of applicaitons to the web means that you need to create an extra layer of communications and serialization. There is a cost both in development and performance for these extra layers.

It comes down to a key question...why are you moving to a web model for your application? If you want to expand the reach of your application to more users and clients (outside your organization), Silverlight is still a great story.  Unfortunately many organizations see web applications as a deployment solution. No install, no framework, etc.  While clearly this isn't true for Silverlight per se, its also a bad reason to go to a web application. Technlogies like Click-Once and XBAP are a great solution for a better deployment story than traditional desktop applications.

Since I brought up XBAP, let's plug it a bit. I notice that even amongst WPF guys, XBAP is a lost story. If you're not familiar with it, essentially its an in-the-browser WPF applicaitons that is deployed via manifest files (e.g. like ClickOnce). This means you can have the richness of UI, the better data binding story and interactivity that WPF/XAML affords you without having to deal with the limitations of Silverlight. I suggest that many organizations that want to use Silverlight for internal applications (inside the firewall) should be doing XBAP instead.

So what about ASP.NET/AJAX? The big story here is that HTML-based interfaces still have the longest reach of all the Internet enabled applications. HTML just works on many more platforms and browsers than Silverlight or Flash. Before you commit to moving away from HTML-based UI's, spend some time with your server logs.  Understand who is really using your existing application before you leave anyone in the dust. A better strategy is often to include fall-back functionality. For example, in my Silverlight Tour website (http://www.silverlight-tour.com), I decided that developers may have Silverlight installed so I wanted to give them a better experience by showing an interactive map of tour stops. But their bosses and accounting departments were unlikely to have it installed. In that case I made a design decision to never prompt to install Silverlight, but instead if it wasn't installed to show a simple table of the classes instead of the Silverlight app. This is a great solution to moving forward without leaving old users in the dust.

Why is Silverlight not a good solution inside the firewall? The two issues are infrastructure and security. In order to build solid line-of-business solutions with Silverlight, you need to have a way to communicate data with the server. Building this infrastructure can be labor intensive, but more importantly adds complexity. More moving parts == more than can go wrong. Security is the second issue. Silverlight (for good reason) is pretty locked down. This means you will need to often learn to work in tighter confines (limited access to storage, no access to file system, registry, ports). If your application is meant to work in trusted scenarios (e.g. Integrated Windows Authentication), the limitations of the high-security environment will be a real limiter.

So what does this all mean? I still think Silverlight is still the solution when you need to *extend* the HTML model in the browser. Line of Business applications across the firewall still need to be web driven in my opinion, but enhancing that story with Silverlight for soutions like data visualization, user interactivity or media is a great solution. While I think that creating whole-browser solutions make sense for some applications, it doesn't for many many more. My fear is that we will move from monolithic desktop apps to monolithic Silverlight apps.  The web is still a disconnected model and deciding on building a single huge Silverlight app (instead of page-based functionality) just doesn't make much sense. If you are planning on building one of these monstrocities, please also read my recent blog about linkability in Silverlight:

http://wildermuth.com/2008/06/25/Doesn_t_Anyone_Bookmark_Anymore.aspx

Doesn't Anyone Bookmark Anymore?

Silverlight Logo

When I teach Silverlight 2, I stress an important lesson that I thought that we (as developers) had learned the importance of linkability of the web. Early usage of Flash was the first time I noticed this. A number of those sites would create nested functionality that never changed the URL.  If the URL doesn't change, i can't bookmark it. Most Flash guys learned their lessons pretty quick, but now I am inundated with AJAX driven sites that try hard to not to do post-backs.  That's cool, but if the URL doesn't change I can't link to it.

I've noticed this happening a lot with support sites. The first time I saw with an AJAX site was using the Intersoft's Developer Portal (http://www.intersoftpt.com).  They treat the developer to a desktop-like experience, but if I can't send a link to my other developers for the latest patch, why bother making it on the web?

The latest is the game Spore's forums. Trying to help a friend figure out why its crashing, I found some good posts on workarounds but the site's address is always http://www.spore.com/forum.  What's the point?

This post is a request...a pleading...begging even. Think about the usability of your sites. If it lives on the Internet, it should be linkable.  Now if your site doesn't have state, this doesn't apply to you, but for the other 99.999% of the sites out there, don't get too caught up in the frenzy of AJAX or RIA to make your sites usable. The reality is that you can do this with Silverlight, Flash, AJAX or any web page. It might be more work, but the level of frustration for users is well worth your time.

(NOTE: Microsoft is working on a new version of their AJAX toolkit to enable URL changes during partial page updates.  This will help some of you, but the rest of you will still need to do some of the hard work yourselves.)

Adam Kinney has a new SIlverlight-based XBox Gamercard

Silverlight Logo

Adam Kinney has created a new Silverlight 2 Application to show off your XBox Gamercard on your site.  I like his design and it is not static so it shows what you're doing at any specific time.  What do you think of mine:

Get Microsoft Silverlight

Do you like?