Question

I have a simple MVC website that displays a jquery dialog for editing purposes. In this dialog is a textarea that accepts a comma delimited list of skills that the user can enter. Upon submission, my model binder turns this into a List. Here is the code for my model binder

public class EditSkillsModelBinder : DefaultModelBinder
    {
        protected override void OnModelUpdated(ControllerContext controllerContext,
        ModelBindingContext bindingContext)
        {
            var form = controllerContext.HttpContext.Request.Form;
            var skillsAsString = form["SkillsAsString"];
            var user = bindingContext.Model as UserEditDetailsModel;

            //FOR VALIDATION
            ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            ModelState modelState = new ModelState {Value = valueResult};

            if (string.IsNullOrEmpty(skillsAsString))
            {
                bindingContext.ModelState.AddModelError("Skills", "You must enter at least one skill.");
            }
            else
            {
                user.Skills = string.IsNullOrEmpty(skillsAsString) ? new List<string>() : skillsAsString.Split(',').Select(i => i.Trim()).ToList();
            }


        }

    }

And this is the code for my partial view

@using (Ajax.BeginForm("EditUserDetails", new { }, new AjaxOptions { }, new { id = "EditUserDetailsForm" }))
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>UserEditDetailsModel</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.FirstName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.FirstName)
            @Html.ValidationMessageFor(model => model.FirstName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.LastName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.LastName)
            @Html.ValidationMessageFor(model => model.LastName)
        </div>


        <div class="editor-label">
            @Html.LabelFor(model => model.Skills)
        </div>
        <div class="editor-field">
            @Html.TextArea("SkillsAsString", Model.Skills.ToCommaSeparatedString())
            @Html.ValidationMessageFor(model => model.Skills)
        </div>


        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>


}


@*Enable Client Side Validation*@
<script type="text/javascript">
    $(document).ready(function () {
        $.validator.unobtrusive.parse("#content_container > form");
    });
  </script>

All of my simple validations such as [Required] as working on the client side. The model binder validation works as well, however, the error message is not being displayed. I am assuming that I am missing something in the javascript to register the error but I cant figure out what it is. Any help would be appreciated. Thanks.

Here is a screenshot of the problem

enter image description here

Was it helpful?

Solution

So I ditched the unobtrusive and what I found was that I had a [Required] attribute on my model for skills which was causing the validation in the screenshot, not the validation from my model binder.

Although model binders are not intended for validation, it appears that trying to mix validation attributes and model binders for the same model property will cause problems (at least in my case of trying to convert a string to list), therefore, I am validating strictly in my model binder (which provides additional functionality) and it has started working.

EDIT

I should add that I dropped validation attributes in favor of FluentValidation per this post. It is much less verbose, integrates with client validation, and is easier to use.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top