如何在 MVC3 中设计登录屏幕?






4.43/5 (5投票s)
通过创建登录屏幕来启动 MVC 项目。
这是 MVC 项目的快速入门。登录表单是每个项目的第一部分。有几种方法可以创建登录功能。我将演示其中一种,并构建基本的 MVC3 项目结构,以便您可以根据项目需求进行增强。
答案
让我们看看项目结构。我创建了一个空的 MVC3
项目。在 App_Data
文件夹中有一个名为 Student
的数据库。我在 MVC 的 Model 文件夹中创建了一个名为 S
tudent_db.edmx
的 ADO.NET entity
data model
作为我的 Model
。
添加名为 Home 的 controller
并创建名为 index 的 action
。创建 index View
。Index 是我们网站的启动页面。打开 Global.asax
,其中包含 RegisterRoutes
方法,如下所示。
public static void RegisterRoutes(RouteCollection routes)<br /> {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Home", action = "Index"} // Parameter defaults
,new[] {"LoginScreenDemo.Controllers"}
);
}
RegisterRoutes
是在 Application_Start
事件中调用的静态方法。RegisterRoutes
接受 RouteCollection
对象作为参数,并调用 RouteCollection
类的 MapRoute
方法。MapRoute
方法具有接受路由名称、带参数的 URL 和 URL 默认参数的重载。Controller Home 和 action Index 被指定为 URL 的默认参数,这设置了我们的启动页面。
我已经设计了如下的 index 页面。
LogIn 是一个锚标签,它导航到 Login 页面。
我已经设计了如下的登录页面。
这里的技巧是,点击 LogIn 链接时,我们不会导航到登录页面,而是将登录页面显示为弹出窗口,如下所示。
让我们仔细看看 IndexView。
我使用了 ajax
辅助方法来创建 LogIn action 链接。单击 LogIn 链接时,它会异步调用 controller action,并将返回的视图渲染到 updateTargetControllId
。
我已经将 updateTargetControllId
设置为 div 标签的 id,因此返回的局部视图会渲染到 div 中。我使用了名为 bpopup 的 JQuery 插件来将 div 显示为弹出窗口。
Ajax
辅助方法要使用 Ajax
辅助方法,您需要在页面中添加以下 Jquery。我选择了最小版本,因为它很轻量。
<script src="@Url.Content("../../Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
<script src="@Url.Content("../../Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
您可以使用 Ajax
辅助方法,通过使用 @Ajax.
语法。我使用 LogIn action 链接执行了 Ajax 调用。
<li class="nav">
@Ajax.ActionLink("Login", "Login", new { area="" }, new AjaxOptions() { UpdateTargetId = "loginView" }, new { id = "lnkLogin", @class="nav" })
</li>
<h2>Home Page</h2>
<h2>Some site description!!!!</h2>
<br />
<div id="loginView" class="white_content">
</div>
我添加了 css 类 nav
,为 action 链接提供菜单项的外观。Action 链接 LogIn 调用 Home controller 的 Login action,并将返回的局部视图渲染到 id 为 loginView 的 div 中。
<div id="loginView" class="white_content"><br /></div>
Login View Login View 由一个表单组成,其中包含用于 username
和 password
的标签和文本框,以及用于提交表单的按钮。我将 Login 创建为 partial view
,因为它会渲染到 Index View
中。Login 是一个类型为 ViewModel
类的局部强类型 View
。对于每个强类型 View
,我都创建了一个 ViewModel
类。ViewModel 表示您想在 view/page
上显示的数据。
@model LoginScreenDemo.ViewModel.LoginVM <div id="pnl_Login"> @using (Ajax.BeginForm("Login", "Home", new { area = "" } , new AjaxOptions { UpdateTargetId = "error_message", OnSuccess = "RedirectToUrl", OnFailure = "OnFailuar", OnBegin = "validateForm" }, new { method = FormMethod.Post })) { <table border="0"> <tr> <td> @Html.LabelFor(Model => Model.LoginName) </td> <td> @Html.TextBoxFor(Model => Model.LoginName) </td> <td> @Html.ValidationMessageFor(Model => Model.LoginName, "*") </td> </tr> <tr> <td> @Html.LabelFor(Model => Model.Password) </td> <td> @Html.PasswordFor(Model => Model.Password) </td> <td> @Html.ValidationMessageFor(Model => Model.Password, "*")<br /> </td> </tr> <tr> <td> </td> <td> <input type="submit" value="Login" /> <input type="button" value="Cancle" class="loginClose" /> </td> <td> </td> </tr> </table> <div id="error_message"> @Html.ValidationSummary(true) </div> } </div>
用于处理 AjaxForm
OnSuccess
和 OnFailuar
方法的 Javascript。
<script> function RedirectToUrl(Result) { if (Result == 1) window.open("/Home/SiteMap", "_self"); else $("#loginView").html(Result); } function OnFailuar(exMessage) { $("#error_message").html(exMessage); } function validateForm() { } </script>
ViewModel
的对象在 controller
action
method
中填充,并传递给 View
。Controller
action
method
调用其 Manager class (Business class)
来填充 ViewModel
对象。
每个强类型 View
都是 ViewModel
类类型,并具有一个 Action
Method
。Action
Method
将 ViewModel
对象传输到 View
。Action
method
调用其 Manager
class
的方法来填充 ViewModel
对象。Manager
Class
与数据库(即实体模型)交互,并提供一个或多个实体对象到 ViewModel
对象的映射。
LoginManager class [Manager Class
] 包含与数据库交互并返回结果的逻辑。
public class LoginManager:BaseManager { public string RollName {get;set;} public bool ValidateLogin(LoginVM loginContext) { var result= (from login in studentContext.tblLogins where login.LoginName == loginContext.LoginName && login.Password == loginContext.Password select new { login.Role, login.LoginName}).FirstOrDefault(); if (result.LoginName == null) { return false; } RollName = result.Role; return true; } public string GetRole(string userName) { return (from login in studentContext.tblLogins where login.LoginName ==userName select login.Role).FirstOrDefault(); } }
通常,Manager class
包含获取数据、插入数据和更新数据的函数。
获取数据函数将从数据库中获取数据,填充 ViewModel
对象并返回给 action 方法。插入和更新则在我们当前使用 entity framework
的情况下,在数据库中执行插入和更新。
LoginVM class [ViewModel class
] 每个 View
直接映射到 ViewModel
或 IEnumerable<ViewModel>
,以便在 View
中提供 ViewModel
的集合。每个强类型 View
都是 ViewModel
或 IEnumerable<ViewModel>
类型。ViewModel
包含与实体集中的一个或多个实体相关的属性。例如,LoginName
可能存在于实体类 tblNameMaster
中,而 Password
可能存在于实体类 tblRecordMaster
中。其中 tblNameMaster
和 tblRecordMaster
直接映射到数据库表对象架构。
注意:- 在代码优先方法中,您可以创建实体,然后从实体生成数据库架构。
public class LoginVM:BaseVM { [Required(ErrorMessage="Please enter valid user name.")] public string LoginName { get; set; } [Required(ErrorMessage="Please enter valid password.")] public string Password { get; set; } }
LoginVM class
使用 using System.ComponentModel.DataAnnotations
namespace
来为 LoginName
和 Password
属性提供验证。目前,我使用了 Required()
数据注释属性来指示 LoginName
和 Password
不能为空。如果您查看 Login 视图,您会注意到以下代码。
@Html.ValidationMessageFor(Model =>Model.LoginName, "*") @Html.ValidationMessageFor(Model=> Model.Password, "*") @Html.ValidationSummary(true)
@Html.VlaidationMessageFor
辅助类帮助我们为提供内联验证消息。
@ValidationSummary
方法显示页面上所有验证消息的列表。
当 View
被渲染时,验证消息和 validation summary
会根据 ModelState
对象的 Errors 属性显示。
以下是帮助我们提供客户端验证消息的 JavaScript
。
<script src="@Url.Content("../../Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("../../Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
Jquery.validate.min.js
包含验证逻辑,而 jquery.validate.unobtrusive.js
则移除内联 jquery 代码并提供一些漂亮的属性来调用它。如果您注意到项目的 web.config,您会注意到以下键,这些键有助于启用 client side validation
。
<appSettings> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> </appSettings>
请阅读以下 codeproject 文章以获取更多关于 MVC 验证的知识。
https://codeproject.org.cn/Articles/249452/ASP-NET-MVC3-Validation-Basic
用户在登录弹出窗口中输入凭据。有效用户将被重定向到 Sitemap page
。如果用户无效,将显示相应的消息。一旦用户登录,让我们识别用户的角色。根据分配给用户的角色,用户将被授予访问页面的权限。如果用户没有权限访问页面,他将被重定向到登录页面。我使用了自定义基于角色的表单身份验证。
我在 web.config
中添加了以下代码来启用表单身份验证。
<authentication mode="Forms"> <forms loginUrl="/Home/Index" timeout="2880" /> </authentication>
Login URL 指示用户未经验证时将重定向到的 URL。
我还覆盖了 Global.asax
文件中的 FormsAuthentication_OnAuthenticate
方法。
protected void FormsAuthentication_OnAuthenticate(Object sender, FormsAuthenticationEventArgs e) { if (FormsAuthentication.CookiesSupported == true) { if (Request.Cookies[FormsAuthentication.FormsCookieName] != null) { try { //let us take out the username now string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name; string roles = string.Empty; LoginScreenDemo.Business.LoginManager loginManager = new Business.LoginManager(); roles = loginManager.GetRole(username); //Let us set the Pricipal with our user specific details e.User = new System.Security.Principal.GenericPrincipal( new System.Security.Principal .GenericIdentity(username, "Forms"), roles.Split(';')); } catch (Exception) { //somehting went wrong //log error } } }
我创建了一个 GenericPrincipal
对象,并将我们的用户特定详细信息(用户名和角色)放入其中。请参阅以下文章,了解如何在 MVC 中创建自定义表单身份验证。https://codeproject.org.cn/Articles/578374/AplusBeginner-27splusTutorialplusonplusCustomplusF
我创建了两个区域 [organizer 和 monitor],它们表示项目中的学生角色。您可以通过右键单击项目名称 -> 添加 -> 区域来创建区域,并为新区域指定名称。区域创建完成后,我们会看到一个名为 Areas 的新文件夹,在该文件夹中您可以看到一个与您的区域同名的文件夹。区域内容与您的项目具有相同的文件结构,您可以将区域视为父 MVC
项目内的子项目。
很多时候,我们遇到需要从一个父部分导航到另一个部分的情况。为了获得更好的用户体验,让我们将父部分创建为 View
,所有相关部分创建为 Partial View
,并根据需要将它们渲染到父部分中。
@{ Layout = "~/Views/Shared/_Layout1.cshtml"; ViewBag.Title = "Monitor"; } <h2> Moniter Task.</h2> <div class="nav"> <ul class="nav"> <li class="nav"> @Html.ActionLink("Site Map", "SiteMap", "Home", new { area = "" }, new { @class = "nav" }) </li> <li class="nav"> @Ajax.ActionLink("Task1", "Task1", "Home", new { Area = "Moniter" }, new AjaxOptions { UpdateTargetId = "body_content" }, new { @class = "nav" }) </li> <li class="nav"> @Ajax.ActionLink("Task2", "Task2", "Home", new { Area = "Moniter" }, new AjaxOptions { UpdateTargetId = "body_content" }, new { @class = "nav" }) </li> </ul> </div> <div id="body_content"> </div>
View
作为父视图。Index 视图包含与 Monitor 任务相关的页面的导航栏。为了获得更好的 UI 体验,我没有导航到相关页面,而是创建了 Partial View
和 PartialViewResult
。其中导航链接是 @ajax.actionlink
,它将 Partial View
渲染到同一页面上。单击 task1 链接时,ajax
actionlink 调用 Partial View
action
task1,并返回 Partial View
。它将 Partial View
渲染到 id 指定为 update target control id 的元素内。
使用相同的逻辑,我创建了其他 area
controller
action
。在开发实际项目时,您将拥有复杂的逻辑,而不是 Partial View
中简单的“Task One Begin..”消息。
请查看附件代码以获得更清晰的说明。希望这能帮助您开始应用程序开发。