【问题标题】:AttemptedValue of ValueProviderResult returns wrong valueValueProviderResult 的 AttemptedValue 返回错误值
【发布时间】:2014-10-03 05:32:57
【问题描述】:

我在我的项目中使用了 ASP.NET MVC5,并在其中使用了自定义模型绑定。 当我在我的模型中获取 IsActive 属性的值时,我遇到了一个问题。IsActive 值必须是“true”或“false”,但我得到了 “true,false” 我怎样才能得到正确的值?

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

我的观点总结:

@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>

【问题讨论】:

    标签: c# asp.net-mvc model-binding custom-model-binder


    【解决方案1】:

    您没有包含您的视图,但我怀疑您使用 CheckBoxFor() 呈现 2 个具有相同名称的输入,第一个是复选框,第二个是隐藏输入(使用它是因为未选中的复选框不会回发,这样可以确保发布默认值)。 DefaultModelBinder 忽略第二个值(如果存在)。

    【讨论】:

    • 我添加了我的观点总结。
    • 正如我所怀疑的那样。如果您查看生成的 html,您将看到带有 name="IsActiveNewComment" 的 2 个输入。如果选中该复选框,则两者都回发,否则只有第二个(隐藏输入)回发。如果存在,您只需要忽略第二个值
    • 你是对的。但是当我更改复选框时,我得到一个正确的值,当我不更改复选框值时,我得到错误的值。如果存在第二个值,我该如何忽略它?请通过代码告诉我。
    • 我猜你可以检查foreach (var propertyName in propertyNames) {...propertyName的值,如果它与之前的值相同,忽略它(未测试)
    【解决方案2】:

    根据Stephen Muecke's descriptions,我修改了BindModel方法。

    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)
            {
                string value = GetValue(bindingContext, propertyName);
                if (bindingContext.PropertyMetadata[propertyName].ModelType.Name == "Boolean")
                {
                    if (value.ToLower() == "true,false" || value.ToLower() == "false,true")
                        value = System.Web.HttpContext.Current.Request.Form.GetValues(propertyName).First();
                }
                model.SetPropertyValue(propertyName, value);
            }
            return model;
        }
    

    【讨论】:

    • 不是一个合适的模型绑定器,因为它忽略了 ValueProviders 并直接转到 Request.Form。这会破坏各种很酷的东西,比如发布 JSON 等。
    猜你喜欢
    • 2015-06-19
    • 2019-02-03
    • 2014-01-16
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多