Search code examples
c#asp.net-mvcmodel-bindingcustom-model-binder

AttemptedValue of ValueProviderResult returns wrong value


I've used ASP.NET MVC5 in my project and I've used custom model binding in it. when I'm getting the value of IsActive property in my model, I faced a problem.IsActive value must be "true" or "false" but I got "true,false" How can I get the correct value?

public class BaseModelBinder<TModel> : IModelBinder where TModel : class, new()
{
    public virtual object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        TModel model = (TModel)bindingContext.Model ?? new TModel();
        ICollection<string> propertyNames = bindingContext.PropertyMetadata.Keys;
        foreach (var propertyName in propertyNames)
        {
            var value = GetValue(bindingContext, propertyName);
            model.SetPropertyValue(propertyName, value);
        }
        return model;
    }

    private string GetValue(ModelBindingContext context, string name)
    {
        name = (context.ModelName == "" ? "" : context.ModelName + ".") + name;

        ValueProviderResult result = context.ValueProvider.GetValue(name);
        if (result == null || result.AttemptedValue == "")
        {
            return "<Not Specified>";
        }
        else
        {
            return (string)result.AttemptedValue;
        }
    }
}

AttemptedValue of ValueProviderResult returns wrong value

Summary of my view:

@using System.ComponentModel
@using Kendo.Mvc.UI
@model Jahan.Blog.ViewModel.ArticleViewModel
  @{
         ViewBag.Title = "Edit";
    }
<h2>Edit</h2>

@using (Html.BeginForm())
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>Article</h4>
    <hr />
    @Html.ValidationSummary(true)
    <div class="form-group">
        @Html.LabelFor(model => model.IsActive, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.CheckBoxFor(model => model.IsActive)
            @Html.ValidationMessageFor(model => model.IsActive)
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.IsActiveNewComment, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.CheckBoxFor(model => model.IsActiveNewComment)
            @Html.ValidationMessageFor(model => model.IsActiveNewComment)
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Save" class="btn btn-default" />
        </div>
    </div>
</div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Solution

  • You haven't included you view, but I suspect your using CheckBoxFor() which renders 2 inputs with the same name, the first is a checkbox and the second is a hidden input (which is used because unchecked check boxes do not post back and this ensures the default value is posted). The DefaultModelBinder ignores the second value if its present.