ASP.NET MVC-Carpeta de modelo personalizada en tipo de interfaz
asp.net-mvc interface (3)
No estoy seguro de si este comportamiento es esperado o no, pero parece que el enlace de modelo personalizado no funciona cuando el enlace se asigna a un tipo de interfaz. ¿Alguien ha experimentado con esto?
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();
}
}
Con el código anterior, cuando se enlaza a un modelo de tipo SomeModel, MyCustomModelBinder nunca se ve afectado; sin embargo, si cambio el código anterior y sustituyo typeof(ISomeModel)
por typeof(SomeModel)
y typeof(SomeModel)
exactamente la misma forma, se llama a MyCustomModelBinder como se esperaba. ¿Eso parece correcto?
Editar
Me encontré nuevamente en esta situación más de un año después de haber formulado esta pregunta, y ahora tengo una solución que funciona. Gracias Matt Hidinger!
De repente, aparece una solución MVC3:
Estaba experimentando con este problema y se me ocurrió una solución de todo tipo. Hice una clase llamada 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);
}
}
Que me registré en mi Application_Start como tal:
ModelBinders.Binders.Add(typeof(IFormSubmission), new InterfaceModelBinder.Models.InterfaceModelBinder());
La interfaz y una implementación concreta se ven así:
public interface IFormSubmission
{
}
public class ContactForm : IFormSubmission
{
public string Name
{
get;
set;
}
public string Email
{
get;
set;
}
public string Comments
{
get;
set;
}
}
El único inconveniente de todo este enfoque (como es posible que ya haya recopilado) es que necesito obtener el AssemblyQualifiedName de algún lugar, y en este ejemplo se está almacenando como un campo oculto en el lado del cliente, de esta manera:
<%=Html.HiddenFor(m => m.GetType().AssemblyQualifiedName) %>
Sin embargo, no estoy seguro de que los inconvenientes de exponer el nombre del Tipo al cliente valgan la pena de perder los beneficios de este enfoque. Una acción como esta puede manejar todos mis envíos de formularios:
[HttpPost]
public ActionResult Process(IFormSubmission form)
{
if (ModelState.IsValid)
{
FormManager manager = new FormManager();
manager.Process(form);
}
//do whatever you want
}
¿Alguna idea sobre este enfoque?
No estoy seguro de si está directamente relacionado, pero sí, hay cosas en las que debe pensar al usar el enlace de modelos y las interfaces ... Me encontré con problemas similares con el cuaderno de modelos predeterminado, pero puede que no esté directamente relacionado, según cómo estas haciendo cosas ...
Eche un vistazo a lo siguiente: ASP.net MVC v2 - Depuración de problemas de vinculación de modelos: ¿ERROR? ASP.net MVC v2 - Debugging Model Binding Issues - BUG?