نموذج ملزمة متعددة نموذج استمارة التقديم من كتابة بشدة عرض

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

سؤال

أواجه مشاكل ملزمة على شكل نماذج عديدة من تقديمها.لدي نموذج الشكوى التي تشمل الشكوى معلومات فضلا عن أن العديد من الشكاوى.أنا أحاول تقديم النموذج ولكن أنا الحصول على الأخطاء على ربط.ModelState.IsValid دوما بإرجاع false.

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

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

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

تحكم التعليمات البرمجية:

    public ActionResult Edit(int id)
    {
        var complaint = (from c in _entities.ComplaintSet.Include("Complainants")
                     where c.Id == id
                     select c).FirstOrDefault();

        return View(complaint);
    }

    //
    // POST: /Home/Edit/5
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(Complaint complaint)
    {
        if (!ModelState.IsValid)
        {
            return View();
        }
        try
        {
            var originalComplaint = (from c in _entities.ComplaintSet.Include("Complainants")
                                     where c.Id == complaint.Id
                                     select c).FirstOrDefault();
            _entities.ApplyPropertyChanges(originalComplaint.EntityKey.EntitySetName, complaint);
            _entities.SaveChanges();
            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }

عرض التعليمات البرمجية (هذا هو نظرة جزئية أن يحصل على ما يسمى طريق إنشاء/تحرير وجهات النظر ، والتي هي أيضا بقوة كتبته مع الشكوى):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ProStand.Models.Complaint>" %>

<%= Html.ValidationSummary() %>
<% using (Html.BeginForm()) {%>

<table cellpadding="0" cellspacing="0" class="table">
    <tr>
        <td>
        <label for="DateReceived">Date Received:</label>
            <%= Html.TextBox("DateReceived") %>
            <%= Html.ValidationMessage("DateReceived", "*") %>    
        </td>
        <td>
            <label for="DateEntered">Date Entered:</label>
            <%= Html.TextBox("DateEntered")%>
            <%= Html.ValidationMessage("DateEntered", "*") %>
        </td>
    </tr>
    <tr>
        <td>
            <label for="Concluded">Concluded:</label>
            <%= Html.CheckBox("Concluded")%>
            <%= Html.ValidationMessage("Concluded", "*") %>
            </td>
        <td>
            <label for="IncidentDate">Incident Date:</label>
            <%= Html.TextBox("IncidentDate")%>
            <%= Html.ValidationMessage("IncidentDate", "*") %></td>
    </tr>
</table>
    <hr />
    <table>
    <% if (Model != null) {
           int i = 0;
       foreach (var complainant in Model.Complainants){ %>
       <%= Html.Hidden("Complainants[" + i + "].Id", complainant.Id)%>
    <tr>
        <td>
            <label for="Surname">Surname:</label>

            <%= Html.TextBox("Complainants[" + i + "].Surname", complainant.Surname)%>
            <%= Html.ValidationMessage("Surname", "*")%>
        </td>
        <td>
            <label for="GivenName1">GivenName1:</label>
            <%= Html.TextBox("Complainants[" + i + "].GivenName1", complainant.GivenName1)%>
            <%= Html.ValidationMessage("GivenName1", "*")%>
        </td>
    </tr>
    <% i++; %>
    <% }} %>
    <tr>
        <td colspan=2>
            <input type="submit" value="Submit" />
        </td>
    </tr>
</table>
<% } %>
<div>
    <%=Html.ActionLink("Back to List", "Index") %>
</div>
هل كانت مفيدة؟

المحلول

أعمى تخمين:

التغيير:

<%= Html.TextBox("Complainants[" + i + "].Surname", complainant.Surname)%>

مع:

<%= Html.TextBox("Complaint.Complainants[" + i + "].Surname",  
complainant.Surname)%>

على التوالي - إضافة "الشكوى" من قبل "الشكوى[..."

تحرير:

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

EDIT2:

قد أكون مخطئا, ولكن بالنسبة لي يبدو أن هناك مشكلة مع الكيان إطار (أو - مع طريقة استخدامه).أعني - asp.net mvc تمكن من قراءة القيم من الطلب ولكن لا يمكن تهيئة الشكوى المجموعة.

هنا إنه مكتوب:

على InitializeRelatedCollection(TTargetEntity) طريقة تهيئة القائمة EntityCollection(TEntity) التي تم إنشاؤها باستخدام منشئ افتراضي.على EntityCollection(TEntity) تمت تهيئته باستخدام المقدمة العلاقة واستهداف دور أسماء.

على InitializeRelatedCollection(TTargetEntity) الطريقة المستخدمة أثناء إلغاء التسلسل فقط.

بعض مزيد من المعلومات:

استثناء:

  • InvalidOperationException

الشروط:

  • عندما قدمت EntityCollection(TEntity) مهيأ مسبقا.
  • عندما تكون العلاقة مدير تعلق بالفعل إلى ObjectContext.
  • عندما مدير العلاقات يحتوي بالفعل على علاقة مع هذا الاسم و المهنة.

Somewhy InitializeRelatedCollection يطرد مرتين.لسوء الحظ ليس لدي أية أفكار لماذا بالضبط.ربما هذا التحقيق الصغير سوف تساعد شخص آخر - أكثر خبرة مع EF.:)

EDIT3:
هذا ليس حلا لهذه المشكلة ، الحل و الطريقة المناسبة للتعامل مع نموذج جزء من mvc.

إنشاء viewmodel لأغراض العرض فقط.إنشاء نطاق جديد نموذج من محض POCOs ' أيضا (لأن EF الدعم لهم في النسخة المقبلة فقط).استخدام AutoMapper إلى خريطة EFDataContext<=>نموذج<=>ViewModel.

من شأنه أن يستغرق بعض الجهد, ولكن هذا ما يجب أن يكون التعامل معها.يزيل هذا النهج عرض المسؤولية من النموذج الخاص بك ، ينظف المجال الخاص بك نموذج (يزيل EF الاشياء من النموذج الخاص بك) وسوف تحل مشكلتك مع ملزمة.

نصائح أخرى

public ActionResult Edit([Bind(Exclude = "Complainants")]Complaint model)
{
  TryUpdateModel(model.Complainants, "Complainants");
  if (!ModelState.IsValid)
  {
      // return the pre populated model
      return View(model);
  }

}

يعمل هذا بالنسبة لي!

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

لحصول على هذا العمل دون كل حالة على حدة الحلول التي تحتاج إليها لخلق بنفسك نموذج الموثق وطريقة تجاوز SetProperty:

public class MyDefaultModelBinder : DefaultModelBinder
{
    protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
    { 
        ModelMetadata propertyMetadata = bindingContext.PropertyMetadata[propertyDescriptor.Name]; 
        propertyMetadata.Model = value;
        string modelStateKey = CreateSubPropertyName(bindingContext.ModelName, propertyMetadata.PropertyName);

        // Try to set a value into the property unless we know it will fail (read-only 
        // properties and null values with non-nullable types)
        if (!propertyDescriptor.IsReadOnly) { 
        try {
            if (value == null)
            {
            propertyDescriptor.SetValue(bindingContext.Model, value);
            }
            else
            {
            Type valueType = value.GetType();

            if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(EntityCollection<>))
            {
                IListSource ls = (IListSource)propertyDescriptor.GetValue(bindingContext.Model);
                IList list = ls.GetList();

                foreach (var item in (IEnumerable)value)
                {
                list.Add(item);
                }
            }
            else
            {
                propertyDescriptor.SetValue(bindingContext.Model, value);
            }
            }

        }
        catch (Exception ex) {
            // Only add if we're not already invalid
            if (bindingContext.ModelState.IsValidField(modelStateKey)) { 
            bindingContext.ModelState.AddModelError(modelStateKey, ex); 
            }
        } 
        }
    }
}

ولا ننسى لتسجيل الموثق الخاص بك في Global.asax:

ModelBinders.Binders.DefaultBinder = new MyDefaultModelBinder();

وعملت في جميع أنحاء استثناء ModelBinding طريق القيام بما يلي:

// Remove the error from ModelState which will have the same name as the collection.
ModelState.Remove("Complaints"/*EntityCollection*/); 
if (ModelState.IsValid) // Still catches other errors.
{
    entities.SaveChanges(); // Your ObjectContext
}

والعيب الرئيسي هو أن الاستثناء لا يزال القيت والتي يمكن أن تكون مكلفة في وقت التشغيل. عمل رائع في جميع أنحاء قد تكون لخلق التفاف حول DefaultBinder الحالية ومنعها من instantiating في EntityCollection مرة أخرى، وهو ما قامت به بالفعل EF. ثم ملزم أن جمع إلى القيم النموذج (FormCollection).

ونضع في الاعتبار إذا كنت ملزمة جمع أكثر من واحد، وسوف تحتاج إلى إزالة الخطأ لكل مجموعة.

في تجربتي، وجمع حفظ بنجاح وكذلك الكائن الجذر في الرسم البياني الذي كان جمع جزءا منها.

وعلى أمل أن يساعد شخص آخر.

وكان لي مشكلة مماثلة! في النهاية سوف تجد أن الإطار لا يمكن معالجة النماذج المعقدة.

وكتبت المكون ملزم القليل الذي يمكن تهيئة الارتباطات المعقدة على وظيفة.

ولكن في الأساس ما عليك القيام به هو ما أرنيس L. تقول.

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