首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MVC -处理DropDownListFor中的空值(DropDownListFor)

MVC -处理DropDownListFor中的空值(DropDownListFor)
EN

Stack Overflow用户
提问于 2015-05-21 13:33:27
回答 1查看 3K关注 0票数 0

我正在尝试使用MVC5和EF6.1定制标识(2.1)。我在Identity users表中添加了一个CountryId,并在CountryId上添加了一个完整的独立国家表(CountryId,CountryName)和FK约束。我正在尝试做一个下拉列表,如果用户在过去已经选择过它(从user表中的CountryId ),它将选择用户国家。但是,如果它尚未被选中,则该值将为空。

我想要实现的逻辑是:

代码语言:javascript
复制
if (Model.Country.CountryName != null) {
    @Html.DropDownListFor(m => m.Country, new SelectList(Model.Countries, "Value", "Text"), Model.Country.CountryName)<br />
} else {
    @Html.DropDownListFor(m => m.Country, new SelectList(Model.Countries, "Value", "Text"), "Select a Country")<br />
}

如果删除上面的If else语句(这两种语句都不起作用),则每个DropDownListFor本身都能工作,但前者在CountryName为null时抛出一个NullRefernceException。后者根本不记得用户在过去选择了什么。这是我的控制器:

代码语言:javascript
复制
        var userId = User.Identity.GetUserId();
        ApplicationUser user = await UserManager.FindByIdAsync(userId);
        var model = new IndexViewModel
        {
            HasPassword = HasPassword(),
            //PhoneNumber = await UserManager.GetPhoneNumberAsync(userId),
            //TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId),
            //Or we can write like this because of the user statement above.
            //PhoneNumber = user.PhoneNumber,
            //TwoFactor = user.TwoFactorEnabled,
            Logins = await UserManager.GetLoginsAsync(userId),
            BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId),
            Country = user.Country,
            State = user.State,
            City = user.City,
            Countries = new SelectList(db.Countries, "CountryId", "CountryName")
        };
        return View(model);

如果我在我的控制器模型中使用这样的东西:

代码语言:javascript
复制
Countries = new SelectList(db.Countries, "CountryId", "CountryName", user.Country.CountryName)

然后它向控制器抛出一个NullReferenceException。我明白为什么会发生这样的事,但是对于我的生活来说,在半天的搜寻之后,我还是找不到答案。

我只是想知道是否有一种干净的方法来处理空值,因此,如果CountryId是空的,那么传递一个不同的默认值?

任何帮助都是非常感谢的。

编辑:,我忘了提到视图模型。基本上,我将所有这些添加到IndexViewModel中(尽管我不确定此时是否需要这些):

代码语言:javascript
复制
    public int CountryId { get; set; }
    public int StateId { get; set; }
    public int CityId { get; set; }

    public virtual Country Country { get; set; }
    public virtual State State { get; set; }
    public virtual City City { get; set; }

    public IEnumerable<SelectListItem> Countries { get; set; }
    public IEnumerable<SelectListItem> States { get; set; }
    public IEnumerable<SelectListItem> Cities { get; set; }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-22 01:46:00

首先,不能将下拉列表绑定到复杂类型。Html对您的c# Country类没有概念。您需要绑定到您的CountryId属性

代码语言:javascript
复制
@Html.DropDownListFor(m => m.CountryId , Model.Countries)

还要注意的是,Countries已经是一个SelectList了,所以它有点没有意义,而且不必要的额外开销,然后从它创建另一个SelectList,所以它只是Model.Countries,而不是new SelectList(Model.Countries, "Value", "Text")

接下来,绑定到属性(CountryId),因此它的值CountryId决定选择哪个选项-第三个参数(Model.Country.CountryName)被忽略。但是即使不是,它也不会选择任何东西,因为选项的value属性是CountryId属性的值,而不是CountryName属性。如果存在CountryId,则需要在控制器中设置Country的值。

最后,if (Model.Country.CountryName != null) {抛出一个异常,因为Country的值是null (不能访问null对象的CountryName属性)。

if/else块是完全不必要的,您只需要视图中的一行代码即可。

代码语言:javascript
复制
@Html.DropDownListFor(m => m.CountryId , Model.Countries, "-Please select-")

如果CountryId的值是0 (int的默认值),那么将选择"-Please select-“选项。如果CountryId的值与集合中的值之一匹配,则在呈现视图时将选择该选项。因为CountryIdint类型,所以如果用户没有选择有效的国家,就会产生验证错误。

最后,尽管使用了IndexViewModel命名,但它不是视图模型!视图模型只包含在视图中显示/编辑的属性,因此应该删除所拥有的3个虚拟属性(可能还有与StatesCities相关的4个属性,但不确定是否从视图和控制器中省略了一些代码)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30375302

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档