2010-02-16 22 views
7

"Emir" modeline form gönderimlerini bağlamanız gereken normal bir durum olduğunu düşündüğüm şey var. Bu model buna bilgilerin birkaç seviyesi vardır:DefaultModelBinder Yuvalanmış düzeyler + diğer bağlayıcılarla ilgili sorun

: Ben param aşağıdaki alanları JustWork (TM) olarak bu al modeli alır bir eylem için bir form POST eğer

Order.Billing.FirstName 
Order.Billing.Address.City 
Order.Billing.Address.Country 

, DefaultModelBinder kullanma

<%=Html.TextBox("Billing.FirstName")%> 
<%=Html.TextBox("Billing.Address.City")%> 

Bu alan yapmaz:

<%=Html.TextBox("Billing.Address.Country")%> 

Ben kırışıklık ülke özelliğiyle olduğunu. Bizim durumumuzda, Address.Country bir Country sınıf örneği (ISO2/3/Name/Code mantığı) döndürür. Bu bir ip değil. Varsayılan olarak çalışmadığı sürpriz değil.

İlk düşüncem CountryModelBinder (inherit DefaultModelBinder) ve ModelBinders.Binders.Add'ı Ülke türüne eklemek oldu. Bunu yaptığımda, CountryModelBinder asla yukarıdaki senaryoda çağrılır.

İkinci düşüncem bir AddressModelBinder (inherit DefaultModelBinder) oluşturmak ve Adres türümüze bağlamaktı. Bu çağrılırken, form "Billing.Address.Country" adlı bir alan yayınlasa bile, SetProperty çağrısı "Ülke" için boş bir değere sahiptir.

Bazı tamir ettikten sonra, model bağlama davranışı yalnızca model, eylemin istediği en üst düzey sınıf olduğunda CreateModel'i çağırır ve diğer tüm bağlayıcıların BindPropery/SetProperty alt öğeleri için çağrılır. Başka bir deyişle, Sipariş, OrderAddress (Faturalama), Adres ve Ülke için model bağlayıcılar oluşturursam, başka bir deyişle. Siparişi alan eylem için yalnızca OrderModelBinder.CreateModel çağrılır. ORDERAdres ve Address.BindProperty/SetProperty, bazı şeyler için çağrılır ve bazen SetProperty değer argümanı, açıkça diğer alan özellik eşleştirmeleriyle eşleşen bir adda yayınlandığında boştur.

Sadece OrderModelBinder'a kod eklemek için Billing.Address.Country'i Request.Form'dan çıkarmak yeterlidir. Fakat Adres'i kullanan ve hepsine sahip olan birden fazla modelim var.

Burada nelerin eksik? CountryModelBinder'ın gerçekten bu durumda aranmasını sağlamak için bir yol var mı? Billing.Address.Country, Address ciltleyicinin Country özelliğine eşlendiğinde CountryModelBinder'ın çağrılması gerektiğini düşünürdüm.

+0

bu yardımcı olabilir: http://stackoverflow.com/questions/2462506/model-binding-with-nested-child-models-and-partialviews-in-asp-net-mvc – Will

+0

Aynı sorunu yaşıyorum Yuvalanmış bir model yapısına sahip, bana göre, üst düzeydeki mülkler ve bir seviye aşağıya doğru gidiyor, ama bundan daha düşük bir şey göz ardı ediliyor gibi görünüyor. Bu model bağlayıcı normal davranış mı? Oldukça keyfi davranışlar gibi görünüyor. – UpTheCreek

cevap

0

Burada yaptığınız şeyi yapmayı denedim, MVC3 üzerinde görünmüyor, bu tür için bir model ciltleyici sağlarsam gerçekten işe yarar.

Bu kavramın sadece bir kanıtı bu ÇALIŞIR ve üretim seviyesi kodu olarak bile yakın görülmemelidir göstermektir:

Modeller:

public class SimpleModel 
    { 
     public string Value { get; set; } 
     public int Other { get; set; } 
    } 

    public class ComplexModel 
    { 
     public SimpleModel Complexity {get;set;} 
     public string StrVal { get; set; } 
    } 

bazı bağlayıcı:

küresel asax içinde
public class MBinder : IModelBinder 
     { 
      public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
      { 
       if (bindingContext.ModelType == typeof(SimpleModel)) 
       { 
        var simpleModel= new SimpleModel(); 
        simpleModel.Other = 1; 
        simpleModel.Value = controllerContext.HttpContext.Request.Form["Complexity"]; 

        return cm; 
       } 
       return null; 
      } 
     } 

:

ModelBinders.Binders.Add(typeof (SimpleModel), new MBinder()); 
Görünümünde

kod:

@model ComplexModel 

    @using (Html.BeginForm()) 
{ 
    <fieldset> 
     @Html.LabelFor(x => x.Complexity) 
     @Html.TextBoxFor(x => x.Complexity) 
    </fieldset> 

    <fieldset> 
     @Html.LabelFor(x => x.StrVal) 
     <br /> 
     @Html.EditorFor(x => x.StrVal) 
    </fieldset> 
    <input type="submit" /> 
} 

Denetleyici:

public ActionResult Index() 
     { 
      return View(); 
     } 

     [HttpPost] 
     public ActionResult Index(ComplexModel model) 
     { 
      return RedirectToAction("Index"); 

     } 

BTW MVC 3'te daha iyi bir seçenek IModelBinderProvider arayüzünü kullanmak olacaktır, ama sadece çalışacak bir şey göstermek istiyorum.