ASP.NET MVC: как преобразовать модель представления в объект Json - PullRequest
147 голосов
/ 29 июля 2010

Я новичок в разработке для .NET. Я работаю над проектом .Net MVC2, где я хочу иметь частичное представление, чтобы обернуть виджет. Каждый объект виджета JS имеет объект данных 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. Мне показалось несколько действительно простых способов сделать это в контроллере, но не в представлении. Я полагаю, что это основной вопрос, но я уже несколько часов пытаюсь сделать это замечательно.

Ответы [ 8 ]

327 голосов
/ 20 сентября 2011

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

30 голосов
/ 29 июля 2010

Отлично, вы только начали использовать 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 для инкапсуляции функциональности.

18 голосов
/ 22 ноября 2012

Я нашел, что было бы неплохо сделать это следующим образом (использование в представлении):

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

Вот соответствующий вспомогательный метод 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не супер-изощренный, но он решает проблему того, где его поместить (в контроллере или в поле зрения?) Ответ очевиден: ни один;)

5 голосов
/ 29 июля 2010

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

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

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

Редактировать

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

2 голосов
/ 24 июля 2016

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

0 голосов
/ 21 июля 2016

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

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

А по вашему мнению:

@Html.RenderAsJson(Model)

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

0 голосов
/ 29 апреля 2016
<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))'>

0 голосов
/ 30 июля 2010

У Эндрю был отличный отклик, но я хотел немного его настроить. Отличие заключается в том, что мне нравится, что мои 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);
}

View

//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, однако для этого требуется на один вызов меньше, что экономит ваши накладные расходы. Кстати, это забавно для дат, но это похоже на другую тему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...