ASP.NET MVC में View Model को JSON ऑब्जेक्ट में कैसे बदलें?


156

मैं एक जावा डेवलपर हूं, जो .NET के लिए नया है। मैं एक .NET MVC2 प्रोजेक्ट पर काम कर रहा हूं, जहां मैं विजेट को लपेटने के लिए एक आंशिक दृश्य रखना चाहता हूं। प्रत्येक जावास्क्रिप्ट विजेट ऑब्जेक्ट में 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
मैं जानता हूं कि यह एक पुराना सवाल है। लेकिन आज तक इसे करने के बेहतर तरीके हैं। JSON इनलाइन को अपने दृश्य परिणाम के साथ न मिलाएं। AJAX के माध्यम से JSON आसानी से धारावाहिक है और इसे वस्तुओं की तरह माना जा सकता है। जावास्क्रिप्ट में कुछ भी दृश्य से अलग होना चाहिए। आप नियंत्रक के माध्यम से बिना किसी प्रयास के आसानी से मॉडल वापस कर सकते हैं।
पिओटर कुल

जवाबों:


346

रेजर के साथ mvc3 @Html.Raw(Json.Encode(object))में चाल करने के लिए लगता है।


1
+1 मैंने Html.Raw का उपयोग किया, लेकिन Json.Encode को कभी नहीं पाया और व्यू मॉडल के कंट्रोलर में स्ट्रिंग जोड़ने के लिए सिर्फ JavaScript सर्वर का इस्तेमाल किया
AaronLS

5
यह दृष्टिकोण तब भी काम करता है जब आप परिणामी JSON को जावास्क्रिप्ट में पास करना चाहते हैं। रेजर हरी स्क्वीगल्स के साथ शिकायत करता है यदि आप <script> टैग्स के अंदर एक फंक्शन पैरामीटर के रूप में @ Html.Raw (...) कोड डालते हैं, लेकिन JSON वास्तव में इसे JS कहलाता है। बहुत काम और चालाक। +1
कार्ल हेनरिक हेंके

1
यह MVC3 के बाद से ऐसा करने का तरीका है और इसे एक नियंत्रक से लौटाया जाना चाहिए। अपने Viewresult में जसन एम्बेड न करें। इसके बजाय JSON को अलग से संभालने के लिए एक नियंत्रक बनाएं और AJAX के माध्यम से JSON अनुरोध करें। यदि आपको JSON की आवश्यकता है तो आप कुछ गलत कर रहे हैं। या तो एक ViewModel का उपयोग करें या कुछ और।
पिओटर कुला

3
Json.Encode मेरे 2-आयामी सरणी को json में 1-आयामी सरणी में एन्कोड करता है। Newtonsoft.Json.JsonConvert.SerializeObject दो आयामों को ठीक से जसन में क्रमबद्ध करता है। इसलिए मैं उत्तरार्द्ध का उपयोग करने का सुझाव देता हूं।
मोनू 68

12
MVC 6 का उपयोग करते समय (शायद 5 भी) आपको Json.Serializeएन्कोड के बजाय उपयोग करने की आवश्यकता है ।
कोआलाअरियर

31

ठीक है, आपने केवल एमवीसी का उपयोग शुरू किया है और आपको इसका पहला बड़ा दोष मिला है।

आप वास्तव में इसे JSON में देखने के लिए परिवर्तित नहीं करना चाहते हैं, और आप वास्तव में इसे नियंत्रक में परिवर्तित नहीं करना चाहते हैं, क्योंकि इनमें से कोई भी स्थान समझ में नहीं आता है। दुर्भाग्य से, आप इस स्थिति के साथ फंस गए हैं।

सबसे अच्छी बात जो मुझे देखने को मिली है वह इस तरह से ViewModel में JSON को भेजना है:

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 को एक निर्भरता के रूप में लेना चाहते हैं ताकि आप इसका मज़ाक उड़ा सकें)

अपने जावास्क्रिप्ट के बारे में भी अपडेट करें, आपके द्वारा ऊपर दिए गए सभी विजेट जेएस को लपेटने के लिए यह अच्छा अभ्यास होगा:

(
    // all js here
)();

इस तरह यदि आप एक पृष्ठ पर कई विजेट्स डालते हैं, तो आपको संघर्ष नहीं होगा (जब तक आपको पेज में कहीं और से तरीकों तक पहुंचने की आवश्यकता नहीं है, लेकिन उस स्थिति में आपको कुछ विजेट फ्रेमवर्क के साथ विजेट को पंजीकृत करना चाहिए)। यह अब एक समस्या नहीं हो सकती है, लेकिन भविष्य में आवश्यकता पड़ने पर भविष्य में अपने आप को बचाने के लिए अब ब्रैकेट्स को जोड़ने के लिए अच्छा अभ्यास होगा, यह कार्यक्षमता को घेरने के लिए अच्छा ओओ अभ्यास भी है।


1
यह दिलचस्प लग रहा है। मैं सिर्फ डेटा की एक कॉपी बनाने जा रहा हूं और इसे व्यूडेटा के रूप में पास कर दूंगा लेकिन इस तरह से यह अधिक दिलचस्प लग रहा है। मैं इसके साथ खेलूंगा और आपको बताऊंगा। BTW यह मेरा पहली बार स्टैकओवरफ्लो पर एक सवाल पोस्ट कर रहा है और इसे अच्छी प्रतिक्रियाएं मिलने में 5 मिनट का समय लगा, यह कमाल है !!
क्रिस स्टीफंस

nothings गलत इसके साथ, अपने बस अनुकूलन योग्य नहीं है, अगर आप किसी भी कस्टम मूल्य स्वरूपण चाहते आप पहले से यह करने के लिए, मूल रूप से सब कुछ एक स्ट्रिंग बनाने है :( इस तिथियों के साथ सबसे प्रमुख है। मुझे पता है आसान समाधान देखते हैं, लेकिन वे नहीं होना चाहिए आवश्यक!
एंड्रयू बुलक

@Update मैं एक अद्वितीय ऑब्जेक्ट नाम उत्पन्न करने के लिए उस विजेट के .net स्थिर काउंटर का उपयोग करने के बारे में देख रहा था। लेकिन आपने जो लिखा है, ऐसा लगता है कि यह एक ही बात को पूरा करेगा और इसे कमजोर करेगा। इसके अलावा, मैंने एक विजेट "new_widget_event 'के निर्माण को एक पृष्ठ स्तर की वस्तु पर नज़र रखने के लिए उन्हें ट्रैक करने के लिए बाध्य किया, लेकिन ऐसा करने का मूल कारण ओबीई बन गया। इसलिए मैं बाद में फिर से विचार कर सकता हूं। सभी मदद के लिए धन्यवाद मैं पोस्ट करने जा रहा हूं। आपने जो सुझाव दिया था, उसका एक संशोधित संस्करण है, लेकिन समझाता हूं कि मुझे यह क्यों पसंद है।
क्रिस स्टीफंस

2
मैं अपने पिछले बयान को वापस लेना "इसके साथ कुछ भी गलत नहीं है"। इसमें सब कुछ गलत है
एंड्रयू बुलॉक

आप यह क्यों कहते हैं कि हम JSON को नियंत्रक से वापस नहीं कर सकते। इस तरह से यह किया जाना चाहिए। एक ही धारावाहिक का उपयोग JavaScriptSerializerया Return Json(object)दोनों का उपयोग करना । जब तक आप सही मॉडल को परिभाषित करते हैं, तब तक कंट्रोलर में वही JSON पोस्ट करना आपके लिए ऑब्जेक्ट को फिर से बनाएगा। शायद MVC2 के दौरान यह एक बड़ी खामी थी .. लेकिन आज इसकी एक हवा और बहुत सुविधाजनक है। आपको यह दर्शाने के लिए अपने उत्तर को अपडेट करना चाहिए।
पिओटर कुल

18

मैंने इसे इस तरह से करना बहुत अच्छा समझा (दृश्य में उपयोग):

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

यह सुपर-सोफिस्टिकेटेड नहीं है, लेकिन यह समस्या को हल करता है कि इसे कहां रखा जाए (नियंत्रक या दृश्य में?) उत्तर स्पष्ट रूप से है: न तो;)


यह मेरी राय में अच्छा और साफ था और एक पुन: प्रयोज्य सहायक में लिपटा हुआ था। चीयर्स, जे
जॉन

6

आप Jsonसीधे कार्रवाई से उपयोग कर सकते हैं ,

आपका एक्शन कुछ इस तरह होगा:

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

संपादित करें

बस देखा कि आप मान लेते हैं कि यह Modelएक दृश्य है, इसलिए उपरोक्त सख्ती से सही नहीं है, आपको इसे प्राप्त करने के लिए Ajaxनियंत्रक पद्धति पर कॉल करना ascxहोगा, तब प्रति मॉडल नहीं होगा, मैं अपना कोड छोड़ दूंगा केवल मामले में यह आपके लिए उपयोगी है और आप कॉल में संशोधन कर सकते हैं

2 को संपादित करें आईडी को कोड में रखें


1
लेकिन वह इस दृश्य में इसे प्रस्तुत नहीं कर सकता, उसे एक 2-अजाक्स कॉल करना होगा
एंड्रयू बुलॉक

धन्यवाद, मैं मूल रूप से jQuery कॉल json कॉल का उपयोग करके ऐसा कर रहा था और HTML तत्वों को json से खुद को पॉप्युलेट करने की योजना बना रहा था। हालाँकि, अभी हम जिस पैटर्न का अनुसरण कर रहे हैं, वह यह है कि हमारे विचारों में एक मॉडल व्यू लौटाया जाए और बेसिक एचटीएमएल एलिमेंट जैसे टेबल आदि को पॉप्युलेट करने का सबसे आसान तरीका है कि मैं JSON फॉर्मेट में एक ही डेटा को ViewData के रूप में भेज सकूं लेकिन यह बेकार लगता है।
क्रिस स्टीफेंस

2
YO को JSON को एक दृश्य परिणाम के साथ एम्बेड नहीं किया जाना चाहिए। ओपी को या तो मानक एमवीसी से चिपके रहने की जरूरत है और एक मॉडल या व्यूमाडेल को वापस करना होगा या एक AJAX करना होगा। JSON को एक दृश्य के साथ एम्बेड करने के लिए बिल्कुल कोई REASON नहीं है। यह सिर्फ बहुत गंदा कोड है। यह उत्तर Microsoft आचरण द्वारा सही तरीका और अनुशंसित तरीका है। डाउनवोट अनावश्यक था यह निश्चित रूप से सही उत्तर है। हमें खराब कोडिंग प्रथाओं को प्रोत्साहित नहीं करना चाहिए। या तो AJAX या दृश्यों के माध्यम से मॉडल के माध्यम से JSON। मिश्रित मार्कअप के साथ कोई भी स्पेगेटी कोड पसंद नहीं करता है!
पिओटर कुला

इस समाधान के परिणामस्वरूप निम्न समस्या होगी: stackoverflow.com/questions/10543953/…
जेनी ओ'रेली



0

डेव से महान जवाब का विस्तार । आप एक साधारण HtmlHelper बना सकते हैं ।

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

और आपके विचार में:

@Html.RenderAsJson(Model)

इस तरह आप JSON बनाने के लिए तर्क को केंद्रीकृत कर सकते हैं यदि आप किसी कारण से, तर्क को बाद में बदलना चाहेंगे।


0

एंड्रयू की शानदार प्रतिक्रिया थी लेकिन मैं इसे थोड़ा कम करना चाहता था। जिस तरह से यह अलग है कि मैं अपने 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 के माध्यम से इसे अनुरोध करने के समान है, हालांकि इसके लिए एक कम कॉल की आवश्यकता होती है ताकि यह आपको उस ओवरहेड को बचाता है। BTW यह तारीखों के लिए कायरता है लेकिन यह एक और धागे की तरह लगता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.