I'm using modals for logging in and registering a user. Each modal is strongly typed to make use of the ASP.NET built-in account classes (RegisterModel and LoginModel). However, since the two buttons to call these modals are located on the navbar and the navbar is placed on every page I receive errors because most views are strongly typed and thus cannot handle a partialview (the modal) to be using a different strongly typed model.

How are strongly typed modals handled in a strongly typed environment?

_Layout:

<body>
 <div class="navbar">
  @Html.Partial("_LoginPartial") // contains buttons to call login/register modals
 </div>

 <div>
  @Html.Partial("_LoginModal")
  @Html.Partial("_RegisterModal")
 </div>

 <div class="container">
  @Html.RenderBody()
 </div>
</body>

/News/Index:

@model List<NewsBulletinViewModel>

LoginModal:

@model NoName.Models.LoginModel

On a related note: Since I have forms inside my modals, how can I refer back to those modals when validation errors occur? Ideally the modal should popup again (or never be closed) with the validation errors shown.

有帮助吗?

解决方案

There is an overload in @Html.Partial that takes an object, used for the partial page's Model. If you include the Partial in your layout, in every page, you need a logic to keep that data. For example, if you take LoginModel and RegisterModel, you could do this:

@Html.Partial("_LoginPartial", ViewBag.LoginModel ?? new LoginModel())
@Html.Partial("_RegisterPartial", ViewBag.RegisterModel ?? new RegisterModel())

And leave to the executing controller the role to put a LoginModel (or RegisterModel). If there isn't any in the ViewBag, it will fallback to creating an empty one.

Edit: Based on the additional information, I'd do this for the LoginPartial (RegisterPartial would be the same logic):

public class AccountController : Controller
{
    public ActionResult LoginPartial()
    {
        return PartialView("_LoginPartial", (Session["Login"] as LoginModel) ?? new LoginModel());
    }

    [HttpPost]
    public HttpStatusCodeResult SaveLoginModel(LoginModel model)
    {
        Session["Login"] = model;
        return new HttpStatusCodeResult(200);
    }
}

And then, in _LoginPartial, do as you would, but add a javascript code to send an ajax post request to the SaveLoginModel action of your controller when the value change to keep your model in sync (there is plenty of information around on how to do that).

Now, instead of doing:

@Html.Partial("_LoginPartial", ViewBag.LoginModel ?? new LoginModel())
@Html.Partial("_RegisterPartial", ViewBag.RegisterModel ?? new RegisterModel())

You would do:

@Html.Action("LoginPartial", "AccountController");
@Html.Action("RegisterPartial", "AccountController");
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top