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.

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

[18 Jun 2009 | 2 Comments]

Welcome to the first in a series of RIA Services How-To's.  Unless mentioned otherwise, all these tidbits will use the latest drop of RIA Services (at the moment, this is the May 2009 drop).  When new drops arrive, changes may have to be made, inherent to beta software. 

 

But, first things first: how do you start using RIA Services?

 

Step 1:  getting started

 

Start a new Silverlight-project.  Assuming you've installed everything correctly (I'm using the May drop of RIA Services, SL3 beta, VS2008 SP1), you'll notice a new checkbox, "Link to ASP .NET server project".

 

image

 

If you check this checkbox, RIA Services will be enabled.  You'll end up with 2 projects as usual: your Silverlight-app, and a webapp hosting this Silverlight-app.  You'll notice extra references added to your project to enable RIA Services. 

 

Tip: you can enable or disable this ability later on, by looking at the project properties of your SL app: you'll notice a combobox, ASP .NET Server Project Link.  Here, you can select the webproject you'll want to link to to use RIA Services.  This effectively means you can enable RIA Services on existing applications, simply by selecting a webproject from your solution.

 

Step 2: your datastore

 

You'll need to add some kind of datastore to your webapp.  It doesn't really matter what kind of store this is: it can be an Entity Framework model, but might as well be some simple POCO classes with dummy data.  The client (your SL-app) doesn't need to know what kind of datastore you have - it's totally unaware of this.  I've installed the Lite version of the AdventureWorks-DB, and will use a few tables from it.  So, I right-click my webapp and choose to add a new ADO .NET Entity Model, and select the Customer and CustomerAddress tables from AdventureWorksLT.  I end up with something looking like this:

 

image

Step 3: expose your data

 

Here's where the magic begins! ;-) You need to expose your data to your SL-app.  To do this, you need to create a DomainService.  This is a new class, with which RIA Services will take care of sharing your data/methods across tiers.  To add one, right-click your webapp -> add new item -> Domain Service Class.  Give it a name, and you'll see a screen looking like this:

 

image

 

Of course, you need to check "Enable client access".  :-)  Next, select the datacontext you wish to expose.  In this example, it's the AdventureWorksLT-model I created in the previous step.  Now, you can select which enitities you want to add to your Domain Service.  For each entity you select, methods will automatically be generated to read data from your datastore, and if you check "Enable editing", subsequent insert, update and delete-methods will be generated. 

 

Tip: if you don't see your datacontext in the dropdownlist, build your application before adding the domain service class.

 

Last but not least, you can also check "Generate associated classes for metadata".  When this is checked, a metadata-class will be generated, allowing you to do stuff like validation accross tiers, define how your data should look when using a dataform, ...  I always check this option (do you know a lot of apps that don't require validation or don't require the need do define how your data should look? ;-)), but I'll go into detail on that in a future post.

 

Now, click "OK", and... magic! Visual Studio will start generating lots of code.  On your webapp-side, you'll see your DomainService-class.  It contains all the necessary CRUD-methods (GetCustomer, InsertCustomer, ...).  You can add methods to this class, or change the existing methods as needed: this is the place where you'd put your application logic:

 

image

 

Now, build your solution.  If you check "click all files" on your Silverlight-app, you'll notice a new folder, called, "GeneratedCode".  This is essentially the client-side, generated code that corresponds with the server-side methods.  It contains client-side versions of the classes (entities) you've exposed through your DomainService-class. It also contains a DomainContext, which is the client-side representation of your server-side DomainService.  Through this context, you can access all the functionality of your domain service.  You'll also notice the DomainContext containing Load-methods for your entity-lists.

 

image

Tip: the names of these methods are automatically generated - by default, an entity "Customer" will have a "GetCustomer"-method server-side, and a "LoadCustomer"-method client-side.  If you want to choose what name the generated client-side method must have, you can use the [Query]-attribute.  Check my previous post for more info on that.

 

Step 4: accessing your data from your SL-app

 

All necessary code has been generated, so now you need to access this data from your Silverlight-application.  As I explained, on your client, Load-methods have been generated (methods like this will be generated for every method you write in your server-side domain service class which returns an IQueryable list).  First, you need to instantiate your client-side generated DomainContext.  You'll notice that that instance contains the generated Load-Methods, and also collections of your entities (eg: the Customers-property is actually an EntityList of Customer):

 

image

 

Now, you want to call the client-side LoadCustomer-method to load the customers.  When this statement is executed, the GetCustomer-method on your server-side DomainService will be executed.

 

image

 

To display the data you've got in your app, bind it to, for example, a datagrid.  You'll end up with something looking like this:

 

image

 

And you're done! ;-) As you'll notice, you've also got events on your DomainContext like Loaded / Loading / PropertyChanged: you can add Event Handlers to these as needed.

 

Step 5: adding, deleting, updating your data

 

Next steps are of course deleting, adding, updating, ... your data.  This is actually quite simple: what you need to do is manipulate the EntityLists you've got in the DomainContext on your client side: Customers, for example.  Add elements, update elements or delete elements from that list.  Now, your DomainContext instance has a method called SubmitChanges & RejectChanges.  As you might have guessed by now, executing the SubmitChanges-method will persist the changes you've made on the collections to your database (it will call the corresponding server-side methods for this automatically).  RejectChanges, well, rejects your changes ;-)  There is, of course, much & much more to this - you can work with transactions, changesets, check for changes, et cetera - more on that in one of the next articles. 

 

That's it! This article should've covered the basics of working with RIA Services.  I hope this helps some of you out - check back regularly for more! ;-)

 

A word of advice: RIA Services is beta-software, and lots of code gets generated automatically.  In most scenario's, you'd want to split your Domain Services into another namespace (or even assembly).  However: this doesn't really work as you'd expect at the moment of writing.  You'll notice code generation going bonkers when trying this, so for now: just keep everything in the same namespace.  I assume (hope ;)) this will be fixed in future drops.

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

[15 Jun 2009 | 0 Comments]

First of all, welcome to a completely new blog-look! :-) 

 

The last few weeks, I've been playing around with RIA Services (for Silverlight 3), which "simplifies the traditional n-tier application pattern by bringing together the ASP.NET and Silverlight platforms. The RIA Services provides a pattern to write application logic that runs on the mid-tier and controls access to data for queries, changes and custom operations. It also provides end-to-end support for common tasks such as data validation, authentication and roles by integrating with Silverlight components on the client and ASP.NET on the mid-tier." (uhm, yeah, I borrowed that part from Brad Abrams  ;-)).

 

To clarify this a bit: we're all used to writing service-oriented SL-apps.  Typically, you'd have a webservice or WCF-service residing somewhere, and you'd use the "Add Service Reference"-option in Visual Studio or a WebClient to get your data.  I actually like that approach, but it's a fact that most people are used to working in a typical n-tier environment (just check the numerous posts on the Silverlight .NET forums asking about how to convert an existing n-tier app to a Silverlight app, or about strategies to get data into a Silverlight-app). 

 

Well, RIA Services bridge this gap; you're still working service-oriented, but it looks and feels different - it feels more as if you were programming in a typical n-tier architecture.  On top of that, it offers easy validation & authentication, and useful client-side controls like the DomainDataSource with built-in sorting, filtering, ... capabilities.  And I'm actually starting to like this as well :-)

 

How do you get started with all this?  You'll need Visual Studio 2008 SP1, Silverlight 3 & the last drop (at the moment of writing, this is the May drop) of the services.  All downloads can be found at Silverlight .NET, as well as a few good tutorials.  For an in-depth view, I'd suggest having a look at the released documentation, which can be found on MSDN's download page.  It's pretty big (about 116 pages), but it covers a lot of what RIA Services have to offer.  You can also find official sample applications here.  Don't want to read through all the documentation?  Well, I found Martin Mihaylov's tutorials at SilverlightShow.NET very useful, you might want to check 'em out!

 

Or... you might want to come back to this site every few days :-)  In the next few days, I'm going to start adding posts about these RIA Services and what you can do with 'em - such as paging, sorting, validation, authentication & authorization, how to submit changes or even changesets, ...  These will come in simple & to the point "How do I ...?"-format, for easy reference afterwards (for myself, and hopefully for you as well ;-)).  So stay tuned!

 

So what about that "something you might not yet know" I mentioned in the title?  Well, from the moment you start working with RIA Services, you'll notice that it automatically generates Load-methods on the client for the Get-methods you have on your server.  Eg: if you've got a GetCustomer-method on your server (which returns an IQueryable<Customer>), a LoadCustomer-method will automatically be generated on your client.  But what if you don't like that prefix?  I kind of like my methods to have the same name across different layers (tends to avoid confusion).  Good thing is, RIA Services is very customizable in the way it generates code - typically by decorating your code with a few attributes, you can control the code that's generated client-side.  To make sure the client-side method will have the same name as your server-side method, use the following attribute:

 

   1: [Query(PreserveName = true)]


   2: public IQueryable<Customer> GetCustomer()


   3: {


   4:     return this.Context.Customer.OrderBy(c => c.CompanyName);


   5: }


 

 

From now on, GetCustomer will still be called GetCustomer on your client.  Nice & easy :-)