ASP.NET MVC - Пользовательский образцовый редактор связей на интерфейсном типе

Я не уверен, ожидается ли это поведение или нет, но кажется, что пользовательская образцовая привязка не работает, когда привязка присвоена интерфейсному типу. Кто-либо экспериментировал с этим?

public interface ISomeModel {}
public class SomeModel : ISomeModel {}

public class MvcApplication : HttpApplication {
    protected void Application_Start(object sender, EventArgs e) {
        ModelBinders.Binders[typeof(ISomeModel)] = new MyCustomModelBinder();
    }
}

С вышеупомянутым кодом, когда я связываю с моделью типа SomeModel, никогда не поражается MyCustomModelBinder; однако, если я изменяю вышеупомянутый код и замену typeof(ISomeModel) для typeof(SomeModel) и отправьте ту же самую форму, которой MyCustomModelBinder называют как ожидалось. Это кажется правильным?


Править

Я оказался назад в этом затруднительном положении спустя более чем год после того, как я первоначально задал этот вопрос, и теперь у меня есть решение, которое работает. Спасибо Matt Hidinger!

http://www.matthidinger.com/archive/2011/08/16/An-inheritance-aware-ModelBinderProvider-in-MVC-3.aspx

19
задан Nathan Taylor 19 October 2011 в 19:00
поделиться

2 ответа

Я не уверен, связано ли это напрямую, но да, есть вещи, о которых вам нужно подумать при использовании привязки модели и интерфейсы ... Я столкнулся с аналогичными проблемами со связывателем модели по умолчанию, но это может не иметь прямого отношения в зависимости от того, как вы что-то делаете ...

Взгляните на следующее: ASP.net MVC v2 - Проблемы с привязкой модели отладки - ОШИБКА? ASP.net MVC v2 - Проблемы с привязкой модели отладки - ОШИБКА?

5
ответ дан 30 November 2019 в 04:33
поделиться

Я экспериментировал с этой проблемой и пришел к своеобразному решению. Я создал класс под названием InterfaceModelBinder:

public class InterfaceModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        ModelBindingContext context = new ModelBindingContext(bindingContext);
        var item = Activator.CreateInstance(
            Type.GetType(controllerContext.RequestContext.HttpContext.Request.Form["AssemblyQualifiedName"]));

        Func<object> modelAccessor = () => item;
        context.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(),
            bindingContext.ModelMetadata.ContainerType, modelAccessor, item.GetType(), bindingContext.ModelName);

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

Который я зарегистрировал в Application_Start следующим образом:

ModelBinders.Binders.Add(typeof(IFormSubmission), new InterfaceModelBinder.Models.InterfaceModelBinder());

Интерфейс и конкретная реализация выглядят так:

public interface IFormSubmission
{
}

public class ContactForm : IFormSubmission
{
    public string Name
    {
        get;
        set;
    }

    public string Email
    {
        get;
        set;
    }

    public string Comments
    {
        get;
        set;
    }
}

Единственным недостатком всего этого подхода (как вы, возможно, уже поняли) является то, что мне нужно откуда-то получить AssemblyQualifiedName, и в этом примере оно хранится как скрытое поле на стороне клиента, вот так:

<%=Html.HiddenFor(m => m.GetType().AssemblyQualifiedName) %>

Однако я не уверен, что недостатки раскрытия имени Type клиенту стоят потери преимуществ этого подхода. Action, подобный этому, может обрабатывать все отправленные формы:

[HttpPost]
public ActionResult Process(IFormSubmission form)
{
    if (ModelState.IsValid)
    {
        FormManager manager = new FormManager();
        manager.Process(form);
    }

    //do whatever you want
}

Есть мысли по поводу этого подхода?

11
ответ дан 30 November 2019 в 04:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: