2011-09-29 13 views
7

¿Hay alguna manera de invocar el archivador de modelo para un solo objeto?Carpeta de modelo de invocación de MVC directamente en un único objeto

no quiero/necesito ligante modelo personalizado - Sólo quiero hacer algo como esto:

MyViewModel1 vModel1 = new MyViewModel1(); 
InvokeModelBinder(vModel1); 

MyViewModel2 vModel2= new MyViewModel2(); 
InvokeModelBinder(vModel2); 

Y cuando he terminado, las propiedades de ambos vModel1 y vModel2 han sido obligados a que hay en la solicitud entrante Debido a la forma en que se está escribiendo nuestro controlador/acción, no necesariamente quiero enumerar vModel1 y vModel2 en la lista de entrada del método de acción (ya que terminará siendo una lista potencialmente larga de modelos de vista para enlazar opcionalmente).

Respuesta

2

Esto está mal en muchos niveles en mi humilde opinión:

  1. Esto no es como ASP.NET MVC está diseñado para trabajar.
  2. Sus acciones no definen un contrato claro de qué datos esperan.
  3. ¿Qué obtienes de él? Huele a mal diseño.

El encuadernado del modelo es conducido por la reflexión. Antes de invocar una acción, reflejará la lista de parámetros del método y para cada objeto y sus propiedades invocará un enlace de modelo para encontrar un valor para cada propiedad de los diversos proveedores de valor (formulario proveedor de valores POST, parámetros de url, etc.). Durante el enlace del modelo, también se realiza la validación de ModelState.

Así que al no utilizar el ASP.NET MVC predeterminado para hacer esto, está perdiendo todo eso.

Incluso si tuviera que conseguir manualmente bodega de un aglutinante de modelo así:

IModelBinder modelBinder = ModelBinders.Binders.GetBinder(typeof(MyObject)); 
MyObject myObject = (MyObject) modelBinder.BindModel(this.ControllerContext, ** ModelBindingContext HERE**); 

se puede ver que es necesario inicializar un ModelBindingContext, algo que ASP.NET MVC se hará basado internamente en el actual propiedad que está reflejando. Aquí está la cortada con tijeras a partir del código fuente de ASP.NET MVC:

protected virtual object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) { 
// collect all of the necessary binding properties 
Type parameterType = parameterDescriptor.ParameterType; 
IModelBinder binder = GetModelBinder(parameterDescriptor); 
IDictionary<string, ValueProviderResult> valueProvider = controllerContext.Controller.ValueProvider; 
string parameterName = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName; 
Predicate<string> propertyFilter = GetPropertyFilter(parameterDescriptor); 

// finally, call into the binder 
ModelBindingContext bindingContext = new ModelBindingContext() { 
    FallbackToEmptyPrefix = (parameterDescriptor.BindingInfo.Prefix == null), // only fall back if prefix not specified 
    ModelName = parameterName, 
    ModelState = controllerContext.Controller.ViewData.ModelState, 
    ModelType = parameterType, 
    PropertyFilter = propertyFilter, 
    ValueProvider = valueProvider 
}; 
object result = binder.BindModel(controllerContext, bindingContext); 
return result; 

}

+0

'¿Qué obtienes de él? Huele a mal diseño. Parece un mal diseño para vincularse a múltiples tipos de modelos, pero tiene un buen uso de rendimiento. Puede inyectar todo lo que se inicializa inicialmente, luego hacer una cláusula de guardia y regresar temprano, sin usar los objetos inyectados que se han configurado. O bien, después de las cláusulas de guardia, una vez que esté seguro de que desea usar un objeto, haga que 'UpdateModel' resuelva la dependencia. Es desordenado, pero si debe hacer que el diseño cambie por el rendimiento, es una posibilidad. – StuperUser

8

Uso Controller.UpdateModel:

MyViewModel1 vModel1 = new MyViewModel1(); 
UpdateModel(vModel1); 

actualización

Nota si ModelState en el controlador tiene errores de validación (relacionado con el modelo pasado en acción), UpdateModel (con cualquier modelo) arroja excedente, a pesar de Upd ateModel success y vModel1 se actualiza. Por lo tanto, los errores en ModelState deberían eliminarse, o poner UpdateModel en try/catch y simplemente ignorar el excedente

+1

FWIW, aquí está el por qué estoy contento de encontrar esta magia. Estoy implementando un marco de "asistente" (es decir, una forma de dividir un único formulario largo en varios formularios más pequeños con los botones "página siguiente" y "página anterior").Quiero que cada página individual POST regrese a una acción de controlador común, pero cada página tiene su propio modelo de vista fuertemente tipado, completo con atributos de validación. Dado que tengo una acción de controlador común, no sé a qué modelo de vista vincularme hasta que he buscado para ver qué página me está enviando. –

Cuestiones relacionadas