2012-02-21 1 views
2

코어 라이브러리에서 참조하지 않지만 웹 응용 프로그램에서 참조하는 어셈블리에 유형이 있습니다. 예 :모델 바인딩 - 외부 어셈블리 입력

[HttpPost, ValidateAntiForgeryToken] 
public ActionResult NewWidget(FormCollection collection) { 
    var activator = Activator.CreateInstance("AssemblyName", "MyApp.Models.LatestPosts"); 
    var latestPosts = activator.Unwrap(); 

    // Try and update the model 
    TryUpdateModel(latestPosts); 
} 

코드는 매우 자명하지만 latestPosts.NumPosts 속성입니다 결코 값이 양식 모음에있는 경우에도 업데이트 :

namespace MyApp.Models { 
    public class LatestPosts { 
     public int NumPosts { get; set; } 
    } 
} 

지금 내가 핵심 라이브러리에 다음과 같은 코드가 있습니다.

왜 누군가가이 방법이 효과가 없으며 다른 방법이 있는지 설명해 주시면 감사하겠습니다.

감사

답변

3

귀하의 문제는 유형이 다른 어셈블리 또는 동적 Activator.Create 그것을 만드는 것을 사실과는 아무 상관이 없습니다. 다음 코드는 훨씬 간단하게 문제를 보여

[HttpPost, ValidateAntiForgeryToken] 
public ActionResult NewWidget(FormCollection collection) 
{ 
    // notice the type of the latestPosts variable -> object 
    object latestPosts = new MyApp.Models.LatestPosts(); 

    TryUpdateModel(latestPosts); 

    // latestPosts.NumPosts = 0 at this stage no matter whether you had a parameter 
    // called NumPosts in your request with a different value or not 
    ... 
} 
문제는 Controller.TryUpdateModel<TModel>는 이유로 폐쇄 this connect issue에서 설명한 모델 유형 (판별 typeof(TModel) 대신 model.GetType()로 사용한다는 사실에 기인

: by design). 다음

protected internal bool MyTryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IValueProvider valueProvider) where TModel : class 
{ 
    if (model == null) 
    { 
     throw new ArgumentNullException("model"); 
    } 
    if (valueProvider == null) 
    { 
     throw new ArgumentNullException("valueProvider"); 
    } 

    Predicate<string> propertyFilter = propertyName => new BindAttribute().IsPropertyAllowed(propertyName); 
    IModelBinder binder = Binders.GetBinder(typeof(TModel)); 

    ModelBindingContext bindingContext = new ModelBindingContext() 
    { 
     // in the original method you have: 
     // ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(TModel)), 
     ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()), 
     ModelName = prefix, 
     ModelState = ModelState, 
     PropertyFilter = propertyFilter, 
     ValueProvider = valueProvider 
    }; 
    binder.BindModel(ControllerContext, bindingContext); 
    return ModelState.IsValid; 
} 

과 :

[HttpPost, ValidateAntiForgeryToken] 
public ActionResult NewWidget(FormCollection collection) 
{ 
    object latestPosts = new MyApp.Models.LatestPosts(); 

    MyTryUpdateModel(latestPosts, null, null, null, ValueProvider); 

    // latestPosts.NumPosts will be correctly bound now 
    ... 
} 
+0

덕분에 치료를했다

해결 방법은 사용자 정의 사용자가 예상하는대로 동작합니다 TryUpdateModel 방법 롤입니다! – nfplee

+0

예. 고맙습니다. !!! – Rookian

+0

이와 같은 솔루션에 직면했을 때 저는 정말 훌륭한 프로그래머가 아니란 것을 알고 있습니다. 언젠가이 문제를 놓치게됩니다. 고맙습니다. – Alexandre