【问题标题】:Foreach to return Model.Roles is failing with null reference exceptionForeach 返回 Model.Roles 因空引用异常而失败
【发布时间】:2018-01-19 08:40:24
【问题描述】:

我正在尝试在 EF 应用程序中实现角色。我让它在所有脚手架视图(创建、删除、详细信息)上工作,但无法让 Edit 视图工作。

GET 方法可以正常返回数据(当我进入编辑页面时,我正确地看到了角色):

但是,如果我进行更改并保存它,我会收到错误消息:

对象引用未设置为对象的实例。
第 47 行:@Html.Label("Roles", new { @class= "control-label col-md-2" })
第 48 行:
第 49 行:@foreach(Model.RolesList 中的变量项)
第 50 行:{
第 51 行: 选中="@item.Selected" class="checkbox-inline" />

我的GetPost方法如下:

//
// GET: /Users/Edit/1
public async Task<ActionResult> Edit(string id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    var user = await UserManager.FindByIdAsync(id);
    if (user == null)
    {
        return HttpNotFound();
    }

    var userRoles = await UserManager.GetRolesAsync(user.Id);

    return View(new EditUserViewModel()
    {
        Id = user.Id,
        Email = user.Email,
        Username = user.UserName,
        FirstName = user.FirstName,
        LastName = user.LastName,

        RolesList = RoleManager.Roles.ToList().Select(x => new SelectListItem()
        {
            Selected = userRoles.Contains(x.Name),
            Text = x.Name,
            Value = x.Name
        })

    });
}

//
// POST: /Users/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "Email,Id,Username,FirstName,LastName")] EditUserViewModel editUser, params string[] selectedRole)
{
    if (ModelState.IsValid)
    {
        var user = await UserManager.FindByIdAsync(editUser.Id);
        if (user == null)
        {
            return HttpNotFound();
        }

        user.UserName = editUser.Username;
        user.Email = editUser.Email;
        user.FirstName = editUser.FirstName;
        user.LastName = editUser.LastName;

        var userRoles = await UserManager.GetRolesAsync(user.Id);

        selectedRole = selectedRole ?? new string[] { };

        var result = await UserManager.AddToRolesAsync(user.Id, selectedRole.Except(userRoles).ToArray<string>());

        if (!result.Succeeded)
        {
            ModelState.AddModelError("", result.Errors.First());
            return View();
        }
        result = await UserManager.RemoveFromRolesAsync(user.Id, userRoles.Except(selectedRole).ToArray<string>());

        if (!result.Succeeded)
        {
            ModelState.AddModelError("", result.Errors.First());
            return View();
        }
        return RedirectToAction("Index");
    }
    ModelState.AddModelError("", "Something failed.");
    return View();
}

我的观点中有问题的部分是:

<div class="form-group">
    @Html.Label("Roles", new { @class = "control-label col-md-2" })
    <span class="col-md-10">
        @foreach (var item in Model.RolesList)
        {
            <input type="checkbox" name="SelectedRole" value="@item.Value" checked="@item.Selected" class="checkbox-inline" />
            @Html.Label(item.Value, new { @class = "control-label" })
        }
    </span>
</div>

我在控制器中设置了rolemanager

private ApplicationRoleManager _roleManager;
public ApplicationRoleManager RoleManager
{
    get
    {
        return _roleManager ?? HttpContext.GetOwinContext().Get<ApplicationRoleManager>();
    }
    private set
    {
        _roleManager = value;
    }
}

这是在我的Startup.auth:

app.CreatePerOwinContext<ApplicationRoleManager>(ApplicationRoleManager.Create);

我非常有信心 rolemanager 设置正常,因为它成功地恢复了 CreateDetails 页面上的角色。那为什么是

@foreach (var item in Model.RolesList)

这里出现空引用异常失败?

【问题讨论】:

  • 尝试使用@html.checkboxfor()
  • 你能发布你的完整视图吗?

标签: entity-framework authorization roles


【解决方案1】:

你可以采取几个步骤

您应该在返回视图上传递模型以再次加载带有 ModelState 错误的视图。

return View(editUser);

如果您使用 c#6 或更高版本,则可以利用null-conditional operator 来避免以下行中的null reference exception

@foreach (var item in Model?.RolesList)

更新

我只是添加您的错误“对象引用未设置为对象的实例。”的控制流 如果您在[HttpPost] 上的ModelState.IsValid 上添加断点,您可能会注意到您的ModelState.IsValid 是错误的。出于这个原因,它试图转到视图,但您没有在方法的最后一行 return View(); 上发送您的模型。现在视图将null 引用到模型中。最后,它上线了foreach (var item in Model.RolesList)

所以检查一下,你在 ModelState 上遇到了什么错误,模型验证不成功

【讨论】:

  • 干杯@MJK,很抱歉无线电沉默(因为没有互联网连接而离开)。该问题是由于 ModelState 验证失败,因为模型需要密码。在验证之前添加了 ModelState.Remove("Password") ,现在一切正常。
【解决方案2】:

Edit [HttpPost] 方法不返回模型:

return View();

应该是

return View(editUser);

此外,您需要确保 editUser 包含 selectedRole 属性,否则您将收到相同(或类似)的错误。

否则,创建并返回一个新的 EditUserViewModel 对象,就像您在 Get 方法中所做的那样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-09
    • 2020-11-14
    • 2018-03-12
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多