我的 SelectListItem 中的 post 操作出现 NullReferenceException

I am getting NullReferenceException on a post action in my SelectListItem

我在角色和订阅上得到了 NullReferenceException,我不确定为什么,我的 Model.State 检查是 false,所以它是无效的。我已将与 get 方法相同的视图模型传递给 post 方法。

表格

<div class="form-group">
    @Html.LabelFor(m => m.User.UserRoles)
    @Html.DropDownListFor(m => m.User.SelectedUserRoleId, Model.User.UserRoles, "Role", new { id = "txtBusinessName", @class = "form-control", placeholder = "Business Name" })
</div>

<div class="form-group">
    @Html.LabelFor(m => m.Business.Subscriptions)
    @Html.DropDownListFor(m => m.Business.SelectedSubscriptionId, Model.Business.Subscriptions, "Subscription Type", new { id = "txtBusinessName", @class = "form-control", placeholder = "Business Name" })
</div>

型号

public class RegisterationViewModel
{
    public BusinessViewModel Business { get; set; }
    public UserViewModel User { get; set; }
}

UserViewModel 属性有错误

public Guid SelectedUserRoleId {get; set;}

[Display(Name = "Role")]
[Required]
public IEnumerable<SelectListItem> UserRoles { get; set; } 

BusinessViewModel 属性有错误

public Guid SelectedSubscriptionId {get; set; }
[Display(Name = "Subscription Type")]
[Required]
public IEnumerable<SelectListItem> Subscriptions { get; set; }

获取方法

[HttpGet]
public ActionResult Register()
{
    var businessSubscriptionViewModels = new List<BusinessSubscriptionViewModel>();
    var userRoleViewModels = new List<UserRoleViewModel>();

    var registrationViewModel = new RegisterationViewModel();
    businessSubscriptionViewModels.AddRange(
        _subscriptionServiceClient.GetBusinessSubscriptionContracts()
            .Select(Mapper.Map<BusinessSubscriptionContract, BusinessSubscriptionViewModel>));

    registrationViewModel.Business = new BusinessViewModel
    {
        Subscriptions = new SelectList(businessSubscriptionViewModels, "Id", "Name")
    };

    userRoleViewModels.AddRange(
        _userRoleServiceClient.GetUserRoles().Select(Mapper.Map<UserRoleContract, UserRoleViewModel>));

    registrationViewModel.User = new UserViewModel
    {
        UserRoles = new SelectList(userRoleViewModels, "Id", "Name")
    };
    return View(registrationViewModel);
}

Post方法

[HttpPost]
public ActionResult Register(RegisterationViewModel registerationViewModel)
{
    if (!ModelState.IsValid)
    {
        return View();
    }

    var businessContract = Mapper.Map<BusinessViewModel, BusinessContract>(registerationViewModel.Business);
    var registeredBusiness = _businessRegistrationServiceClient.CreateBusiness(businessContract);

    var userContract = Mapper.Map<UserViewModel, UserContract>(registerationViewModel.User);
    var registeredUser = _userServiceClient.CreateUser(businessContract.ID, userContract);


    return View(registerationViewModel);
}

您的 UserRolesSubscriptions 属性在发布后将为空,因为只有 selected 选项的 value select 列表将被发布,而不是 select 列表本身。此外,根据已发布或未发布的内容,视图模型上的 Business and/or User 属性也可能为空。如果这些实例上至少有一个 属性 已发布,则模型绑定器只会为这些属性新建一个实例。例如,如果有人将表单的整个 "user" 部分留空,则 User 将为空,并且尝试访问 User 上的任何 属性 将导致 NullReferenceException.

您需要确保 BusinessUser 始终具有一个值(通过视图模型的构造函数或自定义 getter 和 setter),或者您需要在之前显式检查空值访问他们的任何成员。

我弄明白了,错误是我对 SelectListItems 属性 进行了 Required 验证检查。但是在 post 上,select 列表绑定到的值是唯一会像 Chris 建议的那样被 posted 的东西。

如果我想保持相同的必需验证,我已将验证设置为 SelectListItem 绑定到的 Selected 属性。这样,由于 SelectListItem 为空,SelectedUserRoleId 或 SelectedBusinessSubscriptionId 将不会。

简单修复

[Required]
public Guid SelectedUserRoleId {get; set;}

[Display(Name = "Role")]
public IEnumerable<SelectListItem> UserRoles { get; set; } 

[Required]
public Guid SelectedSubscriptionId {get; set; }

[Display(Name = "Subscription Type")]
public IEnumerable<SelectListItem> Subscriptions { get; set; }