لماذا تعاني ASP.NET MVC عن خصائص القراءة فقط أثناء Databinding؟

StackOverflow https://stackoverflow.com/questions/2211829

سؤال

تحرير: إضافي Bounty لأنني أبحث عن محلول MVC3 (إذا كان أحد موجودا) بخلاف هذا:

dataannotationsmodelvalatorprovider.addimplicitrequiredattttypes = false؛


لدي خاصية قراءة فقط على نموذج "العنوان" 'CityStateZip'.

إنها مجرد وسيلة مريحة للحصول على المدينة والولاية والرمز البريدي من عنوان أمريكي. إنه يلقي استثناء إذا لم تكن البلاد الولايات المتحدة الأمريكية (من المفترض أن يتحقق المتصل أولا).

    public string CityStateZip
    {
        get
        {
            if (IsUSA == false)
            {
                throw new ApplicationException("CityStateZip not valid for international addresses!");
            }

            return (City + ", " + StateCd + " " + ZipOrPostal).Trim().Trim(new char[] {','});
        }
    }

هذا جزء من نموذجي حتى يحصل. قبل ASP.NET MVC2 RC2 هذا الحقل لم يسبق أي مشكلة أثناء Databinding. لم أفكر بالفعل في ذلك - بعد كل شيء لا يقرأ فقط.

الآن مع إصدار RC2 RC2 في يناير 2010، فإنه يعطيني خطأ أثناء Databinding - لأن Becasue يبدو أن الموثق النموذج الافتراضي يريد التحقق من هذه القيمة (على الرغم من قراءة فقط).

إنه خط "base.onmodelupdated" الذي يؤدي إلى تشغيل هذا الخطأ.

public class AddressModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        base.OnModelUpdated(controllerContext, bindingContext);

آخر الدقائق تتغير إلى الموديلات بشكل واضح تسبب في هذا التغيير في السلوك - لكنني لست متأكدا تماما بعد ما يطلق عليه - أو ما إذا كان هذا خطأ أم لا؟ أقدم هذا إلى فريق MVC ولكن فضولي إذا كان أي شخص آخر لديه أي اقتراحات في هذه الأثناء، حيث يمكنني منع هذا العقار من الملزمة.

تستحق هذه المقالة القراءة حول التغييرات - ولكنها لا تذكر الخصائص Readonly على الإطلاق (وليس ذلك أتوقع ذلك). قد تكون المشكلة (إذا كان هناك واحد) أوسع من هذا الموقف - أنا لست متأكدا من أي امام - إن وجدت!

التحقق من صحة الإدخال مقابل التحقق من الصحة في ASP.NET MVC


كما هو مطلوب بواسطة Wachacked إليك StackTrace:

أحصل عليها ببساطة عن طريق إضافة السطر التالي إلى أي نموذج وجعل منشورا إلى طريقة الإجراء المقابلة. في هذه الحالة، أضفتها إلى أبسط نموذج ممكن.

 public string Foo { get { throw new Exception("bar"); } }

targetinvocationException: ملحق الممتلكات 'foo' على الكائنات 'rolling_razor_mvc.models.contactusmodel' ألقى الاستثناء التالي: 'bar'system.componentmodel.reflectpropertydescriptor.getValue (مكون كائن) +390 system.web.mvc. <> c__displayclassb.u003CGetPropertyValueAccessor> B__A () +18 system.web.mvc.modelmetadata.get_model () +22 System.web.mvc.modelmetata.get_realmodeltype () +29 system.web.mvc.u003CGetValidatorsImpl> d__0.movenext () +38 system.linq.u003CSelectManyIterator> d__14`2.movenext () +273 system.web.mvc.u003CValidate> d__5.movenext () +644 system.web.mvc.defaultmodelbinder.onmodelupdated (Controlderconstextextextext، modelbindingcontext bindingcontext) +92 system.web.mvc.defaultmodelbinder.bindcompleExelementalmodel (ControlderContext، ModelBindingContext BindingContext، كائن نموذج) +60 System.Web. mvc.defaultmodelbinder.bindcomplexmodel (Controldercontextext، modelbindingcontext bindingcontextextextextextextex) +1048 system.web.mvc.defaultmodelbinder.bindmodel (controlerercontext controlerercontext، modelbindingcontext bindingcontext) +280 system.web.mvc.controller.tryupdatemodel (نموذج tmodel، بادئة السلسلة، السلسلة [ ] formproperties، سلسلة [] excludeproperties، alexueprovider valueprovider) +449 system.web.mvc.controller.tryupdatemodel (نموذج tmodel) +73

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

المحلول

أعتقد أنني أعاني من مشكلة مماثلة. لقد نشرت التفاصيل:

http://forums.asp.net/t/1523362.aspx.


تعديل: استجابة من فريق MVC (من URL أعلاه):

حققنا في هذا وخلصنا إلى أن نظام التحقق من الصحة يتصرف كما هو متوقع. نظرا لأن التحقق من صحة الطراز ينطوي على محاولة تشغيل التحقق من الصحة على جميع الخصائص، وبما أن خصائص نوع القيمة غير القابلة للانتباه لها سمة ضمنية [مطلوب]، فإننا نتحقق من صحة هذه الخاصية واستدعاء Getter في هذه العملية. نحن نفهم أن هذا تغيير كسر من V1 من المنتج، ولكن من الضروري إجراء نظام التحقق من صحة الطراز الجديد بشكل صحيح.

لديك بعض الخيارات للعمل في جميع أنحاء هذا. أي واحد من هذه يجب أن تعمل:

  • تغيير خاصية التاريخ إلى طريقة بدلا من الممتلكات؛ وبهذه الطريقة سيتم تجاهلها من قبل إطار MVC.
  • تغيير نوع الخاصية إلى DateTime؟ بدلا من dateetime. هذا يزيل الضمني [مطلوب] من هذه الخاصية.
  • امسح DataannotationsModelValatorProvider.addimplicitrequiredattttypaluetypes. هذا يزيل الضمني [مطلوب] من جميع خصائص نوع القيمة غير القابلة للانتباه. نحن ننظر إلى إضافة في V3 من المنتج السمة التي ستشير إلينا "لا ترتبط بها، لا تحقق من صحة ذلك، فقط أدعي أن هذه الخاصية غير موجودة".

شكرا مرة أخرى للتقرير!

نصائح أخرى

لا تزال لها نفس المشكلة مع MVC3.

أعتقد أن أفضل طريقة هي لهذا فقط في Global.asax (من إجابة Sevencentral):

 DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

هذا سوف تعطيل لكل منهم

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

أضفت مزود بيانات META النموذج التالي في حولي للحصول على جولة المشكلة

protected override CachedDataAnnotationsModelMetadata CreateMetadataPrototype(IEnumerable<Attribute> attributes, Type containerType, Type modelType, string propertyName)
{
    var metadata = base.CreateMetadataPrototype(attributes, containerType, modelType, propertyName);

    if (metadata.IsReadOnly)
    {
        metadata.IsRequired = false;
    }

    return metadata;
}

protected override CachedDataAnnotationsModelMetadata CreateMetadataFromPrototype(CachedDataAnnotationsModelMetadata prototype, Func<object> modelAccessor)
{
    var metadata = base.CreateMetadataFromPrototype(prototype, modelAccessor);

    if (prototype.IsReadOnly)
    {
        metadata.IsRequired = false;
    }

    return metadata;
}

ستحتاج أيضا إلى إضافة ما يلي إلى Global.asax.cs

protected void Application_Start()
{
    ModelMetadataProviders.Current = new RESModelMetadataProvider();
    ModelBinders.Binders.Add(typeof(SmartDate), new SmartDateModelBinder());

    ...
}

بالطبع أعتقد أنني يمكن أن تحول CityStateZip ل GetCityStateZip() ولكن بعد ذلك لا أستطيع ربطه بشيء مثل Silverlight بسهولة. قد يعمل هذا في إصلاح مؤقت لأي شخص آخر يعاني من هذه المشكلة.

لدي نفس المشكلة بالضبط!!

لمزيد من المعلومات حول مشكلتي، يمكنك زيارة يتم استدعاء خاصية نموذج ASP.NET MVC 2.0 غير المستخدمة عند نشر منتج إلى الخادم؟

هل هذا يعني أننا نحتاج إلى برمجة خصائصنا مع افتراض أنه سيتم استدعاء بشكل غير متوقع (قبل الخصائص التي تعتمد عليها يتم إعدادها / تهيئة وغيرها) ... إذا كان الأمر كذلك، فإن هذا يمثل تغييرا في ممارسات البرمجة الخاصة بنا وأود ذلك ترغب في معرفة كيفية المتابعة.

وفي الوقت نفسه، لدي فقط "إذا" التحقق من ذلك يتخلص من المشكلة.

كنت أمارس مشكلة مماثلة، كان الحقل الذي لم أتوقع أن يتم التحقق منه من صحة خطأ عند إرسال النموذج مرة أخرى إلى وحدة التحكم. بعد بعض googling، صادفت http://codeblog.shawson.co.uk/mvc-strongly-typed-View-Returns-a-null-model-on-post-back/ حيث تمت الإشارة إلى أن النزاعات الاسم قد تسبب مشاكل.

على الرغم من أنني لا أعتقد أن فئة متغيرة بعد الظهر قد تعارض أسماء الملكية المتعارضة، فإن إعادة تسمية الخاصية تلقي الخطأ حل مشكلتي.

نفس المشكلة لا تزال موجودة في MVC 5.2.3، وليس حتى رمز التحقق مما يؤدي إلى المشكلة. ال DefaultModelBinder يستدعي Getters خارج رمز التحقق من الصحة حتى لو كانت خصائص للقراءة فقط، وحتى إذا لم يتم تمرير بيانات طلب إلى وحدة تحكم مطابقة تلك الخصائص.

انظر شرح أكثر تفصيلا وحلالي الكامل هنا: https://stackoverflow.com/a/54431404/10987278..

لست متأكدا مما إذا كان يمكن إعادة مزعج هذا الحل للعمل مع MVC 3، ولكن نأمل أن يساعد الآخرين في أنهم لا يزال يعانون من نفس المشكلة في الإصدار اللاحق من MVC التي تعثرت عبر هذا السؤال كما فعلت.

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