ASP.NET MVC: как преобразовать модель представления в объект Json
Я разработчик Java, новый для. 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 ответов:
хорошо сделано, вы только начали использовать 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 %>in ваш взгляд. Имейте в виду, что стандартный .NET JavaScriptSerializer-это довольно дерьмо.
выполнение этого в контроллере, по крайней мере, делает его тестируемым (хотя и не совсем так, как выше - вы, вероятно, хотите взять ISerializer в качестве зависимости, чтобы вы могли издеваться над ним)
обновление кроме того, что касается вашего JavaScript, было бы хорошей практикой обернуть все виджеты JS, которые у вас есть выше, так:
( // all js here )();таким образом, если вам поставить несколько виджетов на странице не будет возникать конфликтов (если вам не нужно получить доступ к методам из другого места на странице, но в этом случае вы все равно должны зарегистрировать виджет с помощью какой-либо рамки виджета). Это может быть не проблема сейчас, но было бы хорошей практикой добавить скобки сейчас, чтобы сэкономить много усилий в будущем, когда это станет требованием, это также хорошая практика OO для инкапсуляции функциональности.
Я нашел, что это было довольно приятно сделать это так (использование в представлении):
@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()); } }он не супер-софистичен, но он решает проблему, куда его поместить (в контроллер или в поле зрения?) Ответ очевиден: ни то, ни другое ;)
можно использовать
Jsonот действия напрямую,ваше действие будет примерно таким:
virtual public JsonResult DisplaySomeWidget(int id) { SomeModelView returnData = someDataMapper.getbyid(1); return Json(returnData); }Edit
просто увидел, что вы предполагаете, это
Modelпредставления, так что выше не совсем правильно, вы должны были бы сделатьAjaxвызовите метод контроллера, чтобы получить это,ascxтогда не было бы модели как таковой, я оставлю свой код на всякий случай, если он вам пригодится, и вы можете изменить вызов
@ Html.Raw(Json.Encode (object)) может использоваться для преобразования модального объекта View в JSON
<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))'>
расширение Большой ответ от Дэйв. Вы можете создать простой HtmlHelper.
public static IHtmlString RenderAsJson(this HtmlHelper helper, object model) { return helper.Raw(Json.Encode(model)); }а на ваш взгляд:
@Html.RenderAsJson(Model)таким образом, вы можете централизовать логику для создания JSON, если вы по какой-то причине хотите изменить логику позже.
У Андрея был отличный ответ, но я хотел немного подправить его. Это отличается от того, что мне нравится, когда мои 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, однако для этого требуется один вызов меньше, поэтому он экономит ваши накладные расходы. Кстати, это фанки для дат, но это похоже на другую тему.
Comments