Как преобразовать модель представления в объект JSON в ASP.NET MVC?

Я разработчик Java, новичок в .NET. Я работаю над проектом .NET MVC2, где я хочу иметь частичное представление, чтобы обернуть виджет. Каждый объект виджета JavaScript имеет объект данных JSON, который будет заполнен данными модели. Затем методы обновления этих данных привязываются к событиям, когда данные изменяются в виджете или эти данные изменяются в другом виджете.

Код выглядит примерно так:

MyController:

virtual public ActionResult DisplaySomeWidget(int id) {
  SomeModelView returnData = someDataMapper.getbyid(1);

  return View(myview, returnData);
}

myview.ascx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SomeModelView>" %>

<script type="text/javascript">
  //creates base widget object;
  var thisWidgetName = new Widget();

  thisWidgetName.updateTable = function() {
    //  UpdatesData
  };
  $(document).ready(function () {
    thisWidgetName.data = <% converttoJSON(model) %>
    $(document).bind('DATA_CHANGED', thisWidgetName.updateTable());
  });
</script>

<div><%:model.name%></div>

Чего я не знаю, так это как отправить данные как SomeModelView и затем использовать их для заполнения виджета, а также для преобразования их в JSON. Я видел несколько действительно простых способов сделать это в контроллере, но не в представлении. Я полагаю, что это основной вопрос, но я собирался сделать это несколько часов.

Ответ 1

В mvc3 с бритвой @Html.Raw(Json.Encode(object)) кажется, делает трюк.

Ответ 2

Хорошо, вы только начали использовать MVC, и вы нашли свой первый главный недостаток.

Вы действительно не хотите преобразовывать его в JSON в представлении, и вы действительно не хотите его преобразовывать в контроллер, поскольку ни одно из этих мест не имеет смысла. К сожалению, вы застряли в этой ситуации.

Лучшее, что я нашел, это отправить JSON в представление в ViewModel, например:

var data = somedata;
var viewModel = new ViewModel();
var serializer = new JavaScriptSerializer();
viewModel.JsonData = serializer.Serialize(data);

return View("viewname", viewModel);

затем используйте

<%= Model.JsonData %>

в вашем представлении. Имейте в виду, что стандартный .NET JavaScriptSerializer довольно дерьмо.

делать это в контроллере, по крайней мере, делает его проверяемым (хотя и не совсем так, как указано выше), вы, вероятно, хотите взять ISerializer в качестве зависимости, чтобы вы могли его издеваться)

Обновить, что касается вашего JavaScript, было бы неплохо обернуть ВСЕ виджет JS, который у вас выше:

(
    // all js here
)();

таким образом, если вы разместите несколько виджетов на странице, вы не столкнетесь с конфликтами (если вам не нужен доступ к методам из другого места на странице, но в этом случае вы должны регистрировать виджет с какой-либо инфраструктурой виджетов), В настоящее время это может быть не проблема, но было бы неплохо добавить скобки для экономии усилий в будущем, когда это станет требованием, а также хорошей практикой OO для инкапсуляции функциональности.

Ответ 3

Я нашел довольно приятным сделать это так (использование в представлении):

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

Вот соответствующий вспомогательный метод. Класс расширения:

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());
    }
}

Это не супер-сложно, но решает проблему, где его поставить (в Контроллере или в представлении?) Ответ, очевидно: ни;)

Ответ 4

Вы можете напрямую использовать Json из действия,

Ваше действие будет примерно таким:

virtual public JsonResult DisplaySomeWidget(int id)
{
    SomeModelView returnData = someDataMapper.getbyid(1);
    return Json(returnData);
}

Edit

Просто увидел, что вы считаете, что это Model в представлении, поэтому вышесказанное не является строго правильным, вам нужно сделать вызов Ajax для метода контроллера, чтобы получить это, ascx не будет то у меня есть модель как таковая, я оставлю свой код на всякий случай, если он вам полезна, и вы можете изменить вызов

Ответ 5

@Html.Raw(Json.Encode(object)) можно использовать для преобразования View Modal Object в JSON

Ответ 6

У Эндрю был отличный ответ, но я хотел немного подружиться. То, как это отличается, - это то, что мне нравится, когда мои модели ModelViews не содержат служебных данных. Просто данные для объекта. Кажется, что ViewData подходит для счета за данные головной части, но, конечно, я новичок в этом. Я предлагаю сделать что-то вроде этого.

контроллер

virtual public ActionResult DisplaySomeWidget(int id)
{
    SomeModelView returnData = someDataMapper.getbyid(1);
    var serializer = new JavaScriptSerializer();
    ViewData["JSON"] = serializer.Serialize(returnData);
    return View(myview, returnData);
}

Просмотр

//create base js object;
var myWidget= new Widget(); //Widget is a class with a public member variable called data.
myWidget.data= <%= ViewData["JSON"] %>;

Что это для вас значит, это дает вам те же данные в вашем JSON, что и в вашем ModelView, поэтому вы можете вернуть JSON обратно на ваш контроллер, и у него будут все части. Это похоже на просто запрос с помощью JSONRequest, однако для этого требуется один меньше вызовов, поэтому он экономит ваши накладные расходы. Кстати, это фанк для Dates, но это похоже на другой поток.

Ответ 7

<htmltag id=’elementId’ data-ZZZZ’=’@Html.Raw(Json.Encode(Model))’ />

Обратитесь https://highspeedlowdrag.wordpress.com/2014/08/23/mvc-data-to-jquery-data/

Я сделал это ниже, и это работает как прелесть.

<input id="hdnElement" class="hdnElement" type="hidden" value='@Html.Raw(Json.Encode(Model))'>

Ответ 8

Расширение отличного ответа от Dave. Вы можете создать простой HtmlHelper.

public static IHtmlString RenderAsJson(this HtmlHelper helper, object model)
{
    return helper.Raw(Json.Encode(model));
}

И на ваш взгляд:

@Html.RenderAsJson(Model)

Таким образом, вы можете централизовать логику создания JSON, если по какой-то причине вы захотите позже изменить логику.