2012-02-27 14 views
8

एमवीसी 4 के नए सिंगल पेज एप्लिकेशन टूलींग के साथ खेलते समय, मैंने देखा कि मेरे द्वारा प्राप्त किए गए किसी भी उदाहरण में वेबटाई के माध्यम से डेटटाइम को अपडेट नहीं किया गया है। मुझे जल्द ही पता चला क्यों।एमवीसी 4 सिंगल पेज एप्लिकेशन और डेटटाइम

मैंने प्रदान किए गए टेम्पलेट से मानक एसपीए उत्पन्न करके शुरू किया। मैंने फिर TodoItem.cs खोला और डेटटाइम फ़ील्ड जोड़ा। फिर मैंने टिप्पणियों द्वारा निर्देशित नियंत्रक उत्पन्न किया। (डेटाटाइम फ़ील्ड के बिना, सब कुछ ठीक काम करता है)।

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

कोई त्रुटि उत्पादन किया गया था ने कहा कि:

Server error: HTTP status code: 500, message: There was an error deserializing the object of type System.Web.Http.Data.ChangeSetEntry[]. DateTime content '01/01/2012' does not start with '/Date(' and end with ')/' as required for JSON.

ऐसा लगता है कि टूलींग अभी तक दिनांक समय समर्थन नहीं करता। मुझे यकीन है कि मैं जा सकता हूं और इसे समझने में थोड़ा सा समय बिता सकता हूं, लेकिन मैंने सोचा कि मुझे यहां कुछ भाग्य मिल सकता है जो इस समस्या को पहले ही तय कर चुका है और अंतर्दृष्टि प्रदान कर सकता है।

कोई भी पहले ही इस से जूझ रहा है?

अद्यतन: मैं यह पूछने के बाद से मिली अधिक जानकारी जोड़ रहा हूं। मैंने जेएसओएननेट को मेरे फॉर्मेटर के रूप में नीचे सुझाए गए अनुसार प्रयोग करने का प्रयास किया। मुझे लगता है कि यह अंतिम समाधान होगा, हालांकि, सिफारिश की गई पोस्टर के रूप में बस इतना करना पर्याप्त नहीं है।

This DataController does not support operation 'Update' for entity 'JObject'.

कारण यह है कि पूरी तरह से JSON.Net उद्देश्य यह है कि फ़ॉर्मेटर (सिस्टम को deserailize कोशिश कर रहा है पॉप्युलेट नहीं करता है:

JSON.Net serializer का उपयोग कर, मैं निम्नलिखित त्रुटि मिलती है। Web.Http.Data.ChangeSet)।

json में भेज दिया जाता है वह यह है कि:

[{"Id":"0", 
    "Operation":2, 
    "Entity": 
    {"__type":"TodoItem:#SPADateProblem.Models", 
    "CreatedDate":"/Date(1325397600000-0600)/", 
    "IsDone":false, 
    "Title":"Blah", 
    "TodoItemId":1}, 
    "OriginalEntity": 
    {"__type":"TodoItem:#SPADateProblem.Models", 
    "CreatedDate":"/Date(1325397600000-0600)/", 
    "IsDone":false, 
    "Title":"Blah", 
    "TodoItemId":1} 
}] 

Json फ़ॉर्मेटर में बनाया इकाई में embeded TodoItem वस्तुओं और OriginalEntity क्षेत्रों के साथ एक ChangeSet वस्तु में इस Json पुनर्गठित करने में सक्षम है।

क्या किसी ने JSON.Net को ठीक से deserialize करने के लिए प्राप्त किया है?

+0

आपकी समस्या को पुन: पेश करने की अनुमति देने वाला कुछ कोड वास्तव में उपयोगी होगा। –

+0

दुर्भाग्य से, मुझे पूरा समाधान प्रदान करने की आवश्यकता होगी। प्रदान किया गया एकल पृष्ठ आवेदन टेम्पलेट बहुत सारे कोड उत्पन्न करता है। त्रुटि को पुन: उत्पन्न करने के लिए, बस एक नया एमवीसी 4 एकल पृष्ठ अनुप्रयोग बनाएं। टूलिंग खत्म हो जाने के बाद, TodoItem.cs खोलें और डेटाटाइम फ़ील्ड जोड़ें। फिर "नियंत्रक" पर राइट क्लिक करें और एक नियंत्रक जोड़ें। इसके लिए एक नाम चुनें, अपने मॉडल के रूप में TodoItem का चयन करें, एसपीए टेम्पलेट और इसे एक नया संदर्भ बनाने दें। एक बार ऐसा करने के बाद, एप्लिकेशन चलाएं और नए नियंत्रक पर नेविगेट करें। जोड़ें पर क्लिक करें और डेटा दर्ज करें, फिर सहेजें पर क्लिक करें। –

उत्तर

3

समस्या यह है कि वर्तमान बीटा में, एएसपी.नेट वेब एपीआई DataContractJsonSerializer का उपयोग करता है, जिसमें DateTime के क्रमिकरण के साथ जाने-माने समस्याएं हैं। Here is इस मुद्दे के लिए माइक्रोसॉफ्ट कनेक्ट पर हाल ही में उठाए गए बग को शांत करें; एमएस जवाब देता है कि उनके पास पहले से ही इस मुद्दे को ट्रैक करने वाला एक बग है लेकिन इसे .NET 4.5/VS11 टाइमफ़्रेम में ठीक नहीं किया जाएगा।

सौभाग्य से आप एक वैकल्पिक JSON serializer, जैसे James Newton-King's उत्कृष्ट JSON.Net को प्रतिस्थापित कर सकते हैं।

एएसपी.नेट टीम पर हेनरिक नील्सन के पास excellent blog पोस्ट है जो दिखाता है कि आप एएसपी.नेट वेब एपीआई के साथ JSON.Net का उपयोग कैसे कर सकते हैं। यहां MediaTypeFormatter का कार्यान्वयन है जो JSON.Net का उपयोग करता है (इसे एएसपी.नेट वेब एपीआई कॉन्फ़िगरेशन तक भी तारित करने की आवश्यकता होगी, हेनरिक का ब्लॉग भी प्रदर्शित करता है)।

public class JsonNetFormatter : MediaTypeFormatter 
{ 
    private readonly JsonSerializerSettings settings; 

    public JsonNetFormatter(JsonSerializerSettings settings = null) 
    { 
     this.settings = settings ?? new JsonSerializerSettings(); 

     SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json")); 
     Encoding = new UTF8Encoding(false, true); 
    } 

    protected override bool CanReadType(Type type) 
    { 
     return type != typeof(IKeyValueModel); 
    } 

    protected override bool CanWriteType(Type type) 
    { 
     return true; 
    } 

    protected override Task<object> OnReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext) 
    { 
     var ser = JsonSerializer.Create(settings); 

     return Task.Factory.StartNew(() => { 
      using (var strdr = new StreamReader(stream)) 
      using (var jtr = new JsonTextReader(strdr)) 
      { 
       var deserialized = ser.Deserialize(jtr, type); 
       return deserialized; 
      } 
     }); 
    } 

    protected override Task OnWriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext, TransportContext transportContext) 
    { 
     JsonSerializer ser = JsonSerializer.Create(settings); 

     return Task.Factory.StartNew(() => 
     { 
       using (JsonTextWriter w = new JsonTextWriter(new StreamWriter(stream, Encoding)) { CloseOutput = false}) 
       { 
        ser.Serialize(w, value); 
        w.Flush(); 
       } 
     }); 
    } 
}  
+0

मुझे लगता है कि यह सही उत्तर के करीब हो सकता है, लेकिन यह ऊपर बताए गए परिदृश्य के साथ काम नहीं कर रहा है। इस कोड का उपयोग करने और इसे वेबपी में प्लग करने के बाद, सहेजने का प्रयास करते समय निम्न त्रुटि ट्रिगर होती है: सर्वर त्रुटि: HTTP स्थिति कोड: 500, संदेश: यह डेटा नियंत्रक इकाई 'जॉब्जेक्ट' के लिए ऑपरेशन 'अपडेट' का समर्थन नहीं करता है। यह upshot.js के साथ एक समस्या हो सकती है, लेकिन मैं यह पता लगाने में सक्षम नहीं हूं कि यह त्रुटि अभी तक कहां से आ रही है। –

+0

मुझे इस पूरे पथ को काफी छोड़ना पड़ा है। जेसन.Net जवाब होना प्रतीत होता था, लेकिन यह जेसन प्रारूप का सम्मान करने के लिए प्राप्त कर रहा था कि upshot.js सिंगल पेज एप्लिकेशन में चाहता था उदाहरण उदाहरण कोड एक प्रमुख सिरदर्द था कि मैं बस सही काम नहीं कर सका। दिन के अंत में, मैं इसे एमवीसी 3 में तेज़ी से कर सकता हूं और उम्मीद कर सकता हूं कि एमवीसी 4 इन चीजों के लिए समर्थन जोड़ें। मैं इसे उत्तर के रूप में चिह्नित करने जा रहा हूं क्योंकि पोस्टर ने इसे एक बग के रूप में प्रदर्शित किया था। –

+0

उत्तर स्वीकार करने के लिए धन्यवाद; JSON.Net तक पहुंचने के लायक हो सकता है और यह देखने के लिए एक बग उठा सकता है कि JSON.Net को ठीक किया जा सकता है (या पैच सबमिट करें!) –

0

JSON।नेट को $ प्रकार की उम्मीद है जबकि आपके पास इकाई प्रकार को sopcify करने के लिए __type है, जिससे यह इसे जॉब्जेक्ट में बदल देता है।

मैं निम्नलिखित klunk

पहले यह सुनिश्चित कर लें के साथ यह दौर है कि JsonSerializerSettings has .TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Objects;

तो लिखना अपनी खुद की `` `` JsonTextReader

public class MyJsonTextReader : JsonTextReader 
{ 
    public MyJsonTextReader(TextReader reader) 
     : base(reader) 
    { } 

    public override object Value 
    { 
     get 
     { 
      var o = new ActivityManager.Models.Sched_ProposedActivities(); 

      if (TokenType == JsonToken.PropertyName && base.Value.ToString() == "__type") 
       return "$type"; 
      if (TokenType == JsonToken.String && Path.ToString().EndsWith(".__type")) 
      { 
       string s = base.Value.ToString(); 
       var typeName = Regex.Match(s, ":#.*").ToString().Substring(2) + "." + Regex.Match(s, "^.*:#").ToString().Replace(":#", ""); 

       return 
        typeName + ", ActivityManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; 
      } 

      return base.Value; 
     } 
    } 
} 

और इसका इस्तेमाल `` `` (MyJsonTextReader jsonTextReader = नए MyJsonTextReader (StreamReader)) का उपयोग कर

1

मैं हो रही थी साथ Json deserialise को एक ही समस्या है। मैंने json.net को काम करने की कोशिश करने में बहुत अधिक समय बिताया।

self.IsDone = ko.observable(data.IsDone); 
    self.EnterDate = ko.observable(data.EnterDate); 
    self.DateJson = ko.computed({ 
     read: function() { 
      if (self.EnterDate() != undefined) { 
       var DateObj = new Date(parseInt(self.EnterDate().replace("/Date(", "").replace(")/", ""), 10)); //.toDateString(); 
       var ret = DateObj.getMonth() + 1 + "/" + DateObj.getDate() + "/" + DateObj.getFullYear(); 
       return ret; 
      } 
      else { 
       return self.EnterDate(); 
      } 
     }, 
     write: function (value) { 
      var formattedDate = "\/Date(" + Date.parse(value) + ")\/" 
      self.EnterDate(formattedDate); 
     } 
    }); 
    upshot.addEntityProperties(self, entityType); 

कोड के आसपास लाइनों संदर्भ के लिए शामिल किया गया: मैं अंत में इस समाधान है कि आप उदाहरण परियोजना में TodoItemsViewModel.js में रहना होगा के साथ आया था। मैं कम से टिप्पणी में यह पाया: http://blog.stevensanderson.com/2012/03/06/single-page-application-packages-and-samples/

तुम भी "DateJson" करने के लिए बाध्य करने के लिए _Editor.cshtml में एचटीएमएल बदलना चाहते हैं, न कि "EnterDate"

यह निश्चित रूप से एक kludge है लेकिन इसके बारे में पुण्य है काम करना जो कोई छोटी सी काम नहीं है।

1

आप निम्न कोड जोड़कर काम करने के लिए JQuery कैलेंडर पॉपअप भी प्राप्त कर सकते हैं।

ko.bindingHandlers.datepicker = { 
    init: function (element, valueAccessor, allBindingsAccessor) { 
     //initialize datepicker with some optional options 
     var options = allBindingsAccessor().datepickerOptions || {}; 
     $(element).datepicker(options); 

     //handle the field changing 
     ko.utils.registerEventHandler(element, "change", function() { 
      var observable = valueAccessor(); 
      observable($(element).datepicker("getDate")); 
     }); 

     //handle disposal (if KO removes by the template binding) 
     ko.utils.domNodeDisposal.addDisposeCallback(element, function() { 
      $(element).datepicker("destroy"); 
     }); 

    }, 
    update: function (element, valueAccessor) { 
     var value = ko.utils.unwrapObservable(valueAccessor()), 
     current = $(element).datepicker("getDate"); 

     if (value - current !== 0) { 
      //$(element).datepicker("setDate", value); 
      $(element).val(value.toString()); 
     } 
    } 
} 

ko.bindingHandlers.date = { 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) { 
     var jsonDate = "/Date(12567120000-1000)/"; 
     var value = new Date(parseInt(jsonDate.substr(6))); 
     var ret = value.getMonth() + 1 + "/" + value.getDate() + "/" + value.getFullYear(); 
     element.innerHTML = ret; 
    }, 

    update: function (element, valueAccessor, allBindingsAccessor, viewModel) { 
    } 
}; 

यह आपके _Editor.cshtml कोड datepicker

<p> 
    EnterDate: 
    @*<input name="EnterDate" data-bind="value: EnterDate, autovalidate: true" /> 
    <span class="error" data-bind="text: EnterDate.ValidationError"></span>*@ 
    <input name="DateJson" data-bind="datepicker: DateJson, datepickerOptions: { minDate: new Date() }" /> 
    <span class="error" data-bind="text: DateJson.ValidationError"></span> 

</p> 
करने के लिए बाध्य करने के लिए दिखाई देगा क्या है:

MVC 4 एसपीए परियोजना उदाहरण में TodoItemsViewModel.js के निचले भाग में इस जोड़े

इसके अलावा, आप "EnterDate" से "DateJson" में _Grid.cshtml पृष्ठ पर प्रदर्शित चर को बदलना चाहते हैं।

संबंधित मुद्दे