2012-06-18 21 views
18

ProblemaCómo obtener una clave ModelState de un elemento de una lista

Tengo una lista de campos que el usuario puede editar. Cuando se envíe el modelo, quiero verificar si estos elementos son válidos. No puedo usar las anotaciones de datos porque cada campo tiene un proceso de validación diferente que no conoceré hasta el tiempo de ejecución. Si la validación falla, utilizo el ModelState.AddModelError(string key, string error) donde la clave es el nombre del elemento html al que desea agregar el mensaje de error. Como hay una lista de campos, el nombre que Razor genera para el elemento html es como Fields[0].DisplayName. Mi pregunta es ¿hay algún método o una forma de obtener la clave del nombre html generado del modelo de vista?

intento de solución

He probado el método toString() para la clave, pero sin suerte. También miré en la clase HtmlHelper pero no vi ningún método útil.

Fragmento de código

Ver Modelo

public class CreateFieldsModel 
{ 
    public TemplateCreateFieldsModel() 
    { 
     FreeFields = new List<FieldModel>(); 
    } 

    [HiddenInput(DisplayValue=false)] 
    public int ID { get; set; } 

    public IList<TemplateFieldModel> FreeFields { get; set; } 


    public class TemplateFieldModel 
    { 
     [Display(Name="Dispay Name")] 
     public string DisplayName { get; set; } 

     [Required] 
     [Display(Name="Field")] 
     public int FieldTypeID { get; set; } 
    } 
} 

controlador

public ActionResult CreateFields(CreateFieldsModel model) 
{ 
    if (!ModelState.IsValid) 
    { 
     //Where do I get the key from the view model? 
     ModelState.AddModelError(model.FreeFields[0], "Test Error"); 
     return View(model); 
    } 
} 

Respuesta

24

Después de buscar el código fuente encontré la solución. Hay una clase llamada ExpressionHelper que se usa para generar el nombre html para el campo cuando se llama al EditorFor(). La clase ExpressionHelper tiene un método llamado GetExpressionText() que devuelve una cadena que es el nombre de ese elemento html. Aquí está cómo usarlo ...

for (int i = 0; i < model.FreeFields.Count(); i++) 
{ 
    //Generate the expression for the item 
    Expression<Func<CreateFieldsModel, string>> expression = x => x.FreeFields[i].Value; 
    //Get the name of our html input item 
    string key = ExpressionHelper.GetExpressionText(expression); 
    //Add an error message to that item 
    ModelState.AddModelError(key, "Error!"); 
} 

if (!ModelState.IsValid) 
{ 
    return View(model); 
} 
+4

Esto es bueno, pero acabo de encontrar otra publicación que envuelve esta lógica en un buen método de extensión: http://stackoverflow.com/a/12689563/1825109 – Michael12345

0

Hay que enmarcar la clave (nombre del elemento de entrada) en el interior del controlador basado sobre cómo está renderizando la f campos en la forma.

Por ej. si la validación del segundo elemento en la colección FreeFields de CreateFieldsModel falla, puede enmarcar el nombre del elemento de entrada, es decir, la clave FreeFields[1].DisplayName donde se va a asignar el error de validación.

Por lo que sé, no se puede obtener fácilmente desde el controlador.

+0

Entonces, ¿puede tener un campo oculto donde el nombre es un valor constante y el valor del campo sea el resultado del método EditorFor, excepto obtener el atributo de nombre? –

Cuestiones relacionadas