2010-01-08 16 views
6

ASP.NET MVC2 ile bazı denemeler yapıyorum ve ilginç bir sorunla karşılaştım.DataAnnotation Validations ve Özel ModelBinder

MVC uygulamasında Model olarak kullanılacak nesnelerin çevresinde bir arabirim tanımlamak istiyorum. Ek olarak, bu arabirimin üyelerini doğrulama öznitelikleriyle işaretleyerek, yeni DataAnnotation'dan faydalanmak istiyorum.

sitemde "Fotoğraf" nesnesine sahipse yani, ben şu arayüzünü tanımlarsınız:

public interface IPhoto 
{ 
[Required] 
string Name { get; set; } 

[Required] 
string Path { get; set; } 
} 

Ve şu uygulanmasını tanımlarsınız:

public class PhotoImpl : IPhoto 
{ 
public string Name { get; set; } 
public string Path { get; set; } 
} 

My MVC uygulama denetleyici aşağıdaki yöntemleri içerebilir:

public class PhotoController : Controller 
{ 
[HttpGet] 
public ActionResult CreatePhoto() 
{ 
    return View(); 
} 

[HttpPost] 
public ActionResult CreatePhoto(IPhoto photo) 
{ 
    if(ModelState.IsValid) 
    { 
    return View(); 
    } 
    else 
    { 
    return View(photo); 
    } 

} 
} 

Ve son olarak, PhotoImpls'ı bu ac içindeki parametrelere bağlamak için benim denetleyicisi ModelState.IsValid özellik geçersiz değerler (diyelim ki, null) fark görünmüyor o

public class PhotoModelBinder : DefaultModelBinder 
{ 
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
    if(bindingContext.ModelType == typeof(IPhoto)) 
    { 
    IPhoto photo = new PhotoImpl(); 
    // snip: set properties of photo to bound values 
    return photo; 
    } 

    return base.BindModel(controllerContext, bindingContext); 
} 
} 

Her şey dışında harika çalışıyor görünüyor: tion yöntemleri, ben DefaultModelBinder aşağıdaki uzantılarını uygulamaya olabilir IPhoto uygulamasının [Zorunlu] özellikleri.

ModelBinder uygulamamda önemli bir devlet parçası koymayı ihmal ettiğimi sanıyorum. Herhangi bir ipucu?

cevap

7

System.Web.MVC.DefaultModelBinder kaynağını inceledikten sonra, bunun biraz farklı bir yaklaşımla çözülebileceği anlaşılıyor. BindModel'in temel uygulamasına daha çok güvenirsek, IPhoto'dan doğrulama özniteliklerini çekerken PhotoImpl nesnesini oluşturabiliriz. gibi

şey:

public class PhotoModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     if (bindingContext.ModelType == typeof(IPhoto)) 
     { 
      ModelBindingContext newBindingContext = new ModelBindingContext() 
      { 
       ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(
        () => new PhotoImpl(), // construct a PhotoImpl object, 
        typeof(IPhoto)   // using the IPhoto metadata 
       ), 
       ModelState = bindingContext.ModelState, 
       ValueProvider = bindingContext.ValueProvider 
      }; 

      // call the default model binder this new binding context 
      return base.BindModel(controllerContext, newBindingContext); 
     } 
     else 
     { 
      return base.BindModel(controllerContext, bindingContext); 
     } 
    } 
} 
0

Modelinize [Zorunlu] özniteliğini yerleştirmeyi ve yeniden denemeyi denediniz mi? Bir arabirime özniteliği uygulamada zorluk çekiyor olabilir.

+0

teşekkür :-) doğrulama ile kendi şeyler yapalım yapabilirsiniz ... CreateModel() geçersiz kılmak cevap. [Zorunlu] özniteliğinin yeriyle ilgili bir sorun görünmüyor. Öznitelikleri PhotoImpl'e taşıdığımda, Denetleyiciyi bir PhotoImpl üzerinde çalışacak şekilde değiştirirseniz ve bir PhotoImpl için istekte bulunmak üzere ModelBinder'ı değiştirirseniz sorun devam eder. Tersine, ModelBinder'ımın PhotoImpl üzerinde harekete geçmemesi ve varsayılan ModelBinder uygulamasına geri dönmemesi talimatını verirsem, doğrulamalar doğru çalışır. –

8

Ben aynı sorunu vardı. Cevap yerine özel modeli ciltteki BindModel() geçersiz kılma taşımaktadır,

protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, System.Type modelType) 
{ 
    if (modelType == typeof(IPhoto)) 
    { 
     IPhoto photo = new PhotoImpl(); 
     // snip: set properties of photo to bound values 
     return photo; 
    } 

    return base.CreateModel(controllerContext, bindingContext, modelType); 
} 

Daha sonra taban BindModel sınıfı için

+0

DataAnnotations ile karmaşık bir ViewModel ile bağlantı için bir çözüm peşinde koşuyordum ve bu mükemmel bir teşekkür! – daddywoodland