视图错误中的多个模型

时间:2013-02-13 18:15:37

标签: asp.net-mvc-4 model viewmodel asp.net-mvc-viewmodel

我的视图页面具有不同的部分视图和不同的模型。我创建了一个模型类,它将调用其他类,以便我可以在主视图页面上使用它。但我的问题是,当我尝试更改密码时,它给我一个错误,我传递的模型,我需要传递给另一个模型。我相信我的结构正确,但不确定是什么导致了这个问题。

主要观点:

 @model Acatar.Models.ProfileModel

        @{
            ViewBag.Title = "ProfileAccount";
        }
        @{ Html.RenderAction("_PlayNamePartial"); }
        @{ Html.RenderAction("_UsernamePartial", "Account");}
        @{ Html.RenderAction("_TalentsPartial", "Account");}

            @if (ViewBag.HasLocalPassword)
            {
                @Html.Partial("_ChangePasswordPartial")
            }
            else
            { 
                @Html.Partial("_SetPasswordPartial")
            }

个人资料模型:包含我已创建的模型

public class ProfileModel
    {
        public LocalPasswordModel LocalPasswordModel { get; set; }
        public PlayNameModel PlayNameModel { get; set; }
        public UsernameModel UsernameModel { get; set; }
        public TalentsModel  TalentsModel { get; set; }
    }

控制器:

public ActionResult Profile(ManageMessageId? message)
    {
        ViewBag.StatusMessage =
            message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
            : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
            : message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
            : "";
        ViewBag.HasLocalPassword = OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
        ViewBag.ReturnUrl = Url.Action("Profile");
        return View();
    }

POST:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Profile(LocalPasswordModel model)
    {
        bool hasLocalAccount = OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
        ViewBag.HasLocalPassword = hasLocalAccount;
        ViewBag.ReturnUrl = Url.Action("Profile");
        if (hasLocalAccount)
        {
            if (ModelState.IsValid)
            {
                // ChangePassword will throw an exception rather than return false in certain failure scenarios.
                bool changePasswordSucceeded;
                try
                {
                    changePasswordSucceeded = WebSecurity.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword);
                }
                catch (Exception)
                {
                    changePasswordSucceeded = false;
                }

                if (changePasswordSucceeded)
                {
                    return RedirectToAction("Profile", new { Message = ManageMessageId.ChangePasswordSuccess });
                }
                else
                {
                    ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                }
            }
        }
        else
        {
            // User does not have a local password so remove any validation errors caused by a missing
            // OldPassword field
            ModelState state = ModelState["OldPassword"];
            if (state != null)
            {
                state.Errors.Clear();
            }

            if (ModelState.IsValid)
            {
                try
                {
                    WebSecurity.CreateAccount(User.Identity.Name, model.NewPassword);
                    return RedirectToAction("Profile", new { Message = ManageMessageId.SetPasswordSuccess });
                }
                catch (Exception e)
                {
                    ModelState.AddModelError("", e);
                }
            }
        }

        return View(model);
    }

查看密码更改页面:

@model Project.Models.LocalPasswordModel


@using (Html.BeginForm("Profile", "Account")) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    <fieldset>
        <legend>Change Password Form</legend>

                @Html.LabelFor(m => m.OldPassword)
                @Html.PasswordFor(m => m.OldPassword)

                @Html.LabelFor(m => m.NewPassword)
                @Html.PasswordFor(m => m.NewPassword)

                @Html.LabelFor(m => m.ConfirmPassword)
                @Html.PasswordFor(m => m.ConfirmPassword)

       <br/>
        <input class="btn btn-small" type="submit" value="Change password" />
    </fieldset>

我得到的错误: The model item passed into the dictionary is of type 'Project.Models.LocalPasswordModel', but this dictionary requires a model item of type 'Project.Models.ProfileModel'.

1 个答案:

答案 0 :(得分:0)

尝试在@Html.Partial方法中指定模型。 (请原谅我的语法,我现在没有IDE

        @if (ViewBag.HasLocalPassword)
        {
            @Html.Partial("_ChangePasswordPartial",Model.LocalPasswordModel)
        }
        else
        { 
            @Html.Partial("_SetPasswordPartial",Model.LocalPasswordModel)
        }

(我猜第二个视图也使用相同的模型) 但我看不到任何模型从你的控制器传递到你的视图中,你应该传递一个模型来查看

public ActionResult Profile(ManageMessageId? message)
    {
        ViewBag.StatusMessage =
            message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
            : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
            : message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
            : "";
        ViewBag.HasLocalPassword = OAuthWebSecurity.HasLocalAccount(WebSecurity.GetUserId(User.Identity.Name));
        ViewBag.ReturnUrl = Url.Action("Profile");

        var ProfileModel = new ProfileModel();
        ProfileModel.LocalPasswordModel = populateFromDB();
        return View(ProfileModel);
    }

或者考虑创建一个动作结果来渲染这个局部视图,就像你对其他部分视图一样。(如果这里没有使用Html.partial的其他意图)

           @if (ViewBag.HasLocalPassword)
            {
                @Html.RenderAction("_ChangePasswordPartial")
            }
            else
            { 
                @Html.RenderAction("_SetPasswordPartial")
            }