I am developing a client-side and server-side validation for a certain viewModel property.
In the .cshtml
file I put this:
@Html.DropDownListFor(model => model.EntityType.ParentId, Model.ParentTypeList, "")
@Html.ValidationMessageFor(model => model.EntityType.ParentId)
In the Controller for the business validation
catch (BusinessException e)
{
ModelState.AddModelError("EntityType.ParentId", Messages.CircularReference);
}
The above works as expected: if an exception is caught, the message appears next to the dropdownlist.
However, I find that this way is not very elegant. In the cshtml
, I use a method to generate all the required information about the validation. In the controller, I must know the exact Key string and use it.
Isn't there a better way of doing this?
You could write an extension method that will take a lambda expression for the key instead of a string:
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);
}
}
and then use this method:
catch (BusinessException e)
{
ModelState.AddModelError<MyViewModel, int>(
x => x.EntityType.ParentId,
Messages.CircularReference
);
}
I follow @Darin Dimitrov solution but i want to avoid <MyViewModel, int>
so I used some different way but for that you need 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);
}
}
How to Use:
catch (BusinessException e)
{
objMyViewModel.AddModelError(x => x.EntityType.ParentId,
Messages.CircularReference,
ModelState);
}
You want the validation to happen at both the client and server side and also you looking for an elegant solution then why can try creating a custom ValidationAttribute
.