Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 发布到模型的MVC DropDownList值未绑定_C#_Asp.net Mvc 3_Drop Down Menu_Model Binding - Fatal编程技术网

C# 发布到模型的MVC DropDownList值未绑定

C# 发布到模型的MVC DropDownList值未绑定,c#,asp.net-mvc-3,drop-down-menu,model-binding,C#,Asp.net Mvc 3,Drop Down Menu,Model Binding,DropDownLists可能是我最不喜欢使用MVC框架的部分。我的表单中有几个下拉列表,我需要将它们的选定值传递给接受模型作为其参数的ActionResult 标记如下所示: <div class="editor-label"> @Html.LabelFor(model => model.FileType) </div> <div class="editor-field"> @Html.DropDownListFor(model =&g

DropDownLists可能是我最不喜欢使用MVC框架的部分。我的表单中有几个下拉列表,我需要将它们的选定值传递给接受模型作为其参数的ActionResult

标记如下所示:

<div class="editor-label">
    @Html.LabelFor(model => model.FileType)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.FileType.Variety, (SelectList)ViewBag.FileTypes)
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.Status)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.Status.Status, (SelectList)ViewBag.Status)
</div>
[HttpPost]
public ActionResult Create(int reviewid, ReviewedFile file)
{
    if (ModelState.IsValid)
    {
        UpdateModel(file);
    }

    //repository.Add(file);

    return RedirectToAction("Files", "Reviews", new { reviewid = reviewid, id = file.ReviewedFileId });
}
这应该很好,除了下拉列表中的值被发布为null。当我进一步研究ModelState错误时,发现原因是:

类型的参数转换 要键入的“System.String” 'PeerCodeReview.Models.outcome状态' 失败,因为无法使用类型转换器 在这些类型之间转换

不应该这么难,但确实如此。所以问题是,;为了正确绑定模型属性,我需要做什么


顺便说一句,我知道我可以传入FormCollection对象,但这意味着更改单元测试中当前需要强类型模型参数的重要部分。

您需要为绑定到下拉列表的两个属性创建并注册自定义模型绑定器

以下是我为一个模型活页夹编写的代码,我正是为此目的而构建的:

public class LookupModelBinder<TModel> : DefaultModelBinder
    where TModel : class
{
    private string _key;

    public LookupModelBinder(string key = null)
    {
        _key = key ?? typeof(TModel).Name;
    }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var dbSession = ((IControllerWithSession)controllerContext.Controller).DbSession;

        var modelName = bindingContext.ModelName;
        TModel model = null;
        ValueProviderResult vpResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (vpResult != null)
        {
            bindingContext.ModelState.SetModelValue(modelName, vpResult);
            var id = (int?)vpResult.ConvertTo(typeof(int));
            model = id == null ? null : dbSession.Get<TModel>(id.Value);
        }
        if (model == null)
        {
            ModelValidator requiredValidator = ModelValidatorProviders.Providers.GetValidators(bindingContext.ModelMetadata, controllerContext).Where(v => v.IsRequired).FirstOrDefault();
            if (requiredValidator != null)
            {
                foreach (ModelValidationResult validationResult in requiredValidator.Validate(bindingContext.Model))
                {
                    bindingContext.ModelState.AddModelError(modelName, validationResult.Message);
                }
            }
        }
        return model;
    }
}
这假定下拉列表控件的名称与类型名称相同。如果没有,则可以将密钥传递给模型绑定器

binders[typeof(EmploymentType)] = new LookupModelBinder<EmploymentType>("ControlName");

您需要为绑定到下拉列表的两个特性创建并注册自定义模型绑定器

以下是我为一个模型活页夹编写的代码,我正是为此目的而构建的:

public class LookupModelBinder<TModel> : DefaultModelBinder
    where TModel : class
{
    private string _key;

    public LookupModelBinder(string key = null)
    {
        _key = key ?? typeof(TModel).Name;
    }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var dbSession = ((IControllerWithSession)controllerContext.Controller).DbSession;

        var modelName = bindingContext.ModelName;
        TModel model = null;
        ValueProviderResult vpResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (vpResult != null)
        {
            bindingContext.ModelState.SetModelValue(modelName, vpResult);
            var id = (int?)vpResult.ConvertTo(typeof(int));
            model = id == null ? null : dbSession.Get<TModel>(id.Value);
        }
        if (model == null)
        {
            ModelValidator requiredValidator = ModelValidatorProviders.Providers.GetValidators(bindingContext.ModelMetadata, controllerContext).Where(v => v.IsRequired).FirstOrDefault();
            if (requiredValidator != null)
            {
                foreach (ModelValidationResult validationResult in requiredValidator.Validate(bindingContext.Model))
                {
                    bindingContext.ModelState.AddModelError(modelName, validationResult.Message);
                }
            }
        }
        return model;
    }
}
这假定下拉列表控件的名称与类型名称相同。如果没有,则可以将密钥传递给模型绑定器

binders[typeof(EmploymentType)] = new LookupModelBinder<EmploymentType>("ControlName");
请尝试以下方法:

<div class="editor-label">
    @Html.LabelFor(model => model.FileType)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.FileType.Id, (SelectList)ViewBag.FileTypes)
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.Status)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.Status.Id, (SelectList)ViewBag.Status)
</div>
请尝试以下方法:

<div class="editor-label">
    @Html.LabelFor(model => model.FileType)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.FileType.Id, (SelectList)ViewBag.FileTypes)
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.Status)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.Status.Id, (SelectList)ViewBag.Status)
</div>

另外,这里不需要UpdateModelfile,因为发布的表单值已经包含在ReviewFileFile参数中。我只需要它来检查ModelState错误。一旦我找到解决问题的方法,它就会运行。另外,您不需要在其中包含UpdateModelfile,因为发布的表单值已经包含在您的ReviewedFile参数中。我只需要它来检查ModelState错误。一旦我找到解决问题的方法,它就开始运行了。这是一个很好的建议,但我已经尝试过了,同样的错误仍然存在——MVC不知道如何将字符串值转换为相应的对象属性,例如ReviewedFile.FileTypeI无法重新设置。我已经设置了一个快速项目并模拟了您的类,但MVC为我将字符串值转换为对象属性。例如,如果我进入Create操作并检查file.FileType的值,就会得到一个FileType类型的对象,其值为{Id=2,variation=null}。它可能不是完整的对象,但有足够的信息从repo检索它。它到底为您做了什么?很好的建议,但我已经尝试过了,同样的错误仍然存在-MVC不知道如何将字符串值转换为相应的对象属性,例如ReviewDefile.FileTypeI无法重新编程。我已经设置了一个快速项目并模拟了您的类,但MVC为我将字符串值转换为对象属性。例如,如果我进入Create操作并检查file.FileType的值,就会得到一个FileType类型的对象,其值为{Id=2,variation=null}。它可能不是完整的对象,但有足够的信息从repo检索它。它到底为你做了什么?