Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice on passing Mvc Model to KnockoutJS

Tags:

I googled around on how to pass mvc model to knockoutjs and it seems there are two ways:

  • Using @Html.Raw(Json.Encode(Model))
  • Using $.get or $.ajax

Which of the ways is a best practice of passing mvc model to knockoutjs? I know it is a per requirement basis but it seems using $.get is more cleaner versus the @Html.Raw method.

like image 883
gnaungayan Avatar asked Jul 24 '12 10:07

gnaungayan


1 Answers

I've successfully used several approaches.

In a strongly typed Razor view, you can write the JavaScript ViewModel object like you would any other HTML, inserting the Model elements as you go. I find this klunky as Razor and JS don't play well together with Visual Studio and Intellisense, but even with a bunch of red squigglies the resulting code works fine.

<script type="text/javascript">  var data = [     @for (int i=0; i < Model.Packages.Count; i++)     {         var package = Model.Packages[i];         <text>{Id: ko.observable(package.Id),                Name: ko.observable(package.Name)               }</text>     }      var viewModel = {         var packages = ko.observableArray(data);         // more code     }      ko.applyBindings(viewModel); </script> 

This code can get ugly in a hurry depending on the complexity of your Model. As you mentioned, you can also serialize the model object into JSON using Html.Raw(). If you go that route, you can use it to build your Knockout ViewModel using the KO Mapping library:

<script type="text/javascript">     var data = @Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model));     var viewModel = ko.mapping.fromJS(data);     ko.applyBindings(viewModel); </script> 

This isn't as kludgy as the first option, but I feel like I'm giving up too much control this way. It means my KO ViewModel is pretty tightly coupled to the structure of my MVC ViewModel, which I may or may not want. Not to mention, for this to work my JavaScript needs to be in my cshtml page which I really don't like. Lastly, both of these approaches are purely server side. For more responsive web pages, like SPIs, you'll want to do more on the client side.

My preference is to use $.getJSON calls client side from the JavaScript itself. At that point, you can process the return data into your ViewModel, either hand rolling or using the mapping library. If you are calling back to actions in your MVC controller, just have the action return a JsonResult type (instead of an ActionResult). (You can also do similar stuff with ContentResult) If you can use the new MVC4 WebAPI, those controllers will return JSON by default.

like image 99
Joel Cochran Avatar answered Oct 10 '22 04:10

Joel Cochran