Be-Aware of differences in explicit and implicit deserialization with DCS

DataContractSerializer (DCS) is the class that is used by WCF to serialize and deserialize messages when you make service calls. It is also sometimes used on its own to read and write objects to a stream, such as inside the WinRT SuspensionManager class. It works great and is very powerful, even being able to handle circular references inside the object graph that you are serializing (such as a parent object having a collection of child objects inside a collection property, and each of the child objects having a parent object reference through a navigation property). The DCS supports several kinds of serialization: based on Serializable/ISerializable, explicit data contract (using [DataContract] and [DataMember] attributes), and implicit data contracts (public type with public properties).

Depending on your point of view and usage, sometimes it is better to use explicit data contracts and sometimes it is better/easier to use implicit data contracts. However, there is a subtle gotcha that you should be aware of in terms of the construction process of the objects when deserializing an implicit vs an explicit data contract.

When an object with implicit data contract on it (public type and public properties involved in the serialization/deserialization) is deserialized, everything happens as you would expect – a new object instance is created, the constructor is called, and it can do any initialization of members that it wants to.

When an object with explicit data contracts on it ([DataContract] on the type, [DataMember] on the properties involved in serialization/deserialization) is deserialized, the constructor does not get called. As a result, any initialization that the constructor normally does (such as initializing private member variables that do not participate in the deserialization) will not be done on deserialization. If you need to do some initialization on deserialization, you can use OnDeserializing/OnDeserialized hooks. That means if you have some common initialization that you want called both when explicitly constructed (new’ed up) and when deserialized, you need to factor that initialization into a helper method and call that from both places to avoid duplication of code.

To see this in action, consider the following two entity types:

   1: public class ImplicitContractEntity

   2: {

   3:     private string _someRefMember;

   4:     private string _someOtherRefMember = "Initialized";

   5:     public ImplicitContractEntity()

   6:     {

   7:         Console.WriteLine("Constructor of ImplicitContractEntity called");

   8:         _someRefMember = "InitializedName";

   9:     }

  10:  

  11:     public int Id { get; set; }

  12:     public string Name { get; set; }

  13:  

  14:     public string GetPrivateRefMember()

  15:     {

  16:         return _someRefMember;

  17:     }

  18:  

  19:     public string GetPrivateOtherRefMember()

  20:     {

  21:         return _someOtherRefMember;

  22:     }

  23:  

  24: }

  25:  

  26: [DataContract]

  27: public class ExplicitContractEntity

  28: {

  29:     private string _someRefMember;

  30:     private string _someOtherRefMember = "Initialized";

  31:     public ExplicitContractEntity()

  32:     {

  33:         Console.WriteLine("Constructor of ExplicitContractEntity called");

  34:         _someRefMember = "InitializedName";

  35:     }

  36:     [DataMember]

  37:     public int Id { get; set; }

  38:     [DataMember]

  39:     public string Name { get; set; }

  40:  

  41:     public string GetPrivateRefMember()

  42:     {

  43:         return _someRefMember;

  44:     }

  45:  

  46:     public string GetPrivateOtherRefMember()

  47:     {

  48:         return _someOtherRefMember;

  49:     }

  50: }

You can see that the first is an implicit data contract (no DataContract or DataMember, all public properties will be serialized) and the second has explicit data contracts. You can also see that they have exactly the same structure including:

- Inline initialization of one private member variable
- Constructor initialization of another private member variable
- Console output when constructor is called
- Accessor functions for the private member variables

Now lets look at some code that serializes and deserializes these types with DCS:

   1: static void Main(string[] args)

   2: {

   3:     Console.WriteLine("Constructing initial entities");

   4:     ExplicitContractEntity expEntity = new ExplicitContractEntity { Id = 42, Name = "Fred" };

   5:     ImplicitContractEntity impEntity = new ImplicitContractEntity { Id = 43, Name = "Wilma" };

   6:     DataContractSerializer expSerializer = new DataContractSerializer(expEntity.GetType());

   7:     DataContractSerializer impSerializer = new DataContractSerializer(impEntity.GetType());

   8:     Console.WriteLine();

   9:     using (MemoryStream expStream = new MemoryStream())

  10:     {

  11:         expSerializer.WriteObject(expStream, expEntity);

  12:         expStream.Position = 0;

  13:         Console.WriteLine("Deserializing explicit contract entity.");

  14:         ExplicitContractEntity deserializedExpEntity = 

  15:             expSerializer.ReadObject(expStream) as ExplicitContractEntity;

  16:  

  17:         if (deserializedExpEntity.GetPrivateRefMember() == null)

  18:             Console.WriteLine("Explicit contract private member null");

  19:         if (deserializedExpEntity.GetPrivateOtherRefMember() == null)

  20:             Console.WriteLine("Explicit contract other private member null");

  21:     }

  22:     Console.WriteLine();

  23:     using (MemoryStream impStream = new MemoryStream())

  24:     {

  25:         impSerializer.WriteObject(impStream, impEntity);

  26:         impStream.Position = 0;

  27:  

  28:         Console.WriteLine("Deserializing implicit contract entity.");

  29:  

  30:         ImplicitContractEntity deserializedImpEntity =

  31:             impSerializer.ReadObject(impStream) as ImplicitContractEntity;

  32:  

  33:         if (deserializedImpEntity.GetPrivateRefMember() == null)

  34:             Console.WriteLine("Implicit contract private member null");

  35:         if (deserializedImpEntity.GetPrivateOtherRefMember() == null)

  36:             Console.WriteLine("Implicit contract other private member null");

  37:     }

  38:     Console.WriteLine("Hit any key to exit");

  39:     Console.ReadKey();

  40: }

As you can see it first constructs an instance of each entity type, then it serializes and deserializes each, with some console output along the way to indicate the stages and to check whether the deserialized version of the objects has null values in its private member variables (through the accessor functions).

The console output proves the difference in lifetime:

2014-09-29_10-06-02

Notice that the constructor of the ExplicitContractEntity does not get called during the deserialization, but the ImplicitContractEntity constructor does, and as a result both the inline initialized variable and the one initialized in the constructor are null in the ExplicitContractEntity after deserialization whereas the ImplicitContractEntity ones are intact.

So the bottom line?

1. Be aware of the differences in construction / initialization between the two kinds of data contract

2. Be very careful about going and changing code that was using implicit data contracts to start using explicit data contracts. It is too easy to forget or to miss that things that were happening in the constructor during deserialization before are going to stop being called as soon as you switch to explicit data contracts.

If you want to learn more about the fundamentals of WCF, please check out my WCF Jumpstart course on Pluralsight.

You can download the full source code for this article here.

Comments Off

NYC Code Camp Slides and Demos

Had a great time speaking at the NYC Code Camp this weekend at the Microsoft Offices in Times Square. For those that attended or others who just want the goods, below are the slides and demos I presented there.

Build Data-Centric HTML5 Client Apps with Breeze:   Slides   Demos

AngularJS JumpStart:   Slides   Demos

Enjoy!

Two Weeks a Windows Phone User

So I decided to make the switch from iPhone to Windows Phone a couple weeks ago, and thought I would share my experiences after two weeks on the platform. Thanks to Nick Landry (@ActiveNick) for giving me the final nudge I needed to make the switch.

This is actually my third try making the switch, but it is going much better than the first two. The very first was when Windows Phone first came out. Back then the platform was pretty raw and there simply were not enough apps. Second try was in the Windows Phone 7.5 days… again, still not enough of the right apps in comparison to iOS at the time even though the platform had matured a lot. This time, overall, I am extremely happy with the platform as a whole and with the apps available. In fact, I would say that a lot of the same apps that I use on my iPhone have a better overall user experience on Windows Phone than on iPhone.

Overall impressions of Windows Phone in general:

  • User experience of the platform (operating system) and apps following the platform design guidelines is way better than iOS. The fluidity of moving from app to app and navigating around within apps and phone level settings and features is awesome. Feels much more modern and well thought out than iOS.
  • Built in apps are great (People hub, news, music, video, photos)
  • Most importantly, every major app I used on the iPhone is available on Windows Phone and most are feature complete in comparison. Some lack minor features and that gets a little annoying (ex: Amazon Kindle allows you to change font size and color on Windows Phone, but lacks the ability to change the font to a different one – i.e. sans serif – whereas the iOS one does allow that), but that is not Microsoft’s fault, just need to put pressure on the app vendors to get feature parity. But all the major apps I use regularly (Pandora, Kindle, WeatherBug, Netflix, Vevo, TripIt, Twitter, Facebook, United, …) are all there and work great.
  • There are also a lot of really great apps just for Windows Phone that I did not use or do not exist on iOS. MetroMail, Nokia apps (Camera, MixRadio, HERE Drive, HERE Maps)
  • Initially my biggest point of frustration as a Gmail user was email, but then I discovered MetroMail (thanks Khaled @ImmortalFeb) and my Gmail life is now complete again on Windows Phone with full labeling and archiving capabilities.

In terms of what hardware I have, I started out with a Lumia 635 because I am an AT&T user and that was the best handset they had that was similar form factor to my iPhone 5s. The overall user experience with that phone was really good, but the stats on it are fairly low end and I was wanting to try a phablet with some more horsepower and screen real estate, so I traded it in for a Lumia 1520 after the first few days.

  • Overall impressions of the Lumia 1520:
    Fantastic performance
  • Great screen, having the extra real estate is wonderful for most things I do on the phone while stationary
  • Excellent camera
  • Long battery life
  • A little hard to use single handed. My hands are not large. My ability to hold in my right hand and navigate with just my thumb is severely diminished, particularly on the go.
  • One big negative: button placement. This is a BIG phone. That means you have to grip it a bit more explicitly than you would a smaller phone to control it. Where do you grip a phone? On the middle to lower sides of it. Where did they put the lock button and camera button? On the middle and lower side of it on the right side. Stupid, stupid positioning in my opinion. Biggest thing I dislike about the phone so far. Constantly accidentally lock the screen when I am reading something or turning on the camera app. The top and bottom have no buttons at all, why could they have not put the lock button on the top where it would have been out of the way and maybe put the camera button upper left?

So overall, I’m very happy with Windows Phone and will probably stick with it this time. I’m keeping my iPhone around for now on another line for development purposes, but find myself missing it very little. The only iOS features I do miss at times are:

  • iMessage – I have a MacBook Pro and iPad and loved the integrated texting across all my devices. But many friends are not on iOS, so could never do that with them anyway.
  • Find my iPhone – my wife and I use this to coordinate our location sometimes without needing to call and describe where we are at. Wish I could find something similar that worked across platforms (wife is not switching for now)
  • Thumbprint password on iPhone 5s. Very handy when mobile to just touch and hold to get past the lock screen.

Bottom line, if you are not already a dedicated iOS or Android user, you will love Windows Phone. Even if you are, you will probably love Windows Phone after getting past the fact that things are a bit different and you have to learn some new patterns of use. The Nokia Lumias are fantastic phones from a hardware perspective and have great apps that accompany them, so they are the perfect fit for the Windows Phone arena.

Comments Off

Working with Breeze Lookup Queries

One capability of Breeze that is often overlooked or not fully understood is executing queries that bring back multiple collections of data. These are often referred to as lookup queries because they are a perfect fit for going to the server one time to get back a collection of lists that can be used for populating “lookup lists” – lists of objects that you will use to populate drop down lists or other selection lists in various places in the application. These are often coded lists of allowable values for an enumerated property on some object you are going to be editing, and are usually fairly invariant over time. But you could also use this capability to retrieve multiple collections of interrelated objects in a single shot if you can not achieve the same result through a normal query execution with filtering and expansion.

To execute a lookup query, the server needs to expose an API operation that return a JSON payload with a root object containing each of the collections as a named property. If you were implementing this with an ASP.NET BreezeController, the controller method would look like this:

   1: [BreezeController]

   2: public class ZzaController : ApiController

   3: {

   4:     EFContextProvider<ZzaDbContext> _ContextProvider = new EFContextProvider<ZzaDbContext>();

   5:  

   6:     [HttpGet]

   7:     public string Metadata()

   8:     {

   9:         return _ContextProvider.Metadata();

  10:     }

  11:  

  12:     [HttpGet]

  13:     public object Lookups()

  14:     {

  15:         var orderStatuses = _ContextProvider.Context.OrderStatuses.ToList();

  16:         var productOptions = _ContextProvider.Context.ProductOptions.ToList();

  17:         var productSizes = _ContextProvider.Context.ProductSizes.ToList();

  18:         return new { orderStatuses, productOptions, productSizes };

  19:     }

  20:  

  21: }

 

The resulting wire level format will be a single JSON object at the root of the payload, containing one or more named array properties that contain the lists. For the server method above, addressed as /breeze/Zza/Lookups, the response body would look roughly like this:

{ $id=1, $type=…, orderStatuses = […], productOptions […], productSizes =[…] }

The individual items in the arrays would need to be entity types that are included in the client side metadata and that express their type with additional metadata properties on the returned JSON:

{ $id=2, $type=’Zza.Data.OrderStatus, Zza.Data’, Id = 1, Name=’Ordered’ }

If using the Breeze ASP.NET Web API support to implement BreezeControllers with EntityContextProviders, to get this extra type information associated with the entities you just need to expose a DbSet property from your DbContext for each of the entity types in the collections you return, but you do not need to have a separate query method for those types exposed from your Web API Controller.

   1: public class ZzaDbContext : DbContext

   2: {

   3:     public DbSet<ProductOption> ProductOptions { get; set; }

   4:     public DbSet<ProductSize> ProductSizes { get; set; }

   5:     public DbSet<OrderStatus> OrderStatuses { get; set; }

   6: }

 

To execute the lookup query, you do it like any other query execution with Breeze, you just use the name of your server API operation in specifying the query:

   1: var em = new breeze.EntityManager('breeze/Zza');

   2: var lookupsQuery = breeze.EntityQuery.from('Lookups');

   3: em.executeQuery(lookupsQuery).then(successHandler, errorHandler);

 

The important part to understand is what you will see in the successHandler arguments vs. what will be created in the EntityManager cache. When your successHandler gets called, like for other Breeze queries, the data object that gets passed to your handler will contain a results array just like it does for any other query, but the results will have the single object returned in it. That single item in the array will be the single root object that the server side returned. And that object, as expressed by the server will have the named properties containing each of the arrays returned by the server.

What sometimes trips people up is understanding how that relates to what gets created in the cache so that you can query for those collections in the cache later. The thing to realize is that the collection names produced in the cache have nothing to do with the names of the properties for the collections in the server payload. In the example payload I showed above, I could have named the properties foo, bar, and baz instead of orderStatuses, productOptions, and productSizes. And if I did that, those would still be the names of the properties containing the arrays when received in the client executeQuery successHandler.

But if the types of those entities were OrderStatus, ProductOption, and ProductSize, the names of the resulting collections in the EntityManager cache after the query completes would still be OrderStatuses, ProductOptions, and ProductSizes respectively. So if you were going to write code to retrieve those entities from the cache later, the collection name you would want to use when creating an EntityQuery to query the local cache with executeQueryLocally would be the plural of the entity type name, not the name of the property that contained the collection in the server payload.

Here is client JavaScript that demonstrates that the name of the array property in the successHandler is different from the collection created in the EntityManager cache for the Lookups controller showed earlier, if you changed the orderStatuses local variable name in the server Lookups method to foo:

   1: var em = new breeze.EntityManager('breeze/Zza');

   2: var lookupsQuery = breeze.EntityQuery.from('Lookups');

   3: em.executeQuery(lookupsQuery).then(successHandler, errorHandler);

   4:  

   5: function successHandler(data) {

   6:     var results = data.results[0];

   7:     if (results.foo != null)

   8:         console.log("results contain foo collection");

   9:     var cacheResults = em.executeQueryLocally(breeze.EntityQuery.from("OrderStatuses"));

  10:     if (cacheResults.length > 0)

  11:         console.log("cache contains 'OrderStatuses' collection");

  12: }

 

Notice that the data.results[0] object is the root object returned by the Lookups method, and that still has a foo property for the array of OrderStatus objects. But the collection that is created in the EntityManager cache that you can query for is not based on the names of those arrays in the payload object, they are based on the type of the entities contained in the arrays – in this example OrderStatus. So the resulting EntityManager collection is OrderStatuses.

Hopefully that helps clarify the differences between what you see in the query completion results and what gets put in the cache. If you have questions, ping me on Twitter @briannoyes.

Comments Off

Reusable Async Validation in WPF with Prism 4.2

I recently wrote a post on implementing a reusable validation base class for models and view models in WPF using Prism 4.2 on the Pluralsight blog. You can find the whole article here:

http://blog.pluralsight.com/async-validation-wpf-prism

Comments Off

VSLive! Chicago Sessions

Had a great week presenting at VSLive! Las Vegas last week and am already looking forward to presenting again at VSLive! Chicago next. You can register for that conference with this link http://bit.ly/CHSPK22_Reg. In Chicago I’ll be presenting the following:

Full day workshop: Data-Centric Single Page Apps with Angular, Breeze, and Web API

Build Data-Centric HTML5 Single Page Applications with Breeze

Build Maintainable Windows Store Apps with MVVM and Prism

Zero to Connected with Windows Azure Mobile Services

Hope to see you there!

Comments Off

Programmatic WPF Bindings and Chaining CollectionViewSource

In my Pluralsight course WPF Data Binding in Depth, I barely covered using bindings from code behind, mainly because where bindings really shine is in XAML. But there are occasions where you need to set a binding from code behind. I got a question on my course discussion about an example I showed where I show how to chain CollectionViewSources (CVSs) to get a Master-Details presentation of parent and child collections and how you could do that from code behind. So rather than answer there, I’ll do it here where it is a little easier to show code and explanation.

First off, to chain the CVSs, you set them up as Resources like so:

<Window.Resources>

    <CollectionViewSource x:Key="customerViewSource" />

    <CollectionViewSource x:Key="customerOrdersViewSource" 

       Source="{Binding Orders, Source={StaticResource customerViewSource}}"/>

    <CollectionViewSource x:Key="customerOrdersOrderItemsViewSource" 

       Source="{Binding OrderItems, Source={StaticResource customerOrdersViewSource}}"/>

</Window.Resources>

In my course, I show how you can get all this done through simple drag and drop using the Data Sources Window. Here I will just focus on the code.

In this case, I am chaining two levels deep, from a Customers collection, to the Orders for each Customer, to the OrderItems for each Order. You can see that the key is to set the Source property of the child CVS to the parent CVS through a binding.

Then naturally there are UI elements, typically DataGrids, whose ItemsSource property gets bound to each CVS to present that level in the hierarchy:

<DataGrid x:Name="ordersDataGrid" 

ItemsSource="{Binding Source={StaticResource customerOrdersViewSource}}" ...>

 

So how would you do this from code behind? First you need to create the CVS instances:

private CollectionViewSource _customerViewSource = new CollectionViewSource();

private CollectionViewSource _customerOrdersViewSource 

  = new CollectionViewSource();

private CollectionViewSource _customerOrdersOrderItemsViewSource 

  = new CollectionViewSource();

 

Then you need to create the bindings for the child (and grandchild) CVS in code in the constructor or Loaded event:

var ordersBinding = new Binding("Orders");

ordersBinding.Source = _customerViewSource;

BindingOperations.SetBinding(_customerOrdersViewSource, 

    CollectionViewSource.SourceProperty, ordersBinding);

 

var orderItemsBinding = new Binding("OrderItems");

orderItemsBinding.Source = _customerOrdersViewSource;

BindingOperations.SetBinding(_customerOrdersOrderItemsViewSource, 

    CollectionViewSource.SourceProperty, orderItemsBinding);

 

FrameworkElement derived types have their own SetBinding method on them. For normal DependencyObjects like a CVS, you use the BindingOperations class to set a binding programmatically, passing it the object you want to set the binding on, the dependency property that will be the target on that object, and the binding you want to set it to.

Finally, since the XAML won’t have access to those CVSs (unless you expose them through a property you can bind to), you can set the bindings for the DataGrids in the code behind as well.

ordersDataGrid.SetBinding(DataGrid.ItemsSourceProperty, 

    new Binding { Source = _customerOrdersViewSource });

orderItemsDataGrid.SetBinding(DataGrid.ItemsSourceProperty, 

    new Binding { Source = _customerOrdersOrderItemsViewSource });

Then you need to set the root collection on the root CVS Source property (after loading the data from somewhere naturally).

_customerViewSource.Source = Customers;

Then you are off and running.

Again, I rarely set bindings programmatically like this. Most of the time it is better to keep your bindings in the XAML. But if you need to, there you go.

You can download a full sample here.

Comments Off

Passing Complex Query Parameters with Breeze

In my course Building Data-Centric Single Page Applications with Breeze, I cover Breeze’s ability to pass parameters when you execute a query. The basics of that are that there is a withParameters method on the EntityQuery object that lets you pass in a JavaScript object with key/value pair properties that will be turned into a query string parameter by breeze and passed along to the service. You need to make sure the resource you are querying has a corresponding method on the target controller that takes those parameters.

So lets say I executed a query on the client side like this:

var em = new breeze.EntityManager("breeze/Zza");

var queryWithParams = breeze.EntityQuery

    .from("ProductsWithSimpleParams")

    .withParameters({ name: "foo", description: "bar"});

em.executeQuery(queryWithParams, function (data) { products(data.results); });

Based on the set up of the EntityManager, I am targeting a BreezeController called ZzaController. Whatever I pass to the .from call is interpreted as the Resource that I want to query. Breeze will append that to the URL path requested, and based on the default action-based routing of Breeze, that means I will need to have a method called ProductsWithSimpleParams that responds to HTTP GET requests on my controller. Because I used the .withParameters call, passing a JavaScript object literal with properties name and description on it, Breeze will add these as query string parameters with their values on the request. When I execute the query, I get an HTTP GET request with a URL of:

GET /breeze/Zza/ProductsWithSimpleParams?name=foo&description=bar

To handle this call, I will need a method on the controller that looks like this:

[HttpGet]

public IQueryable<Product> ProductsWithSimpleParams(string name, string description)

{

    // Do something with params...

    return _ContextProvider.Context.Products;

}

A combination of the action-based routing of Breeze and the model binding system of ASP.NET Web API kicks in here and the method is selected by name based on the URL, and the parameters are matched against the query string parameters by name and case, so the call gets dispatched into this method with the parameters populated. Couldn’t be simpler.

However, what might not be so obvious is what if you need to pass more complex parameters to your queries from the client side, including complex types and/or collections of parameters.

Lets take the case of complex types as discrete parameters first. Say that on the server side, you want to take in a single complex object as a parameter:

public class ComplexParam

{

    public string name { get; set; }

    public string description { get; set; }

}

 

[HttpGet]

public IQueryable<Product> ProductsWithSingleComplexParam(ComplexParam param)

{

    // Do something with params...

    return _ContextProvider.Context.Products;

}

With model binding in ASP.NET this won’t work by default for a query method because it expects complex types to be in the HTTP body, and a GET request can’t have a body. So what can we do? Well, we know Breeze is going to put parameters in the query string anyway, so we just need to tell ASP.NET model binding where to look. If we use a [FromUri] attribute on the parameter, it will look to what it finds in the query string to try to come up with a ComplexParam object to pass in:

public IQueryable<Product> ProductsWithSingleComplexParam([FromUri] ComplexParam param)

Basically once you do that, ASP.NET will create a new ComplexParam object and try to populate any of its properties from query string parameters. So the same client side code that we were using before (other than the resource name changing to “ProductsWithSingleComplexParam”) that put name and description in the query string will now be use to populate the name and description properties of the ComplexParam object instead.

Note that there is case sensitive matching going on here, so that is why I non-conventionally defined my property names camelCase instead of the norm in .NET of PascalCased. You can work around this by using the Breeze camelCase convention to get that conversion to happen automatically on the client side, or you can use the JSON.NET convention conversion to do it on the server side. That is a separate subject, so I will just make sure my client and server are using the same casing for the samples I show here.

What if you want a signature that has multiple complex types in it, such as:

[HttpGet]

public IQueryable<Product> ProductsWithTwoComplexParams([FromUri] ComplexParam param1,

    [FromUri] ComplexParam2 param2)

{

    // Do something with params...

    return _ContextProvider.Context.Products;

}

where ComplexParam2 looks like:

public class ComplexParam2

{

    public int Age { get; set; }

    public string Comments { get; set; }

}

In this case if we change our query on the client side to this:

var queryWithTwoComplexParams = breeze.EntityQuery

    .from("ProductsWithTwoComplexParams")

    .withParameters({ name: "foo", description: "bar", age: 42, comments: "hello" });

em.executeQuery(queryWithTwoComplexParams, function (data) { products(data.results); });

Now model binding will create the two separate objects, ComplexParam and ComplexParam2 and will pull values for their properties out of the individual query string values from the client side.

What if you want to treat them as separate objects on the client side as well, to keep more of a 1:1 object model? Breeze withParameters still wants a single root JavaScript object to be passed to it, but that object can have nested objects. if our parameters on the server side are named param1 and param2 as shown above, then we just need to make sure the structure of the root object we pass matches that parameter naming:

var queryWithTwoComplexParamsAsObjects = breeze.EntityQuery

    .from("ProductsWithTwoComplexParams")

    .withParameters({ param1: { name: "foo", description: "bar" }, param2: { age: 42, comments: "hello" } });

em.executeQuery(queryWithTwoComplexParamsAsObjects, function (data) { products(data.results); });

Here I am hard coding the objects for demonstration purposes, but those param1 and param2 objects could be variables that point to an object that was originally returned from a query that brought back ComplexParam and ComplexParam2 objects.

Finally, what if you want to be able to pass a collection of objects as parameters to the server side? Well, again you are constrained by the fact that Breeze wants a single root object that you pass to withParameters, but that object can certainly contain a property that is an array of objects. To understand what to do here, we just need to drop back to the fundamentals of what is going to happen on each end of the wire. Breeze withParameters is going to take the JavaScript object you pass it and turn it into a JSON representation and put it into the query string with each root property of the JavaScript object as a separate parameter. On the server side, you need to use the [FromUri] to get that complex object representation deserialized into a server object that you can use in your service method.

So say we had a structure to the collection (array) of JavaScript complex objects that we wanted to pass like this:

var params = [{ propName: "Name", value: "foo" }, { propName: "Description", value: "bar" }];

var queryWithCollectionOfParams = breeze.EntityQuery.from("ProductsWithCollectionOfParams").withParameters({ values: params });

em.executeQuery(queryWithCollectionOfParams, function (data) { products(data.results); });

What ends up on the wire is a GET request like this:

GET /breeze/Zza/ProductsWithCollectionOfParams?values%5B0%5D%5BpropName%5D=Name&values%5B0%5D%5Bvalue%5D=foo&values%5B1%5D%5BpropName%5D=Description&values%5B1%5D%5Bvalue%5D=bar

Now that is a little hard to read with the URL encoding, so lets look at the decoded query string:

values[0][propName]=Name&values[0][value]=foo&values[1][propName]=Description&values[1][value]=bar

We can see that because we passed a root object with with a property named “values” that points to the array of JavaScript objects, Breeze broke that down and turned each array entry and each property for each entry into its own query string parameter. So what do we need to have that read back in to some strongly typed objects on the server side? First we need a model object corresponding to each entry object:

public class CollectionItem

{

    public string propName { get; set; }

    public string value { get; set; }

}

Then we need an array argument named values for our service method of those CollectionItems:

[HttpGet]

public IQueryable<Product> ProductsWithCollectionOfParams([FromUri] CollectionItem[] values)

{

    // Do something with params....

    return _ContextProvider.Context.Products;

}

Now we are good to go even with passing a collection of complex objects to the server side.

If you need to go beyond that, my first instinct is to recognize that not every service call from your JavaScript client that happens to be using Breeze MUST use Breeze for every data related call. Ultimately your BreezeController is a Web API controller with an action-based route. You can call any method in your controller (or any other controller for that matter) with simple AJAX calls through JQuery. So if you have highly complex parameter passing and return type requirements that Breeze seems to be getting in the way of accomplishing, just get it out of the way and make those calls as normal AJAX calls yourself.

Also be aware the Breeze Labs has a sample of how you can take control of POST requests to put whatever you want in the request body here: https://github.com/IdeaBlade/Breeze/tree/master/Breeze.Client/Scripts/Labs.

Hope you find this helpful for understanding some of the options in passing more than simple parameters to a query method through Breeze.

You can download the full sample here.

Comments Off

Yet Another Podcast – Breeze Roundtable

Want to get to know more about Breeze and where it fits into HTML client and Single Page Application development? This discussion that we had as a round table podcast discussion on Jesse Liberty’s Yet Another Podcast is a great place to start:

http://jesseliberty.com/2014/02/10/yet-another-podcast-120-breeze-roundtable/

Comments Off

Speaking at Microsoft Maniacs 18 March 2014

I’m going to give a talk at a new user group in Sterling Virginia on March 18: Designing RESTful Services with ASP.NET Web API. You can find all the details and sign up to attend here:

http://www.meetup.com/Microsoft-Maniacs/events/166143782/

Hope to see you there, come out and support this new group at their inaugural meeting!