17

पर मूल्य वापस पास करते समय एएसपी.नेट एमवीसी डेटाटाइम संस्कृति समस्या, मैं अपने नियंत्रक/मॉडल को कैसे बता सकता हूं कि डेटाटाइम को पार्स करने के लिए किस तरह की संस्कृति की अपेक्षा करनी चाहिए?नियंत्रक

मैं अपने एमवीसी आवेदन में jquery datepicker को लागू करने के लिए this post का उपयोग कर रहा था।

जब मैं तारीख जमा करता हूं तो यह "अनुवाद में खो जाता है" मैं तारीख के लिए यूएस स्वरूपण का उपयोग नहीं कर रहा हूं, इसलिए जब यह मेरे नियंत्रक को भेजा जाता है तो यह बस शून्य हो जाता है।

मैं एक रूप जहाँ उपयोगकर्ता एक तारीख चुनता है:

@using (Html.BeginForm("List", "Meter", FormMethod.Get)) 
{ 
    @Html.LabelFor(m => m.StartDate, "From:") 
    <div>@Html.EditorFor(m => m.StartDate)</div> 

    @Html.LabelFor(m => m.EndDate, "To:") 
    <div>@Html.EditorFor(m => m.EndDate)</div> 
} 

मैं इस के लिए एक संपादन टेम्पलेट बनाया है, jQuery datepicker लागू करने के लिए:

@model DateTime 
@Html.TextBox("", Model.ToString("dd-MM-yyyy"), new { @class = "date" }) 

मैं तो datepicker बनाने इस तरह के विजेट।

$(document).ready(function() { 
    $('.date').datepicker({ dateFormat: "dd-mm-yy" }); 
}); 

यह सब ठीक काम करता है।

वह स्थान है जहां समस्याओं शुरू, यह मेरा नियंत्रक है:

[HttpGet] 
public ActionResult List(DateTime? startDate = null, DateTime? endDate = null) 
{ 
    //This is where startDate and endDate becomes null if the dates dont have the expected formatting. 
} 

यही कारण है कि मैं किसी भी तरह मेरी नियंत्रक बताने के लिए संस्कृति यह उम्मीद करनी चाहिए चाहते हैं? क्या मेरा मॉडल गलत है? क्या मैं किसी भी तरह से यह बता सकता हूं कि कौन सी संस्कृति का उपयोग करना है, डेटा एनोटेशन विशेषताओं के साथ?

public class MeterViewModel { 
    [Required] 
    public DateTime StartDate { get; set; } 
    [Required] 
    public DateTime EndDate { get; set; } 
} 

संपादित करें: this link मेरी समस्या और अच्छी तरह से इसे करने के लिए एक बहुत अच्छा समाधान बताते हैं। Gdoron

+1

उपयोग एक सब के लिए प्रारूप: इस सरल दृष्टिकोण मुझे वांछित स्थान में मॉडल में प्रबलता से टाइप किये तारीख, शो कार्रवाई लिंक और संपादन फ़ील्ड का उपयोग करें और एक जोरदार टाइप किया दिनांक समय में वापस सब पर उपद्रव करने की यह बाध्यकारी नहीं करने की अनुमति दी अनुरोध। http://stackoverflow.com/a/28219557/960997 – rnofenko

+0

@fomaa अब मैं [altField] (http://api.jqueryui.com/datepicker/#option-altField) और [altFormat] के साथ डेटपिकर का उपयोग करता हूं (http://api.jqueryui.com/datepicker/#option-altFormat) दिनांक के एक संस्कृति इनवेरिएंट संस्करण के साथ एक छिपे हुए क्षेत्र की आपूर्ति करने के विकल्प (जैसा कि आप उल्लेख करते हैं ISO8601)। फिर इसके बजाय उस क्षेत्र को सबमिट करना, मुझे लगता है कि यह एक बेहतर समाधान है। – FRoZeN

उत्तर

11

आप संस्कृति प्रारूप में दिनांक को संभालने के लिए बाइंडर एक्सटेंशन बना सकते हैं।

यह एक नमूना मैं दशमलव प्रकार के साथ एक ही समस्या को संभालने के लिए लिखा है आशा है कि आप विचार प्राप्त

public class DecimalModelBinder : IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
    ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
    ModelState modelState = new ModelState { Value = valueResult }; 
    object actualValue = null; 
    try 
    { 
     actualValue = Convert.ToDecimal(valueResult.AttemptedValue, CultureInfo.CurrentCulture); 
    } 
    catch (FormatException e) 
    { 
     modelState.Errors.Add(e); 
    } 

    bindingContext.ModelState.Add(bindingContext.ModelName, modelState); 
    return actualValue; 
    } 
} 

अद्यतन

यह बस की तरह Global.asax में बांधने की मशीन की घोषणा का उपयोग करने के यह

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 
    RegisterGlobalFilters(GlobalFilters.Filters); 
    RegisterRoutes(RouteTable.Routes); 

    //HERE you tell the framework how to handle decimal values 
    ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder()); 

    DependencyResolver.SetResolver(new ETAutofacDependencyResolver()); 
} 

फिर जब मॉडलबिंडर को कुछ काम करना है, तो यह स्वचालित रूप से पता चलेगा कि क्या करना है। उदाहरण के लिए, यह एक मॉडल के साथ एक क्रिया है जिसमें कुछ प्रकार के गुण दशमलव हैं। मैं बस कुछ भी नहीं करता

[HttpPost] 
public ActionResult Edit(int id, MyViewModel viewModel) 
{ 
    if (ModelState.IsValid) 
    { 
    try 
    { 
     var model = new MyDomainModelEntity(); 
     model.DecimalValue = viewModel.DecimalValue; 
     repository.Save(model); 
     return RedirectToAction("Index"); 
    } 
    catch (RulesException ex) 
    { 
     ex.CopyTo(ModelState); 
    } 
    catch 
    { 
     ModelState.AddModelError("", "My generic error message"); 
    } 
    } 
    return View(model); 
} 
+0

क्या आप अपने कोड से एक उदाहरण दिखा सकते हैं जहां आप इसका इस्तेमाल करते हैं? – FRoZeN

+0

एक उदाहरण के साथ उत्तर अद्यतन किया गया। मुझे उम्मीद है कि यह आपको बेहतर मदद कर सकता है – Iridio

+0

धन्यवाद, इससे मुझे बहुत मदद मिलती है :) – FRoZeN

3

एक तारीख सबमिट करते समय आपको हमेशा "yyyy-MM-dd" प्रारूप में इसे प्रस्तुत करने और सबमिट करने के लिए धन्यवाद। यह संस्कृति को स्वतंत्र बनने की अनुमति देगा।

मेरे पास आमतौर पर एक छिपी हुई फ़ील्ड होती है जो इस प्रारूप में दिनांक रखती है। यह jQuery UI के डेटपिकर का उपयोग करके अपेक्षाकृत सरल है।

+0

@ डिब्बिस्विफ्ट: मैं छिपे हुए क्षेत्र के बारे में सोच रहा था, लेकिन यह सुनिश्चित नहीं था कि यह जाने का रास्ता था, क्योंकि मैं अनैतिक छुपे हुए फ़ील्ड नहीं चाहता हूं। लेकिन अब दूसरी राय के साथ मैं उस दिशा में जा सकता हूं। – FRoZeN

+0

एक छिपे हुए क्षेत्र का लाभ यह है कि आपके पास एक दृश्यमान 'डिस्प्ले' फ़ील्ड हो सकता है जो उपयोगकर्ताओं को उपयोगकर्ता के अनुकूल प्रारूप में एक तिथि प्रदान करने की अनुमति देता है, जबकि छिपे हुए फ़ील्ड को आपके इच्छित प्रारूप में मूल्य को बरकरार रखा जाता है। – Digbyswift

10

यह समस्या उत्पन्न होती है क्योंकि आप अपने फॉर्म पर जीईटी विधि का उपयोग कर रहे हैं। एमवीसी में क्वेरीस्ट्रिंग वैल्यू प्रदाता हमेशा इनवेरिएंट/यूएस डेट प्रारूप का उपयोग करता है।देखें:

  1. पोस्ट करने के लिए अपने विधि बदलें: MVC DateTime binding with incorrect date format

    तीन समाधान कर रहे हैं।

  2. जैसा कि कोई और कहता है, जमा करने से पहले दिनांक प्रारूप को आईएसओ 8601 "yyyy-mm-dd" में बदलें।
  3. हमेशा क्वेरी स्ट्रिंग तिथियों को जीबी के रूप में इलाज करने के लिए कस्टम बाइंडर का उपयोग करें।

    public class DateTimeBinder : IModelBinder 
        { 
         public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
         { 
          var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
          var date = value.ConvertTo(typeof(DateTime), CultureInfo.CurrentCulture); 
    
          return date;  
         } 
        } 
    

    और में IModelBinder का उपयोग कर

    public class UKDateTimeModelBinder : IModelBinder 
    { 
    private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 
    
    /// <summary> 
    /// Fixes date parsing issue when using GET method. Modified from the answer given here: 
    /// https://stackoverflow.com/questions/528545/mvc-datetime-binding-with-incorrect-date-format 
    /// </summary> 
    /// <param name="controllerContext">The controller context.</param> 
    /// <param name="bindingContext">The binding context.</param> 
    /// <returns> 
    /// The converted bound value or null if the raw value is null or empty or cannot be parsed. 
    /// </returns> 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
        var vpr = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
    
        if (vpr == null) 
        { 
         return null; 
    
        } 
    
        var date = vpr.AttemptedValue; 
    
        if (String.IsNullOrEmpty(date)) 
        { 
         return null; 
        } 
    
        logger.DebugFormat("Parsing bound date '{0}' as UK format.", date); 
    
        // Set the ModelState to the first attempted value before we have converted the date. This is to ensure that the ModelState has 
        // a value. When we have converted it, we will override it with a full universal date. 
        bindingContext.ModelState.SetModelValue(bindingContext.ModelName, bindingContext.ValueProvider.GetValue(bindingContext.ModelName)); 
    
        try 
        { 
         var realDate = DateTime.Parse(date, System.Globalization.CultureInfo.GetCultureInfoByIetfLanguageTag("en-GB")); 
    
         // Now set the ModelState value to a full value so that it can always be parsed using InvarianCulture, which is the 
         // default for QueryStringValueProvider. 
         bindingContext.ModelState.SetModelValue(bindingContext.ModelName, new ValueProviderResult(date, realDate.ToString("yyyy-MM-dd hh:mm:ss"), System.Globalization.CultureInfo.GetCultureInfoByIetfLanguageTag("en-GB"))); 
    
         return realDate; 
        } 
        catch (Exception) 
        { 
         logger.ErrorFormat("Error parsing bound date '{0}' as UK format.", date); 
    
         bindingContext.ModelState.AddModelError(bindingContext.ModelName, String.Format("\"{0}\" is invalid.", bindingContext.ModelName)); 
         return null; 
        } 
    } 
    } 
    
+0

+1 यह भी उपयोगी था – FRoZeN

+0

+1, मैंने पोस्ट करने के लिए स्विच किया और मूल्य स्वीकार किए गए। – Malkin

+0

आईएसओ 8601 "yyyy-mm-dd" दिनांक प्रारूप मेरे लिए काम किया। मैं द्विभाषी रूप से संघर्ष कर रहा था और यह एक अच्छा समझौता है। धन्यवाद। – vbocan

18

आप उपयोगकर्ता संस्कृति उपयोग करने के लिए डिफ़ॉल्ट मॉडल बांधने की मशीन बदल सकते हैं: आप ऐसा करते हैं तो आप यह सुनिश्चित करें कि सभी तिथियों उस रूप में कर रहे हैं करने के लिए है Global.asax लिखने:

ModelBinders.Binders.Add(typeof(DateTime), new DateTimeBinder()); 
ModelBinders.Binders.Add(typeof(DateTime?), new DateTimeBinder()); 

this excellent blog का वर्णन क्यों MVC ढांचे टीम एक डीईएफ़ कार्यान्वित पर और अधिक पढ़ें सभी उपयोगकर्ताओं के लिए संस्कृति संस्कृति।

+3

+1 मेरी समस्या को बिल्कुल समझाते हुए बहुत अच्छा ब्लॉग पोस्ट। – FRoZeN

+0

अपवाद फेंक देगा अगर यह एक अमान्य तिथि है। – mikek3332002

+0

मैंने कोशिश की और यह जीईटी के लिए काम नहीं किया, उदाहरण के लिए एक्शनलिंक्स से –

0

कि मुझे

<system.web>  
     <globalization enableClientBasedCulture="true" uiCulture="Auto" culture="Auto" /> 
    </system.web> 
+0

यकीन नहीं है कि मेरी याददाश्त परोसा जाता है, लेकिन यदि आप पोस्ट का उपयोग करते हैं, लेकिन यह नहीं मिलता है तो यह काम करता है। बुलाए गए उत्तरों में से एक में लिंक का पालन करें: एमवीसी डेटटाइम गलत तिथि प्रारूप के साथ बाध्यकारी – FRoZeN

1

के लिए चाल किया क्यों नहीं बस डेटा की संस्कृति का निरीक्षण किया और इस तरह के रूप में यह कन्वर्ट?

public class DateTimeBinder : IModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
     return value.ConvertTo(typeof(DateTime), value.Culture); 
    } 
}