我的任务是在一个视图上创建登录和注册表单!
我有家的看法。在主视图中,我有两种形式,登录和注册。它们由@ Html.RenderPartial(部分视图名称,模型)呈现。该表单与帐户控制器(登录和注册操作)有关。
让我先给你一些代码......
模型:
// Login model, that contains email and password
public class Login
{
…
}
// Registration model that contains minimum user data, e.g. name, surname
public class Register
{
...
}
// Model for home view which contains models for both register and login
public class Home
{
public Login LoginModel { get; set; }
public Register RegisterModel { get; set; }
}
视图: Index.cshtml
@model App.Models.Home.Home
<!-- Login Box -->
@{ Html.RenderPartial("_LoginArea", Model.LoginModel); }
<!-- Register Box -->
@{ Html.RenderPartial("_RegisterArea", Model.RegisterModel); }
_LoginArea.cshtml
@model App.Models.Account.Login
<div style="float: left; margin-right: 100px;">
<h1>@Localization.Account.Login</h1>
<!-- Login form -->
<div id="loginBox">
@using (Html.BeginForm("Login", "Account", FormMethod.Post))
{
<div class="editor-label">
@Html.LabelFor(m => m.Email):
</div>
<div class="editor-field">
@Html.TextBoxFor(m => m.Email)
@Html.ValidationMessageFor(m => m.Email)
</div>
<div class="editor-label">
@Html.LabelFor(m => m.Password):
</div>
<div class="editor-field">
@Html.PasswordFor(m => m.Password)
@Html.ValidationMessageFor(m => m.Password)
</div>
<div class="editor-label">
@Html.CheckBoxFor(m => m.RememberMe)
@Html.LabelFor(m => m.RememberMe)
</div>
<p>
<input type="submit" value="@Localization.Account.Login" />
</p>
}
</div>
</div>
_RegisterArea.cshtml
@model App.Models.Account.Register
<div style="vertical-align: bottom;">
<h1>@Localization.Account.Register</h1>
<div>
@using (Html.BeginForm("Register", "Account"))
{
//same things like in login
}
...
控制器:
的HomeController
//
// GET: /Home/
public ActionResult Index(Home model)
{
//
// If logedin redirect to profile page
// Else show home page view
//
if (Request.IsAuthenticated)
{
return RedirectToAction("Index", "User", new { id = HttpContext.User.Identity.Name });
}
else
{
model.LoginModel = new Login();
model.RegisterModel = new Register();
return View(model);
}
}
只显示来自帐户控制器的登录操作
//
// POST: /Account/Login
[HttpPost]
public ActionResult LogIn(Login model)
{
if (Request.IsAuthenticated)
{
return RedirectToAction("Index", "User", new { id = HttpContext.User.Identity.Name });
}
else
{
if (ModelState.IsValid)
{
if (model.ProcessLogin())
{
return RedirectToAction("Index", "User", new { id = HttpContext.Session["id"] });
}
}
}
//Note: this is problem part
// If we got this far, something failed, redisplay form
return View("~/Views/Home/Index.cshtml", model);
}
所以一切正常,但!当模型状态无效时,我有以下异常
The model item passed into the dictionary is of type 'App.Models.Account.Login', but this dictionary requires a model item of type App.Models.Home.Home'.
我可以将部分视图和帐户操作绑定到Home模型,但这不是我需要的。 我打算在其他视图中使用_LoginArea.cshtml视图(例如在'User'视图的页眉中,该视图有另一个模型) 所以,我需要动作方法(例如Login)来检索Login模型,而不是Home或其他任何东西。但在这种情况下,我无法将模型返回到Home视图。 我该如何解决这个问题?什么是最好的方法? 很抱歉有很多代码,只想要清楚的事情。
答案 0 :(得分:3)
在这种情况下,我建议建立一个中央登录/注册页面,用户将在验证失败时重定向到。出于示例的目的,假设这是一个名为SiteAuthenticate
因此,对于您的LogIn(Login model)
操作,如果验证失败,您将始终返回SiteAuthenticate
视图,该视图将被强类型化以包含Login
和Register
模型,与您的Home
模型非常相似。
使此方法有效的最后一个方法是向ReturnUrl
和Login
模型添加Register
属性。这可以根据您的意愿填充,也可以使用Request.UrlReferrer
之类的内容填充。通过这种方式,您可以在最终登录/注册成功时知道将用户送回的位置。
因此,当完成所有操作后,您的LogIn
操作可能如下所示:
[HttpPost]
public ActionResult LogIn(Login model)
{
if (Request.IsAuthenticated)
{
return RedirectToAction(model.ReturnUrl);
}
else
{
if (ModelState.IsValid)
{
if (model.ProcessLogin())
{
return RedirectToAction(model.ReturnUrl);
}
}
}
// If we got this far, something failed. Return the generic SiteAuthenticate view
var saModel = new SiteAuthModel { LoginModel = model };
return View("~/Views/Account/SiteAuthenticate.cshtml", saModel);
}
您的SiteAuthenticate
也会发回相同的Login
行动。由于您已经传递了原始的RetunrUrl,如果登录成功,则该用途将按计划重定向到其原始目的地。
希望有所帮助,如果有任何不清楚或没有意义,请告诉我。
答案 1 :(得分:2)
解决!!!使用 Html.RenderAction 代替。 这是代码:
Index.cshtml
<!-- Login form -->
@{ Html.RenderAction("Login", "Account"); }
<!-- Register form -->
@{ Html.RenderAction("Register", "Account"); }
部分观点相同......
控制器的行动:
//
// GET: /Account/Login
public ActionResult Login()
{
Login model = new Login();
if (TempData.ContainsKey("Login"))
{
ModelStateDictionary externalModelState = (ModelStateDictionary)TempData["Login"];
foreach (KeyValuePair<string, ModelState> valuePair in externalModelState)
{
ModelState.Add(valuePair.Key, valuePair.Value);
}
}
return View("_LoginHome", model);
}
//
// POST: /Account/Login
[HttpPost]
public ActionResult Login(Login model)
{
if (Request.IsAuthenticated)
{
return RedirectToAction("Index", "User", new { id = HttpContext.User.Identity.Name });
}
else
{
if (ModelState.IsValid)
{
if (model.ProcessLogin())
{
return RedirectToAction("Index", "User", new { id = HttpContext.Session["id"] });
}
}
}
TempData.Remove("Login");
TempData.Add("Login", ModelState);
// If we got this far, something failed, redisplay form
return RedirectToAction("Index", "Home");
}
注册操作也是如此。
正如您所见,我正在使用 TempData 来存储模型状态,然后在操作开始渲染时检索它。 另一个问题是,如果模型状态无效,我们怎么知道应该回到哪里。我的解决方案是解析 Request.UrlReferrer ,就像ataddeini说的那样。
非常感谢我的朋友 Danylchuk Yaroslav 为他提供帮助!