Asp.net Html.dropdownlist用于根据ModelState而不是Model选择项

Asp.net Html.dropdownlist用于根据ModelState而不是Model选择项,asp.net,asp.net-mvc,asp.net-mvc-5,Asp.net,Asp.net Mvc,Asp.net Mvc 5,在asp.net mvc(在我的示例中是v5)中,当您将模型发回控制器,然后使用发回的模型以外的模型渲染视图时,Html.DropDownListFor将根据发回的模型中的数据而不是传递给视图的模型来选择所选项 为什么会这样 这里有一个例子。当您在第一个下拉列表中选择一个新项目时,表单会发回,如果第一个下拉列表中选择了id=2,则SelectedD2会发生更改,第二个下拉列表中应显示选定的第二个项目。但事实并非如此。虽然视图中的模型对象确实具有新的Selected2=2值,但引擎盖下的DropD

在asp.net mvc(在我的示例中是v5)中,当您将模型发回控制器,然后使用发回的模型以外的模型渲染视图时,Html.DropDownListFor将根据发回的模型中的数据而不是传递给视图的模型来选择所选项

为什么会这样

这里有一个例子。当您在第一个下拉列表中选择一个新项目时,表单会发回,如果第一个下拉列表中选择了id=2,则SelectedD2会发生更改,第二个下拉列表中应显示选定的第二个项目。但事实并非如此。虽然视图中的模型对象确实具有新的Selected2=2值,但引擎盖下的DropDownList for从ViewState.ModelState对象而不是ViewState.Model获取选定值。如何使DropDownListFor仅基于传递给视图的模型进行渲染

控制员:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var defaultModel = getModel();
        return View(defaultModel);
    }

    [HttpPost]
    public ActionResult Index(Model1 postedModel)
    {
        var defaultModel = getModel();

        if (postedModel.selectedId1 == 2)
        {
            defaultModel.selectedId1 = 2;
            defaultModel.selectedId2 = 2;
        }

        return View(defaultModel);
    }

    private Model1 getModel()
    {
        var items1 = new[]
        {
            new
            {
                Name = "Item 1-1",
                Id = "1"
            },
            new
            {
                Name = "Item 1-2",
                Id = "2"
            }
        };

        var items2 = new[]
        {
            new
            {
                Name = "Item 1-1",
                Id = "1"
            },
            new
            {
                Name = "Item 2-2",
                Id = "2"
            }
        };

        return new Model1
        {
            selectedId1 = 1,
            selectedId2 = 1,
            SelectList1 = new SelectList(items1, "Id", "Name", 1),
            SelectList2 = new SelectList(items2, "Id", "Name", 1)
        };
    }


}
视图模型:

public class Model1
{
    public SelectList SelectList1 { get; set; }
    public SelectList SelectList2 { get; set; }
    public int selectedId1 { get; set; }
    public int selectedId2 { get; set; }
}
观点:

@model Model1

@using (Html.BeginForm(FormMethod.Post))
{
    <div>
        @Html.DropDownListFor(m => m.selectedId1, Model.SelectList1, new { title = "Select 1", onchange = "this.form.submit();" })
        @Html.DropDownListFor(m => m.selectedId2, Model.SelectList2, new { title = "Select 2", onchange = "this.form.submit();" })
    </div>
}

如果使用适当的
SelectList
构造函数,则可以指定所选值:

最后一个参数是所选项目,它必须是
IEnumerable
的一个对象


您正在使用此构造函数,但将
1
指定为值。它应该像
items1[0]

那样,只是设置了要选择的默认项,它会被DropDownListFor()调用中使用的model/lambda表达式中提供的所选项id覆盖?DropDownListFor的MVC代码非常复杂。如果您遵循它,您将看到一个
SelectInternal
类,该类使用
SelectList
中每个项目的
Selected
属性来决定是否选择了值(
SelectList
是一个
IEnumerable
SelectListItem
有一个
Selected
属性)。在整个过程中,似乎没有一个地方可以修改
Selected
属性。我一直这样使用它,从来没有遇到过麻烦(至少在我的使用模式中)。它对您不起作用吗?如果您将
DropDowListFor
与其他帮助程序进行比较,就会发现一个很大的区别:在其他帮助程序代码中,您可以看到他们收到了模型。
DropDownListFor
没有收到。不,我想你错过了我问题的主要部分。在视图模型或SelectList的构造函数中作为选定项放置什么并不重要,因为模型中发布到操作的数据将被使用。如果查看DropDownListFor的MVC代码,您将看到所选值是从ViewState.ModelState提取的,而不是从ViewState.Model提取的。当视图在POST上呈现时存在我的问题-当视图为GET呈现时没有问题。我确实发现添加ViewData.ModelState.Clear();在我调用控制器中的View()之前,我的操作有效。您是否尝试过我的解决方案,但失败了?如果是这样,请让我知道,我会尝试用概念证明来重复。谢谢
ViewData.ModelState.Clear();