How to convert View Model into JSON object in ASP.NET MVC? How to convert View Model into JSON object in ASP.NET MVC? javascript javascript

How to convert View Model into JSON object in ASP.NET MVC?


In mvc3 with razor @Html.Raw(Json.Encode(object)) seems to do the trick.


Well done, you've only just started using MVC and you've found its first major flaw.

You don't really want to be converting it to JSON in the view, and you don't really want to convert it in the controller, as neither of these locations make sense. Unfortunately, you're stuck with this situation.

The best thing I've found to do is send the JSON to the view in a ViewModel, like this:

var data = somedata;var viewModel = new ViewModel();var serializer = new JavaScriptSerializer();viewModel.JsonData = serializer.Serialize(data);return View("viewname", viewModel);

then use

<%= Model.JsonData %>

in your view. Be aware that the standard .NET JavaScriptSerializer is pretty crap.

doing it in the controller at least makes it testable (although not exactly like the above - you probably want to take an ISerializer as a dependency so you can mock it)

Update also, regarding your JavaScript, it would be good practice to wrap ALL the widget JS you have above like so:

(    // all js here)();

this way if you put multiple widgets on a page, you won't get conflicts (unless you need to access the methods from elsewhere in the page, but in that case you should be registering the widget with some widget framework anyway). It may not be a problem now, but it would be good practice to add the brackets now to save yourself muchos effort in the future when it becomes a requirement, it's also good OO practice to encapsulate the functionality.


I found it to be pretty nice to do it like this (usage in the view):

    @Html.HiddenJsonFor(m => m.TrackingTypes)

Here is the according helper method Extension class:

public static class DataHelpers{    public static MvcHtmlString HiddenJsonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)    {        return HiddenJsonFor(htmlHelper, expression, (IDictionary<string, object>) null);    }    public static MvcHtmlString HiddenJsonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)    {        return HiddenJsonFor(htmlHelper, expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));    }    public static MvcHtmlString HiddenJsonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)    {        var name = ExpressionHelper.GetExpressionText(expression);        var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);        var tagBuilder = new TagBuilder("input");        tagBuilder.MergeAttributes(htmlAttributes);        tagBuilder.MergeAttribute("name", name);        tagBuilder.MergeAttribute("type", "hidden");        var json = JsonConvert.SerializeObject(metadata.Model);        tagBuilder.MergeAttribute("value", json);        return MvcHtmlString.Create(tagBuilder.ToString());    }}

It is not super-sofisticated, but it solves the problem of where to put it (in Controller or in view?) The answer is obviously: neither ;)