2009-09-25 19 views
19

मैं ऐसी वेबसाइट पर काम कर रहा हूं जो सर्वर पक्ष में JSON ऑब्जेक्ट (jQuery पोस्ट विधि का उपयोग करके) पोस्ट करेगा।एएसपी.नेट एमवीसी में, नियंत्रक की एक्शन विधि से पहले या नियंत्रक में जेएसओएन को deserialize

{ 
    "ID" : 1, 
    "FullName" : { 
     "FirstName" : "John", 
     "LastName" : "Smith" 
    } 
} 

साथ ही, मैंने इस डेटा संरचना के लिए सर्वर पक्ष पर कक्षाएं लिखीं।

public class User 
{ 
    public int ID { get; set; } 
    public Name FullName { get; set;} 
} 

public class Name 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

जब मैं अपने नियंत्रक वर्ग में निम्न कोड के साथ वेबसाइट चलाता हूं, तो पूर्ण नाम संपत्ति deserialized नहीं मिलता है। मैं क्या गलत कर रहा हूं?

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Submit(User user) 
{ 
    // At this point, user.FullName is NULL. 

    return View(); 
} 
+3

MVC आउट-ऑफ-द-बॉक्स JSON अक्रमांकन का समर्थन नहीं करता है, लेकिन हम इसे v2 के लिए जोड़ने पर विचार कर रहे हैं। इस बीच, आप अनुरोध शरीर को पूरी तरह से हाइड्रेटेड उपयोगकर्ता ऑब्जेक्ट में बदलने के लिए JavaScriptSerializer का उपयोग कर सकते हैं। – Levi

+1

@ लेवी - यह एक उत्तर पोस्ट होना चाहिए;) – womp

+0

यह अजीब है; किसी भी तरह आईडी संपत्ति सही ढंग से deserialized था। अगर मैं जावास्क्रिप्टसेरियलाइज़र का उपयोग करना चाहता था, तो सबमिट करने के लिए इनपुट पैरामीटर() ऑब्जेक्ट टाइप करेगा? – weilin8

उत्तर

22

मैंने एक एक्शन फ़िल्टर लागू करके मेरी समस्या का समाधान किया; कोड नमूना नीचे प्रदान किया गया है। शोध से, मैंने सीखा कि ऊपर वर्णित टेकपारा के रूप में एक और समाधान, मॉडल बाइंडर है। लेकिन मैं वास्तव में नहीं जानता कि किसी भी दृष्टिकोण में करने के पेशेवरों और विपक्ष।

इस समाधान के लिए स्टीव जेनेटाइल के blog post के लिए धन्यवाद।

public class JsonFilter : ActionFilterAttribute 
    { 
     public string Parameter { get; set; } 
     public Type JsonDataType { get; set; } 

     public override void OnActionExecuting(ActionExecutingContext filterContext) 
     { 
      if (filterContext.HttpContext.Request.ContentType.Contains("application/json")) 
      { 
       string inputContent; 
       using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream)) 
       { 
        inputContent = sr.ReadToEnd(); 
       } 

       var result = JsonConvert.DeserializeObject(inputContent, JsonDataType); 
       filterContext.ActionParameters[Parameter] = result; 
      } 
     } 
    } 

[AcceptVerbs(HttpVerbs.Post)] 
[JsonFilter(Parameter="user", JsonDataType=typeof(User))] 
public ActionResult Submit(User user) 
{ 
    // user object is deserialized properly prior to execution of Submit() function 

    return View(); 
} 
+2

awww स्नैप के बजाय 'ContentType' का मतलब हो सकते हैं, 133t एमवीसी कौशल के साथ weilin, आप मुझे सोमवार को बेहतर सिखाते हैं;) – TJB

+3

इस विधि के कस्टम मॉडलबिन्डर पर एक उल्लेखनीय लाभ है जिसमें आप इस प्रकार को deserialize करने के लिए परिभाषित कर सकते हैं। कस्टम मॉडलबिंडर के साथ, यह हार्ड-कोडेड है और इस प्रकार केवल एक प्रकार के लिए उपयोगी है। –

+0

बहुत लचीला एक, बढ़िया! –

5

आप Json.NET को आजमा सकते हैं। documentation बहुत अच्छी है और यह do what you need में सक्षम होना चाहिए। तुम भी रूप में यह एक ActionResult कि ASP.NET MVC आवेदन में इस्तेमाल किया जा सकता रिटर्न JsonNetResult हड़पने के लिए चाहता हूँ। इसका उपयोग करना काफी आसान है।

जेसन.नेट भी दिनांक क्रमबद्धता के साथ अच्छी तरह से काम करता है। can be found here के बारे में अधिक जानकारी।

उम्मीद है कि इससे मदद मिलती है।

11

1. बनाएँ कस्टम मॉडल बांधने की मशीन Application_Start घटना

ModelBinders.Binders[typeof(User)] = new UserModelBinder(); 

3.Use jQuery $ .Get/$ में

public class UserModelBinder : IModelBinder 
    { 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     User model; 

     if(controllerContext.RequestContext.HttpContext.Request.AcceptTypes.Contains("application/json")) 
     { 
     var serializer = new JavaScriptSerializer(); 
     var form = controllerContext.RequestContext.HttpContext.Request.Form.ToString(); 
     model = serializer.Deserialize<User>(HttpUtility.UrlDecode(form)); 
     } 
     else 
     { 
     model = (User)ModelBinders.Binders.DefaultBinder.BindModel(controllerContext, bindingContext); 
     } 

     return model; 
    } 
    } 

2.add मॉडल बांधने की मशीन। दृश्य जावा स्क्रिप्ट कोड क्लाइंट में पोस्ट करें।

<% using(Html.BeginForm("JsonData","Home",new{},FormMethod.Post, new{id="jsonform"})) { %> 

    <% = Html.TextArea("jsonarea","",new {id="jsonarea"}) %><br /> 

    <input type="button" id="getjson" value="Get Json" /> 
    <input type="button" id="postjson" value="Post Json" /> 
    <% } %> 
    <script type="text/javascript"> 
    $(function() { 
     $('#getjson').click(function() { 
     $.get($('#jsonform').attr('action'), function(data) { 
      $('#jsonarea').val(data); 
     }); 
     }); 

     $('#postjson').click(function() { 
     $.post($('#jsonform').attr('action'), $('#jsonarea').val(), function(data) { 
      alert("posted!"); 
     },"json"); 
     }); 
    }); 
    </script> 
+0

क्या आप 'AcceptTypes' – Dmitriy

4

इसे आजमाएं;

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Submit(FormCollection collection) 
{ 
    User submittedUser = JsonConvert.DeserializeObject<User>(collection["user"]); 
    return View(); 
} 
2

कुछ शोध के बाद, मैं Takepara के समाधान पाया Newtonsoft के Json.NET के साथ डिफ़ॉल्ट MVC JSON deserializer की जगह के लिए सबसे अच्छा विकल्प हो सकता है। Global.asax.cs में

using Newtonsoft.Json; 

namespace MySite.Web 
{ 
    public class MyModelBinder : IModelBinder 
    { 
     // make a new Json serializer 
     protected static JsonSerializer jsonSerializer = null; 

     static MyModelBinder() 
     { 
      JsonSerializerSettings settings = new JsonSerializerSettings(); 
      // Set custom serialization settings. 
      settings.DateTimeZoneHandling= DateTimeZoneHandling.Utc; 
      jsonSerializer = JsonSerializer.Create(settings); 
     } 

     public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
     { 
      object model; 

      if (bindingContext.ModelType.Assembly == "MyDtoAssembly") 
      { 
       var s = controllerContext.RequestContext.HttpContext.Request.InputStream; 
       s.Seek(0, SeekOrigin.Begin); 
       using (var sw = new StreamReader(s)) 
       { 
        model = jsonSerializer.Deserialize(sw, bindingContext.ModelType); 
       } 
      } 
      else 
      { 
       model = ModelBinders.Binders.DefaultBinder.BindModel(controllerContext, bindingContext); 
      } 
      return model; 
     } 
    } 
} 

फिर, Application_Start():: यह भी एक सभा में सभी प्रकार के साथ सामान्यीकृत किया जा सकता है इस प्रकार है

 var asmDto = typeof(SomeDto).Assembly; 
     foreach (var t in asmDto.GetTypes()) 
     { 
      ModelBinders.Binders[t] = new MyModelBinder(); 
     } 
संबंधित मुद्दे