ValidationMessageFor together with AddModelError(key, message). What’s the key?

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?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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
    );
}

Method 2

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);
}

Method 3

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.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x