2012-10-02 15 views
11

Estoy desarrollando una validación del lado del cliente y del lado del servidor para una cierta propiedad de viewModel.ValidationMessageFor junto con AddModelError (clave, mensaje). Cual es la clave?

En el archivo .cshtml pongo esto:

@Html.DropDownListFor(model => model.EntityType.ParentId, Model.ParentTypeList, "") 
@Html.ValidationMessageFor(model => model.EntityType.ParentId) 

en el controlador para la validación de negocios

catch (BusinessException e) 
{ 
    ModelState.AddModelError("EntityType.ParentId", Messages.CircularReference); 
} 

lo anterior funciona como se esperaba: si se detecta una excepción, el mensaje aparece al lado de la lista desplegable.

Sin embargo, me parece que esta manera no es muy elegante. En el cshtml, utilizo un método para generar toda la información requerida sobre la validación. En el controlador, debo conocer la cadena clave exacta y usarla.

¿No hay una mejor manera de hacerlo?

+0

Este enlace proporciona alguna adicional visión y una forma de no hacer referencia a la clave directamente como una cadena, sino como una expresión: http://stackoverflow.com/questions/11090445/how-to-get-a-modelstate-key-of-an-item-in- a-list aquí hay otro recurso ce que proporcionan un método de envoltura para la clave Expression http://stackoverflow.com/questions/8793799/get-reference-to-object-from-c-sharp-expression – bUKaneer

Respuesta

21

Se puede escribir un método de extensión que tendrá una expresión lambda de la clave en lugar de una cadena:

public static class ModelStateExtensions 
{ 
    public static void AddModelError<TModel, TProperty>(
     this ModelStateDictionary modelState, 
     Expression<Func<TModel, TProperty>> ex, 
     string message 
    ) 
    { 
     var key = ExpressionHelper.GetExpressionText(ex); 
     modelState.AddModelError(key, message); 
    } 
} 

y luego usar este método:

catch (BusinessException e) 
{ 
    ModelState.AddModelError<MyViewModel, int>(
     x => x.EntityType.ParentId, 
     Messages.CircularReference 
    ); 
} 
+0

Gracias. Funciona perfectamente –

+0

¿Por qué no está en la biblioteca? – UserControl

+0

@UserControl, porque no todo puede ser parte del marco. Para que una característica forme parte del marco en las necesidades, debe escribirse, probarse y documentarse. A veces es necesario tomar una decisión sobre qué características incluirán en el lanzamiento; de lo contrario, nunca podrás lanzar :-) Así que simplemente Microsoft no encontró el tiempo para implementar, probar y documentar esta función. Es por eso que no es parte de la biblioteca. –

0

desea que el validación suceda tanto en el lado del cliente como del servidor, y también en busca de una solución elegante, entonces, ¿por qué puede intentar crear un ValidationAttribute personalizado?

4

que siguen solución @Darin Dimitrov pero quiero evitar <MyViewModel, int> por lo que utiliza alguna forma diferente, pero para eso se necesita MyViewModel object variable.

public static class ModelStateExtensions 
{ 
    public static void AddModelError<TModel, TProperty>(this TModel source,   
                Expression<Func<TModel, TProperty>> ex, 
                string message, 
                ModelStateDictionary modelState) 
    { 
     var key = System.Web.Mvc.ExpressionHelper.GetExpressionText(ex); 
     modelState.AddModelError(key, message); 
    } 
} 

Modo de empleo:

catch (BusinessException e) 
{ 
    objMyViewModel.AddModelError(x => x.EntityType.ParentId, 
           Messages.CircularReference, 
           ModelState); 
} 
+4

Para mí, sería más intuitivo signatura del método de extensión de: 'AddModelError (este ModelStateDictionary modelState, modelo TModel, Expression > ex, mensaje de cadena)'. De esta forma puede usarlo como 'ModelState.AddModelError (modelo, x => x.Email," Correo electrónico inválido "));' – benmccallum

Cuestiones relacionadas