为什么在提交视图后使用多个DropDownLists时,MVC DropDownList帮助程序的行为不一致

时间:2014-02-15 23:55:33

标签: asp.net-mvc asp.net-mvc-4 drop-down-menu

我对MVC来说并不陌生,但在处理DropDownList和DropDownListFor助手时,我一直遇到同样的问题,助手们的表现并不像他们应该的那样。

我目前的项目正在做一些非常直接的任务,我正在捕获用户关于付款和频率的输入数据。在我的控制器中,我正在构建List的预定义列表并将它们传递给我的视图。

    private List<SelectListItem> PaymentTypes
    {
        get
        {
            return new List<SelectListItem>
            {
                new SelectListItem {Selected = true, Text = string.Empty, Value = string.Empty},
                new SelectListItem {Selected = false, Text = "Cash", Value = "Cash"},
                new SelectListItem {Selected = false, Text = "Personal Cheque", Value = "Personal Cheque"},
                new SelectListItem {Selected = false, Text = "Business Cheque", Value = "Business Cheque"},
                new SelectListItem {Selected = false, Text = "Credit Card", Value = "Credit Card"},
                new SelectListItem {Selected = false, Text = "Direct Debit", Value = "Direct Debit"},
                new SelectListItem {Selected = false, Text = "Other", Value = "Other"}
            };
        }
    }

    private List<SelectListItem> Frequency
    {
        get
        {
            return new List<SelectListItem>
            {
                new SelectListItem {Selected = true, Text = string.Empty, Value = string.Empty},
                new SelectListItem {Selected = false, Text = "Monthly", Value = "Monthly"},
                new SelectListItem {Selected = false, Text = "Quarterly", Value = "Quarterly"},
                new SelectListItem {Selected = false, Text = "Semi-Annually", Value = "Semi-Annually"},
                new SelectListItem {Selected = false, Text = "Annually", Value = "Annually"}
            };
        }
    }

在我看来,我没有做任何与通常通过助手创建和填充下拉列表所做的不同的事情。我只是从ViewBag中获取值,然后使用DropDownList并创建列表。

var frequency = ViewBag.Frequency as List<SelectListItem>;
var paymentTypes = ViewBag.PaymentTypes as List<SelectListItem>;

<li><label class="mediumLabel">Payment Type </label> @Html.DropDownList("paymentType", paymentTypes, new { @class = "input medium_textbox" })</li>
<li><label class="mediumLabel">Frequency </label> @Html.DropDownList("frequency", frequency, new { @class = "input medium_textbox" })</li>

到目前为止,一切都很完美,加载视图时一切正常。下拉列表将填充,用户可以选择所需内容。

如果用户随后提交表单(如果有任何缺少的字段且模型无效),DropDownList和DropDownListFor帮助程序将变得不一致。如果两个字段都被选中并且视图返回给用户,则只有两个下拉列表中的一个将具有值。

这里到底发生了什么,为什么会发生?

添加了操作

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Output(AbstractOutput model)
{
    if (!ModelState.IsValid)
    {
        ViewBag.Frequency = Frequency;
        ViewBag.PaymentTypes = PaymentTypes;

        return View(model);
    }

    //--
    //-- 
    var context = new Context();
        var options = new OptionsRepository(context);

        //-- add the request to the system
        try
        {
            context.Output.Add(request);
            context.SaveChanges();

            //-- alert the user that thier download has been submited 
            SendConfirmationAlert(context, options, model);

            return RedirectToAction("Output", "Output");
        }
        catch (SmtpException ex)
        {
            Log4NetService.LogException(Log4NetLevel.Error, ex, true);

            TempData["error"] = new Error
            {
                Controller = "Output",
                Action = "Output",
                Severity = Severity.Low,
                Description = string.Format("App is unable to to send {0} request confirmation", model.OutputType.ToLower()),
                Exception = ex
            };

            return RedirectToAction("Error", "Home");
        }
        catch (Exception ex)
        {
            Log4NetService.LogException(Log4NetLevel.Error, ex, true);

            TempData["error"] = new Error
            {
                Controller = "Output",
                Action = "Output",
                Severity = Severity.High,
                Description = string.Format("App is unable to process your {0} request", model.OutputType),
                Exception = ex
            };

            return RedirectToAction("Error", "Home");
        }
}

1 个答案:

答案 0 :(得分:0)

这可能与人们在使用DropDownList时遇到的常见问题有关,特别是当他们将项目命名为与其选择列表相同的名称时。当MVC找到与您发布的名称相同的类型时,它会在模型​​绑定期间内部混淆。

我不喜欢依赖模型状态来填充这样的并且更喜欢使用强类型数据。请注意,我保留了不同的名称,与其他类型的名称分开(您有一个名为Frequency的属性,因此将ID更改为模型中的FrequencyId)

我会这样做:

var frequencyList = ViewBag.Frequency as List<SelectListItem>;
var paymentTypeList = ViewBag.PaymentTypes as List<SelectListItem>;

<li><label class="mediumLabel">Payment Type</label>
   @Html.DropDownListFor(x => x.PaymentTypeId, paymentTypeList, 
       new { @class = "input medium_textbox" })</li>
<li><label class="mediumLabel">Frequency </label> 
   @Html.DropDownListFor(x => x.FrequencyId, frequencyList, 
       new { @class = "input medium_textbox" })</li>

顺便说一句,我不会为第一项使用空字符串,而是使用DropDownListFor参数中的默认值选项。这里的原因是,如果你没有设置初始值,那么你有两个不同的条件......未选中,并用空白数据选择。

您可能也会看到不同的症状。使用同名的SelectList时,会出现“无参数构造函数”错误。这是因为模型绑定器试图从发布的值中实例化选择列表。它变得混乱,因为名字是相同的。

相关问题