我尝试使用MVC5和EF6.1自定义Identity(2.1)。我已经在Identity用户表中添加了一个CountryId,并在CountryId上添加了一个具有FK约束的完整单独的Country表(CountryId,CountryName)。我尝试做一个下拉列表,如果用户过去曾选择用户国家(来自users表中的CountryId),则会选择用户所在国家/地区。但是,如果没有选择,则该值将为空。
我试图完成的逻辑是:
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。后者根本不记得用户过去选择的内容。这是我的控制器:
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);
如果我在控制器模型中使用这样的东西:
Countries = new SelectList(db.Countries, "CountryId", "CountryName", user.Country.CountryName)
然后它会在控制器上抛出NullReferenceException。我明白为什么会发生这种情况,但是对于我的生活来说,在半天的搜索后找不到答案。
我只是想知道是否有一种干净的方法来处理空值,因此,如果CountryId为null,则传递一个不同的默认值?
总是非常感谢任何帮助。
编辑:我忘了提及viewmodel。我基本上将所有这些添加到了IndexViewModel中(虽然我不确定此时是否需要它):
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; }
答案 0 :(得分:0)
首先,您无法将下拉列表绑定到复杂类型。 Html没有关于你的c#Country
类的概念。您需要绑定到CountryId
属性
@Html.DropDownListFor(m => m.CountryId , Model.Countries)
另请注意,Countries
已经是SelectList
,因此从它创建另一个SelectList
有点无意义和不必要的额外开销,所以它只是Model.Countries
,而不是new SelectList(Model.Countries, "Value", "Text")
CountryId
接下来,您对属性(CountryId
)的绑定以及确定选择了哪个选项的Model.Country.CountryName
的值 - 第3个参数(value
)将被忽略。但即使它不是,它根本不会选择任何内容,因为您的选项的CountryId
属性是CountryName
属性的值,而不是CountryId
属性。如果存在Country
,则需要在控制器中设置if (Model.Country.CountryName != null) {
的值。
最后,您的Country
会抛出异常,因为null
的值为CountryName
(您无法访问null
对象的if/else
属性。
完全不需要@Html.DropDownListFor(m => m.CountryId , Model.Countries, "-Please select-")
块,视图中只需要一行代码
CountryId
如果0
的值为int
(CountryId
的默认值),则会选择“-Please select-”选项。如果CountryId
的值与集合中的某个值匹配,则在呈现视图时将选择该选项。由于int
的类型为IndexViewModel
,因此如果用户未选择有效的国家/地区,则会生成验证错误。
最后,尽管States
命名,但它不是视图模型!视图模型仅包含在视图中显示/编辑所需的属性,因此应删除您拥有的3个虚拟属性(可能还有与Cities
和sphereRadiusCGFloat = sphereRadiusFloat.map{CGFloat($0)}
相关的4个属性,但不确定是否刚刚从视图和控制器中省略了一些代码)