Knockout w/ASP.Net MVC: JSON model binding question

1,558 views
Skip to first unread message

jrnail23

unread,
Apr 7, 2011, 2:24:54 PM4/7/11
to KnockoutJS
Hi all,
I just posted this question as a comment on Steve Sanderson's blog
post entitled "Editing a variable-length list, Knockout-style" (http://
blog.stevensanderson.com/2010/07/12/editing-a-variable-length-list-
knockout-style), and I thought I'd repost it here in hopes of getting
wider feedback:

BACKGROUND: in Steve's example, he used a [FromJson]
CustomModelBinderAttribute to enable binding to an action method's
parameter, an IEnumerable<GiftModel> (where GiftModel is just a simple
model class with a couple of primitive properties).

(snip)
Are there any alternatives to using the FromJson attribute? Perhaps a
way to plug in a utility to Knockout to convert the JSON to something
more friendly to the MVC action method without having to decorate my
action method's parameters?

I ran across this blog post showing a jQuery addIn that converts JSON
into something ASP.Net MVC’s DefaultModelBinder can handle directly
(http://erraticdev.blogspot.com/2010/12/sending-complex-json-objects-
to-aspnet.html), which seemed interesting, but I’m not sure if there’s
a way to get Knockout to use this approach.

Also, what guidance would you offer for separating JavaScript code
from my MVC Views with Knockout (i.e., like the unobtrusive jQuery
approach -- I'm aiming to eliminate <script> tags in my HTML views)?

-James

rpn

unread,
Apr 7, 2011, 2:44:13 PM4/7/11
to knock...@googlegroups.com
Hi James-
If you post your data back via AJAX, then you won't need the FromJson attribute.  So, this would be doing something like using jQuery's $.ajax functionality like this:

$.ajax({
    url
: yourcontroller/action,
    type
: "POST",
    data
: ko.toJSON(yourdata),
    dataType
: "json",
    contentType
: "application/json; charset=utf-8",
    success
: function(data) {
       
...do something
   
}
});
This will work properly with MVC 3, as the JSON model binding is supported by default.
The ko.toJSON function will make sure that any observables or dependentObservables are unwrapped into regular properties and will then convert the object to the JSON string representation for transferring to the server (using JSON.stringify).
As far as keeping your JavaScript separate, you should not have a problem creating your viewModel and calling ko.applyBindings in a separatre file.  
If you are interesting in keeping your templates in external files, then there are various thoughts on that topic.  I put mine here, although I also have some ideas about baking this into the template binding itself, in its 'init" function.
Hope this helps.





jrnail23

unread,
Apr 7, 2011, 3:05:25 PM4/7/11
to KnockoutJS
Thanks RPN,
In Steve's example, a collection of model objects are being posted
together via a non-Ajax post, but the posted form collection just
consists of one pair, as follows:

gifts=%5b%7b%22Title%22%3a%22Tall+Hat%22%2c%22Price%22%3a49.95%7d%2c%7b
%22Title%22%3a%22Long+Cloak%22%2c%22Price%22%3a78.25%7d%5d

When UrlDecoded, you can see that this is actually a JSON-serialized
array of the GiftModel object (with properties Price and Title):

[{"Title":"Tall Hat","Price":49.95},{"Title":"Long Cloak","Price":
78.25}]

Of course, the DefaultModelBinder doesn't know what to do with this,
so Steve is using that FromJson attribute, to get around it.

I'm guessing this isn't the typical Knockout form post behavior, so
this problem may not exist for regular (single model) form posts...
but if there's a way to support this scenario without resorting to
decorating action method parameters with the [FromJson] attribute
wherever this might happen, I'd really like to find it.

Any thoughts?

rpn

unread,
Apr 7, 2011, 3:09:42 PM4/7/11
to knock...@googlegroups.com
OK- so, you are saying that it is a requirement for your app to use a non-AJAX post?

rpn

unread,
Apr 7, 2011, 3:31:49 PM4/7/11
to knock...@googlegroups.com
How about you create a custom model binder and register it in Global.asax.cs.

Binder looks like:
	public class JsonModelBinderIModelBinder
	{
		private readonly static JavaScriptSerializer serializer = new JavaScriptSerializer();
 
		public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
		{
			var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName];
			if (string.IsNullOrEmpty(stringified))
				return null;
			return serializer.Deserialize(stringified, bindingContext.ModelType);
		}
	}
Then, register it in global.asax.cs like:
ModelBinders.Binders.Add(typeof(IEnumerable<GiftModel>), new JsonModelBinder());
This would allow you to receive the url-encoded JSON from ko.utils.postJSON() without using the custom attribute.
Does this work for you?

jrnail23

unread,
Apr 7, 2011, 4:08:44 PM4/7/11
to KnockoutJS
RPN, I'll give that a try.

Thanks again!

ciarafu...@gmail.com

unread,
Aug 6, 2012, 7:10:51 PM8/6/12
to knock...@googlegroups.com
I was just wondering how are people passing viewmodels via mvc down to their views serialised as Json.. I am trying to work out if you have to manually create js view model representations of your asp.net view models .. nothing out there that auto generates js view model from model? It very manual at present I was hoping to play with the new apicontroller stuff but there don't seem to be a good tutorial on knockout with mvc from scratch

Jon Bitler

unread,
Aug 7, 2012, 7:25:52 AM8/7/12
to knock...@googlegroups.com
I used the new ASP.NET Web API http://www.asp.net/web-api/overview but
I still manually created the model in knockout. There is the mapping
plugin from knockout
http://knockoutjs.com/documentation/plugins-mapping.html that I think
may help you.
Reply all
Reply to author
Forward
0 new messages