2012-02-23 8 views
8

Tengo el siguiente código:datos de Publicación cuando mi modelo de vista tiene un constructor que no funciona

[HttpGet] 
public ActionResult Edit(int req) 
{ 
    var viewModel = new EditViewModel(); 
    viewModel.RequestId = int; 
    return View(viewModel); 
} 

[HttpPost] 
Public ActionResult Edit(EditViewModel viewModel) 
{ 
// some code here... 
} 

Funciona bien: cuando el formulario de edición se publicó, tengo el controlador de la acción que se llama.

Ahora modificar algunos poco mi código como este:

[HttpGet] 
public ActionResult Edit(int req) 
{ 
    var viewModel = new EditViewModel(req); 
    return View(viewModel); 
} 

[HttpPost] 
Public ActionResult Edit(EditViewModel viewModel) 
{ 
// some code here... 
} 

public class EditViewModel() 
{ 
    public EditViewModel(int req) 
    { 
     requestId = req; 
    } 
    ... 
} 

En esta nueva versión, tengo un modelo de vista con un contructor.

Esta vez, cuando mi formulario se devuelve, el controlador de acción nunca se activa.

¿Alguna idea?

Gracias.

Respuesta

12

Eso es normal. La carpeta de modelo predeterminada ya no puede crear instancias de su modelo de vista ya que no tiene un constructor sin parámetros. Deberá escribir una carpeta de modelo personalizada si desea usar modelos de vista que no tengan un constructor predeterminado.

Normalmente no necesita ese constructor personalizado. Usted podría simplemente tiene su vista del modelo de esa manera:

public class EditViewModel() 
{ 
    public int RequestId { get; set; } 
} 

y la acción POST así:

[HttpPost] 
public ActionResult Edit(EditViewModel viewModel) 
{ 
    // some code here... 
} 

y ahora todo lo que tiene que hacer es publicar el parámetro requestId en lugar de req y el modelo por defecto Binder hará el trabajo.

Y si por alguna razón desea utilizar un modelo de vista con el constructor de encargo, he aquí un ejemplo de cómo el aglutinante de modelo personalizado podría ser:

public class EditViewModelBinder : DefaultModelBinder 
{ 
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) 
    { 
     var req = bindingContext.ValueProvider.GetValue("req"); 
     if (req == null) 
     { 
      throw new Exception("missing req parameter"); 
     } 
     int reqValue; 
     if (!int.TryParse(req.AttemptedValue, out reqValue)) 
     { 
      throw new Exception(string.Format("The req parameter contains an invalid value: {0}", req.AttemptedValue)); 
     } 

     return new EditViewModel(reqValue); 
    } 
} 

que se registrará en su Application_Start:

ModelBinders.Binders.Add(typeof(EditViewModel), new EditViewModelBinder()); 
+0

Muchas gracias por esta precisa respuesta. La razón por la que me gustaría mover algún código al constructor de mi modelo de vista es mantener mi controlador lo más ligero posible. Tengo un montón de código para 'preparar' mi modelo de vista y 'contaminar' mi controlador ... Mi primera idea fue moverlo al constructor de mi modelo de vista. Quizás esta no sea una buena idea ... ¿Qué piensas? Gracias de cualquier manera. – Bronzato

+0

@Bronzato Tengo los mismos requisitos que usted para pasar algún objeto en el constructor de vm y debe encapsular cómo procesarlo y establecer sus propias propiedades. ¿Estás utilizando la solución anterior o apoyaste cualquier otra solución para resolver esto? –

+0

Utilicé la solución sugerida anteriormente. – Bronzato

Cuestiones relacionadas