Silverlight »

[9 Sep 2009 | 0 Comments]

As mentioned on Joe Stegman’s blog, Tim Heuer and Scott Barnes have established a feature tracker for new features we’d like to see in Silverlight 4.  The whole community can now vote for the features they’d like best on the Silverlight Feedback Forum

 

So if there’s a feature you’d really like to see in Silverlight 4, here’s your chance to let the team working on it know!  If you happen to feel like doing me a favour: vote for commanding support, please ;-)  A few other features I voted for: printing support, webcam support & Sillverlight for iPhone (or better, mobile in general).

 

What are your picks?  Let them know!

 

General, RealDolmen, RIA, Silverlight »

[7 Sep 2009 | 0 Comments]

A while ago, my company decided to launch a new marketing campaign, showing of some of the things we’ve done in the past.  To accompany this campaign, we decided to design a showcase site.  This showcase site shows of a whole lot of customer cases, technology flyers, solutions sheets, … in short: technologies and solutions we offer to our customers. 

 

We wanted this site to leave an immediate impression on everyone who visits it – and what better way to do that than by using Silverlight to build it, right? :-)

 

image

My team worked hard on building this site, and I hope you’ll like what we’ve come up with.  To have a look, point your browsers at http://www.realdolmen.com/customercases/!

 

From a technical point of view, some points of interest:

  • Silverlight 3 site (frontend & backend)
  • RIA Services & Entity Framework ORM
  • Indexability by search engines was very important to us, so we’ve incorporated some SEO techniques
  • Deep linking support
  • Custom designed “Rich Text Viewer” (and editor in the backend SL app) –> the details view markup you see when you select a case is actually generated on the fly from an XML-file!

General, WCF RIA Services, BESUG, Drag and Drop Manager »

[7 Sep 2009 | 0 Comments]

So, the holiday season is over for most of us, I hope everyone had a nice few weeks off – I know I had :-) 

 

Time to get back on track!  Quite a few things are coming up in the next days/weeks/months: a new version of the Silverlight Drag and Drop Manager is coming up (watch this space!), and one of my projects @ work is going live – it’s a showcase site, built completely in Silverlight 3; I’ll share the URL shortly.

 

Next to that, my company is hosting a session I’m doing for BESUG, the Belgian Silverlight User Group shortly, about Silverlight 3 & RIA Services.  If you’d like to be at this session, click here to register.  I’ll share the slides & code on this blog after the session.

 

And last but not least, I’m continuing work on a Silverlight book (more details later) I’m writing together with a collegue, Gill Cleeren.

 

I tend to post updates concerning these things on Twitter, so if you’d like to, you can follow me here (@KevinDockx).

 

To sum it all up: lots of work to do, guess I won’t have time to get bored the next few months ;-)

Silverlight, .NET, WCF RIA Services, RIA, WCF »

[24 Jul 2009 | 0 Comments]

When working with RIA Services, a lot of your code is generated automatically, but you'll still need to write quite a lot of custom methods and you'd typically write them in your DomainService-class.  But what if you add an Entity to your datastore?  What if you want to add some CUD-operations next to the read-operation that's been generated?  Either you'd have to write the Entity-classes and methods manually (a lot of work for something that could be generated), or you'd have to delete your DomainService and re-add it (so the newly added Entities/Queries get generated), but then you'd lose all the custom methods you've written in your DomainService...

 

Bummer, huh?  Well, luckily, there's a nice workaround for this!  Imagine you've written a DomainService filled with custom queries, ServiceOperations, ..., working on an Entity Framework domain model.  All of a sudden, a table has to be added to your domain model, so you need to regenerate your DomainService: delete and re-add, thereby losing your custom methods.  It would be nice if you could just put your custom methods in a seperate file, so deleting the DomainService wouldn't delete those methods.  And you can!  The magic word here?  Partial classes!

 

As an example, I've changed my demo-app around a bit: it now only shows the customers beginning with a certain string.  To get this behaviour, I've added a new query method, GetCustomersByFirstLetters, which accepts a string.  I'm passing this as a query to my LoadOperation when loading the items for my DataGrid:

 

   1: LoadOperation<Customer> loCustomer = CDC.Load(CDC.GetCustomersByFirstLettersQuery("a"));


 

But, instead of adding this custom method to the CustomerDomainService.cs-file, I've created a new file, and named it CustomerDomainService.partial.cs.  In this file, I define a class like this, and add my new method to it:

 



   1: public partial class CustomerDomainService : LinqToEntitiesDomainService<AdventureWorksLTEntities>


   2: {


   3:     public IQueryable<Customer> GetCustomersByFirstLetters(string firstLetters)


   4:     {


   5:         return this.Context.Customer.Where(c => c.CompanyName.StartsWith(firstLetters));


   6:     }


   7: }


 

Notice the "partial" keyword? Now, in my original CustomerDomainService.cs-file, I've also changed the class signature to include the "partial" keyword.

 



   1: [EnableClientAccess()]


   2:     public partial class CustomerDomainService : LinqToEntitiesDomainService<AdventureWorksLTEntities>


 

When you build and run this, you'll see the app behaves just as you'd expect it to - but thanks to the fact that the custom method is now in a separate file, you'll no longer lose it in case you have to recreate your DomainService.  All you have to remember is to add the "partial" keyword to the class definition of your generated DomainService, and you're done! :-)

 

What has happened here?  Well, the "partial" keyword actually tells .NET that your class has been split over multiple class definitions/files.  When you build your app, the compiler will combine all the "partial"-classes with the same signature into one class, just as if they were defined in the same file.

 

I'm pretty sure the need for deleting & recreating your DomainService will be fixed in one of the next drops (after all, the "Update from Database"-option didn't exist in the first versions of the Entity Framework either), but until then, this should be quite a handy tip.  Enjoy! :-)

 

Adjusted sourcecode has been posted here if you'd want it.

Silverlight, .NET, WCF RIA Services, RIA, WCF »

[23 Jul 2009 | 1 Comments]

Since the previous part in this series, the final version of Silverlight 3 has been released, and a new version of RIA Services has been released: the July 2009 drop.  This release includes quite a few changes, so I had to change my demo source code around quite a bit to make it work with the new release.  This post details the changes that have been made - and a new sourcecode download is included as well! :-)

 

First of all, in the previous drop, you'd often bind to completed and/or submtted-handlers on your DomainContext.  This behaviour has been changed, together with the way loading is done.  Now, we'd typically use a LoadOperation<type> for this.  Eg, instead doing something like this:

   1: // init domaincontext, load customers


   2: context = new DomainService1();


   3: myDataGrid.ItemsSource = context.Customers;


   4: context.LoadCustomer();



which would automatically execute the GetCustomer method (and eventually bind a handler to the submitted-event), you'd now do something like this:




   1: CustomerDomainContext CDC = new CustomerDomainContext();


   2:  


   3: public MainPage()


   4: {


   5:     InitializeComponent();


   6:  


   7:     LoadOperation<Customer> loCustomer = CDC.Load(CDC.GetCustomerQuery());


   8:  


   9:     EventHandler handler = null;


  10:     handler = (send, args) =>


  11:         {


  12:             // do stuff after entities have been loaded


  13:             myDataGrid.ItemsSource = loCustomer.Entities;


  14:             loCustomer.Completed -= handler;


  15:         };


  16:     loCustomer.Completed += handler;


  17: }



(first thing you'll notice: I've used names that make sense now ;-))


What happens here is that the LoadOperation will now take care of executing a query (the one you pass in, an EntityQuery - these are automatically generated from your server side query methods) and thus filling its EntityCollection.  If you need to subscribe to said events, you can find 'em on the LoadOperation.  So: the LoadCustomer-method is no longer generated on your client.  Instead, a GetCustomerQuery-method is generated, which you now pass to a LoadOperation to make sure it gets executed.  This is actually quite a nice model to work with - for one, you can now check for each LoadOperations's completed event, instead of just checking the completed event on your full context!


Next to that, the demo solution also had a means of submitting changesets.  This, too, has been changed around.  Previously, submitting changes would call context.SubmitChanges().  Now, submitting changes on your context can return a SubmitOperation.  In this SubmitOperation, you can check if any errors have occurred, and you can execute some code you want to be executed after submit:




   1: private void btnSubmitChangeSet_Click(object sender, RoutedEventArgs e)


   2: {


   3:       if (!CDC.IsSubmitting)


   4:       {


   5:           if (CDC.HasChanges)


   6:           {


   7:               CDC.SubmitChanges(OnSubmitCompleted, null);


   8:           }


   9:       }


  10: }


  11:  


  12: private void OnSubmitCompleted(SubmitOperation so)


  13: {


  14:       EntityChangeSet currentChanges = CDC.Entities.GetChanges();


  15:       grdChanges.DataContext = currentChanges;


  16:  


  17:       if (so.HasError)


  18:       {


  19:           MessageBox.Show(so.Error.Message);


  20:       }


  21: }



As you can see, checking for changes is still possible by getting the EntityChangeSet from the context's GetChanges()-method.


New sourcecode has been uploaded, feel free to check it out. 

Silverlight, .NET, Silverlight Toolkit »

[9 Jul 2009 | 0 Comments]

Quick, short & to the point: Silverlight 3 has just been released!

 

Download links: runtime & dev tools.  (note: Scott Hanselman just twittered they're still in the process of uploading this to all sites - you might want to try again in a few hours if something doesn't work).

 

Next to that, Blend 3 including Sketchflow has also been released, get it from the Microsoft Download Center.

 

I guess the only thing left is RIA Services, July drop, right? :-)  Hope to see that one appear one of these days as well.

 

For now: happy coding! :-)

 

Update!

 

The July CTP of RIA Services has also been released, and a new version of the Silverlight Toolkit is available @ Codeplex as well. If you use any of these, make sure to download the new versions for use with Silverlight 3, as there are quite a few breaking changes.

 

So I guess that's all we need, now lets go forth and design great Silverlight applications ;-)

Silverlight, .NET, WCF RIA Services, RIA, WCF »

[4 Jul 2009 | 1 Comments]

In the first part of this series, I talked about some general concepts, and went into reading, updating, adding, deleting data using RIA Services.  If you haven't read it yet, you might want to read up on that, and maybe read up on the introductory post as well.

 

In this part, I'll talk about an interesting option you have when updating your data: the change set.

 

As some people asked for it, I've uploaded the sourcecode of my demo project.  This code will be updated with every new part in the series.  To use the demo code, you'll need to change the connection string for the Entity Model to your own local copy of the AdventureWorks SL database - once that's done, you're ready to go! :-)

 

As mentioned in the previous part, persisting your changes to the underlying datastore boils down to calling SubmitChanges() on your (clientside) DomainContext.  This will automatically make sure the correct server side methods (in the demo: InsertCustomer, UpdateCustomer or DeleteCustomer) are called for each of your entities. 

 

Then what is a change set?  A change set should be seen as a complete collection of all the changes you've made on your context, before having them submitted and thus persisted to your datastore.  This principle makes sure server-side methods don't have to be called every time you make a change to your data: the changes will be tracked client-side, and will be submitted once you explicitly call SubmitChanges() to persist your change set.

 

To visualize this, I've added a few things to the demo application.  To the right side of the datagrid, there's a grid which will track the changes.  This grid contains some textblocks, bound to the number of modified, added, removed entities, and it contains a reject & submit button:

 

image

 

Now, to track the changes, I need to get the changeset from my DomainContext.  I will do this in my datagrid's RowEditEnded-event (which gets fired right after I've edited a row), and this change set will be the datacontext of the grid used to track the changes:

 

image

 

As you can see, context.Entities.GetChanges() returns an EntityChangeSet.  This object contains a list of changes, divided into different lists for AddedEntities, ModifiedEntities, ...  (I've also added a way to delete items from the datagrid, have a look at the source code for that.) 

 

So, now we've got a list of changes, and thanks to some databinding, these changes are automatically reflected in our UI.  Now, we need to submit or reject this change set.

 

Rejecting changes is easy: just execute RejectChanges() on your context, and every change you've made that hasn't been submitted yet will be undone.  To submit your changes, call the SubmitChanges()-method on your context:

 

image

 

There is, of course, more to it than just that.  When you submit your changes, a few things will happen.  This is what will be done on your DomainService after you've called that command (copy/paste from the RIA Services documentation):

1. Submit – the service entry point that receives the changeset and begins the changeset processing pipeline
2. AuthorizeChangeSet – Verifies Permission/Authorization for each operation. If any operations are not permitted, processing stops and an error is returned to the client
3. ValidateChangeSet – Validation for all operations in the changeset is run. If any operations fail validation, processing stops and errors are returned to the client
4. ExecuteChangeSet – The corresponding method for each operation in the changeset is invoked. This is the point in time when your business logic is run. If any operations failed, processing stops and errors are returned to the client
5. PersistChangeSet – At this point all the domain operations have been executed, and this method is called to finalize the changes.
6. ResolveChangeSet – If there were any optimistic concurrency errors, this method is called to resolve them.

 

All these methods are virtual, so they can be overridden as needed!  As you can see, a few things can go wrong (eg, something isn't valid, the necessary permissions aren't available, ...), so it's important to include error handling.  To do this, add an event handler to your context's Submitted-event:

image

 

By the way, this is not enough for correct, complete error handling.  For example, in this demo it's quite easy to change the ID of a customer to something that's not valid anymore - best way to solve this is, of course, make sure it's not editable (an internal ID is NOT something you'd want to be editable), or not visible.  But this does show that not all errors are caught: it isn't exactly a Conflict (used for concurrency) and it isn't exactly a a ValidationError (no validation exists on that field) either.  So while this specific example isn't something that would occur in real-life situations, it does show that it's important to put validation on your data where needed AND to include some more general error handling in your code.

 

But as far as change sets are concerned: you're done!  This is what change sets can mean for you - using them carefully will make sure you don't have unnecessary client-server-communication, and thanks to some databinding, you can easily track the changes in your UI. 

 

Stay tuned for the next update, in a few days! :-)

 

Sourcode download.