IT:AD:Knockout:HowTo:MVC:Serialize an MVC Model
Summary
FAQ
* Should I serialize the ViewModel serverside or clientside?
- There may be a very tenuous reason to render the input controls with the values directly, due to Compliance reasons, but it will always be a wrong design architecture as it combines Data + View.
- A better SOC is to render the View without data, and post it with the first Model embedded (in order to not require a second callback).
- Subsequent updates call back to the server.
* What about DropDowns? Don't you need to send those values as well? Isn't it expensive to call back to the server for the values?
- Really? You think it's better to embed in the page for all users the values for a dropdown they may not change, just for the % of users that will to not call back to the server? All those Create and Edit forms? To save a second post? That's ASPergers thinking (that the server should render the page+model+serializedserviceoptions).
Process
Serialize the Model
You can define them the ViewModel in JScript, but a more elegant way is to serialize a server side MVC Model, and send it up to the model:
var model = @Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model))
Although it makes a hash of the dates, so consider using a better serializer:
var simpleModel = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model, new Newtonsoft.Json.Converters.IsoDateTimeConverter()))
or
var simpleModel = @Html.Raw(Json.Encode(Model))
or use a lib:
[https://github.com/paultyng/FluentJson.NET](https://github.com/paultyng/FluentJson.NET)
Make the JSON into an *Observable* ViewModel
The first time you load the page, embed the code directly in the page:
<script type="text/javascript">
var simpleModel = @Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model))
$(document).ready(function () {
//Ensure knockout.mapping-latest.js is loaded, so you can
//use the Mapping Extension to make it into an observable mmodel:
var viewModel = ko.mapping.fromJS(simpleModel);
//Start binding:
ko.applyBindings(viewModel);
} );
</script>
Note that we're using the mapping extension to make the scalar properties into observables: [[IT/AD/Knockout.JS/HowTo/Import/the/necessary/Libs]]