سؤال

أود أن أكتب موثق النموذج الخاص بي DateTime يكتب. بادئ ذي بدء ، أود أن أكتب سمة جديدة يمكنني إرفاقها على خاصية النموذج الخاصة بي مثل:

[DateTimeFormat("d.M.yyyy")]
public DateTime Birth { get; set,}

هذا هو الجزء السهل. لكن جزء الموثق أكثر صعوبة قليلاً. أرغب في إضافة موثق طراز جديد للنوع DateTime. يمكنني إما

  • ينفذ IModelBinder واجهة واكتب بلدي BindModel() طريقة
  • ورث من DefaultModelBinder والتجاوز BindModel() طريقة

النموذج الخاص بي لديه خاصية كما هو موضح أعلاه (Birth). لذلك عندما يحاول النموذج ربط البيانات بالطلب على هذه الخاصية BindModel(controllerContext, bindingContext) يتم الاحتجاج. كل شيء على ما يرام ، ولكن. كيف أحصل على سمات خاصية من وحدة التحكم/bindingContext ، لتحليل تاريخ بلدي بشكل صحيح؟ كيف يمكنني الوصول إلى PropertyDesciptor الممتلكات Birth?

يحرر

نظرًا لفصل المخاوف ، يتم تعريف فئتي النموذجية في مجموعة لا (ولا ينبغي) مرجعًا). تحديد الربط المخصص (على غرار مثال سكوت هانسلمان) السمات هي عدم وجود هنا.

هل كانت مفيدة؟

المحلول

لا أعتقد أنك يجب أن تضع سمات خاصة بالمكان على النموذج.

حلولان آخران لهذه المشكلة هما:

  • اطلب من صفحاتك تواريخ ترجمة من التنسيق المحدد إلى تنسيق عام مثل Yyyy-MM-DD في JavaScript. (يعمل ، ولكنه يتطلب javaScript.)
  • اكتب الموثق النموذجي الذي يأخذ في الاعتبار ثقافة واجهة المستخدم الحالية عند تحليل التواريخ.

للإجابة على سؤالك الفعلي ، طريقة الحصول على سمات مخصصة (لـ MVC 2) هي اكتب AssociatedMetAdataprovider.

نصائح أخرى

يمكنك تغيير موثق النموذج الافتراضي لاستخدام ثقافة المستخدم باستخدام ImodelBinder

public class DateTimeBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        bindingContext.ModelState.SetModelValue(bindingContext.ModelName, value);

        return value.ConvertTo(typeof(DateTime), CultureInfo.CurrentCulture);
    }
}

public class NullableDateTimeBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        bindingContext.ModelState.SetModelValue(bindingContext.ModelName, value);

        return value == null
            ? null 
            : value.ConvertTo(typeof(DateTime), CultureInfo.CurrentCulture);
    }
}

وفي Global.asax ، أضف ما يلي إلى application_start ():

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

اقراء المزيد على هذه المدونة الممتازة هذا يصف سبب قيام فريق MVC Framework بتنفيذ ثقافة افتراضية لجميع المستخدمين.

واجهت هذه المشكلة الكبيرة جدًا بنفسي وبعد ساعات من المحاولة وفشل ، حصلت على حل عمل كما طلبت.

بادئ ذي بدء ، نظرًا لأن الحصول على رابط على خاصية فقط ليس من الممكن أن يكون Yuo هو تطبيق نموذج كامل. نظرًا لأنك لا تريد ربط جميع الخصائص الفردية ولكن فقط تلك التي تهتم بها يمكن أن ترثها من DefaultModelBinder ثم ربط الخاصية المفردة:

public class DateFiexedCultureModelBinder : DefaultModelBinder
{
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor)
    {
        if (propertyDescriptor.PropertyType == typeof(DateTime?))
        {
            try
            {
                var model = bindingContext.Model;
                PropertyInfo property = model.GetType().GetProperty(propertyDescriptor.Name);

                var value = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name);

                if (value != null)
                {
                    System.Globalization.CultureInfo cultureinfo = new System.Globalization.CultureInfo("it-CH");
                    var date = DateTime.Parse(value.AttemptedValue, cultureinfo);
                    property.SetValue(model, date, null);
                }
            }
            catch
            {
                //If something wrong, validation should take care
            }
        }
        else
        {
            base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
        }
    }
}

في مثالي ، أقوم بتجفيف التاريخ بثقافة منتفخة ، لكن ما تريد القيام به ممكن. يجب عليك إنشاء CustomAttribute (مثل DateTimeFormatAttribute) ووضعها فوق خاصية لك:

[DateTimeFormat("d.M.yyyy")]
public DateTime Birth { get; set,}

الآن في طريقة BindProperty ، بدلاً من البحث عن خاصية DateTime ، يمكنك البحث عن خاصية مع DateTimeFormatTribut

آمل أن يساعد هذا الأمر ، استغرق الأمر وقتًا طويلاً لأتمكن من الوصول إلى هذا الحل. كان من السهل في الواقع الحصول على هذا الحل بمجرد أن أعرف كيفية البحث عنه :(

يمكنك تنفيذ موثق مخصص لوقت DateTime مثل ذلك ، ولكن عليك أن تهتم بالثقافة المفترضة والقيمة من طلب العميل الفعلي. قد تحصل على موعد مثل mm/dd/yyyy في en-us وتريد تحويلها في ثقافة الأنظمة en-gb (والتي ستكون مثل Dd/mm/yyyy) أو ثقافة ثابتة ، كما نفعل ، ثم أنت يجب تحليلها من قبل واستخدام الواجهة الثابتة تحويلها لتغييرها في سلوكها.

    public class DateTimeModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var valueResult = bindingContext.ValueProvider
                              .GetValue(bindingContext.ModelName);
            var modelState = new ModelState {Value = valueResult};

            var resDateTime = new DateTime();

            if (valueResult == null) return null;

            if ((bindingContext.ModelType == typeof(DateTime)|| 
                bindingContext.ModelType == typeof(DateTime?)))
            {
                if (bindingContext.ModelName != "Version")
                {
                    try
                    {
                        resDateTime =
                            Convert.ToDateTime(
                                DateTime.Parse(valueResult.AttemptedValue, valueResult.Culture,
                                    DateTimeStyles.AdjustToUniversal).ToUniversalTime(), CultureInfo.InvariantCulture);
                    }
                    catch (Exception e)
                    {
                        modelState.Errors.Add(EnterpriseLibraryHelper.HandleDataLayerException(e));
                    }
                }
                else
                {
                    resDateTime =
                        Convert.ToDateTime(
                            DateTime.Parse(valueResult.AttemptedValue, valueResult.Culture), CultureInfo.InvariantCulture);
                }
            }
            bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
            return resDateTime;
        }
    }

على أي حال ، تعتمد الثقافة على تحليل DateTime في تطبيق عديمي الجنسية من خلال القسوة ... خاصةً عندما تعمل مع JSON على JavaScript Companside و Rackwards.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top