七天学会ASP.NET MVC (五)——Layout页面使用和用户角色管理

day5

系列文章

七天学会ASP.NET MVC (一)——深刻理解ASP.NET MVChtml

七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递浏览器

七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理安全

七天学会ASP.NET MVC (四)——用户受权认证问题session

七天学会ASP.NET MVC (五)——Layout页面使用和用户角色管理mvc

 

目录ide

实验22——添加页脚函数

实验23——实现用户角色管理布局

实验24——实现项目外观一致性post

实验25——使用Action  过滤器让页眉和页脚代码更有效学习

总结

 

实验22——添加页脚

在本实验中,咱们会在Employee 页面添加页脚,经过本实验理解分部视图。

什么是“分部视图”?

从逻辑上看,分部视图是一种可重用的视图,不会直接显示,包含于其余视图中,做为其视图的一部分来显示。用法与用户控件相似,但不须要编写后台代码。

1. 建立分部视图的 ViewModel

右击 ViewModel 文件夹,新建 FooterViewModel 类,以下:

 1: public class FooterViewModel
 2: {
 3:  public string CompanyName { get; set; }
 4:  public string Year { get; set; }
 5: }

2. 建立分部视图

右击“~/Views/Shared”文件夹,选择添加->视图。

输入View 名称”Footer”,选择复选框“Create as a partial view”,点击添加按钮。

注意:View中的Shared 共享文件夹是为每一个控制器均可用的文件夹,不是某个特定的控制器所属。

3. 在分部View 中显示数据

打开Footer.cshtml,输入如下HTML 代码。

 1: @using WebApplication1.ViewModels
 2:  
 3: @model FooterViewModel
 4:  
 5: <div style="text-align:right;background-color: silver;color: darkcyan;border: 1px solid gray;margin-top:2px;padding-right:10px;">
 6:  
 7:  @Model.CompanyName © @Model.Year
 8:  
 9: </div>

4.  在Main ViewModel 中包含Footer 数据

打开 EmployeeListViewModel 类,添加新属性,保存 Footer数据,以下:

 1: public class EmployeeListViewModel
 2: {
 3:  public List<EmployeeViewModel> Employees { get; set; }
 4:  
 5:  public string UserName { get; set; }
 6:  
 7:  public FooterViewModel FooterData { get; set; }//New Property
 8: }

在本实验中Footer会做为Index View的一部分显示,所以须要将Footer的数据传到Index View页面中。Index View 是EmployeeListViewModel的强类型View,所以Footer须要的全部数据都应该封装在EmployeeListViewModel中。

5. 设置Footer 数据

打开 EmployeeController ,在Index  action 方法中设置FooterData 属性值,以下:

 1: public ActionResult Index()
 2: {
 3:  ...
 4:  ...
 5:  employeeListViewModel.FooterData = new FooterViewModel();
 6:  employeeListViewModel.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value
 7:  employeeListViewModel.FooterData.Year = DateTime.Now.Year.ToString();
 8:  return View("Index", employeeListViewModel);
 9: }

6. 显示Footer

打开Index.cshtml 文件,在Table 标签后显示Footer 分部View,以下:

 1: </table>
 2:  @{
 3:  Html.RenderPartial("Footer", Model.FooterData);
 4:  }
 5:  </div>
 6: </body>
 7: </html>

7. 运行,打开Index View

关于实验22

 Html.Partial的做用是什么?与Html.RenderPartial区别是什么?

与Html.RenderPartial做用相同,Html.Partial会在View 中用来显示分部View。

Html.RenderPartial会将分部View的结果直接写入HTTP 响应流中,而 Html.Partial会返回 MvcHtmlString值。

什么是MvcHtmlString,为何 Html.Partial返回的是MvcHtmlString 而不是字符串?

每一个MSDN”MvcHtmlString”表明了一个 HTML编码的字符串,不须要二次编码。代码以下:

 1: @{
 2:  string MyString = "My Simple String";
 3: }
 4: @MyString

以上代码会转换为:

Razor显示了所有的内容,许多人会认为已经看到加粗的字符串,是Razor Html在显示内容以前将内容编码,这就是为何使用纯内容来代替粗体。

当不适用razor编码时,使用 MvcHtmlString,MvcHtmlString是razor的一种表示,即“字符串已经编码完毕,不须要其余编码”。

如:

 1: @{
 2:  string MyString = "My Simple String";
 3: }
 4: @MvcHtmlString.Create(MyString)

输出:

Html.RenderAction 和 Html.Action二者之间有什么不一样?更推荐使用哪一种方法?

Html.RenderAction会将Action 方法的执行结果直接写入HTTP 响应请求流中,而 Html.Action会返回MVCHTMLString。更推荐使用Html.RenderAction,由于它更快。当咱们想在显示前修改action执行的结果时,推荐使用Html.Action。

 

实验23——实现用户角色管理

在实验23中咱们将实现管理员和非管理员登陆的功能。需求很简单:非管理员用户没有建立新Employee的权限。实验23会帮助你们理解MVC提供的Session 和Action过滤器。

所以咱们将实验23分为两部分:

第一部分:非管理员用户登陆时,隐藏 Add New 连接

1. 建立标识用户身份的枚举类型

右击Model 文件夹,选择添加新项目。选择“Code File”选项。

输入“UserStatus”名,点击添加。

“Code File”选项会建立一个“.cs”文件.

建立UserStatus枚举类型,以下:

 1: namespace WebApplication1.Models
 2: {
 3:  public enum UserStatus
 4:  {
 5:  AuthenticatedAdmin,
 6:  AuthentucatedUser,
 7:  NonAuthenticatedUser
 8:  }
 9: }

 2. 修改业务层功能

删除  IsValidUser函数,建立新函数“GetUserValidity“,以下:

 1: public UserStatus GetUserValidity(UserDetails u)
 2: {
 3:  if (u.UserName == "Admin" && u.Password == "Admin")
 4:  {
 5:  return UserStatus.AuthenticatedAdmin;
 6:  }
 7:  else if (u.UserName == "Sukesh" && u.Password == "Sukesh")
 8:  {
 9:  return UserStatus.AuthentucatedUser;
 10:  }
 11:  else
 12:  {
 13:  return UserStatus.NonAuthenticatedUser;
 14:  }
 15: }

3. 修改DoLogin action方法

打开 AuthenticationController, 修改DoLogin action:

 1: [HttpPost]
 2: public ActionResult DoLogin(UserDetails u)
 3: {
 4:  if (ModelState.IsValid)
 5:  {
 6:  EmployeeBusinessLayer bal = new EmployeeBusinessLayer();
 7:  //New Code Start
 8:  UserStatus status = bal.GetUserValidity(u);
 9:  bool IsAdmin = false;
 10:  if (status==UserStatus.AuthenticatedAdmin)
 11:  {
 12:  IsAdmin = true;
 13:  }
 14:  else if (status == UserStatus.AuthentucatedUser)
 15:  {
 16:  IsAdmin = false;
 17:  }
 18:  else
 19:  {
 20:  ModelState.AddModelError("CredentialError", "Invalid Username or Password");
 21:  return View("Login");
 22:  }
 23:  FormsAuthentication.SetAuthCookie(u.UserName, false);
 24:  Session["IsAdmin"] = IsAdmin;
 25:  return RedirectToAction("Index", "Employee");
 26:  //New Code End
 27:  }
 28:  else
 29:  {
 30:  return View("Login");
 31:  }
 32: }

在上述代码中,已经出现Session 变量来识别用户身份。

什么是Session?

Session是Asp.Net的特性之一,能够在MVC中重用,可用于暂存用户相关数据,session变量周期是穿插于整个用户生命周期的。

4. 移除存在的 AddNew 连接

打开“~/Views/Employee”文件夹下 Index.cshtml View,移除”Add New“超连接。

<!-- Remove following line from Index.cshtml --> <a href="/Employee/AddNew">Add New</a>

5. 建立分部View

右击“~/Views/Employee”文件夹,选择添加View,设置View名称”“AddNewLink”“,选中”Create a partial View“复选框。

6. 输入分部View的内容

在新建立的分部视图中输入如下内容:

<a  href="/Employee/AddNew">Add New</a>

7.  新建 Action 方法

打开 EmployeeController,新建Action 方法”GetAddNewLink“,以下:

 1: public ActionResult GetAddNewLink()
 2: {
 3:  if (Convert.ToBoolean(Session["IsAdmin"]))
 4:  {
 5:  return Partial View("AddNewLink");
 6:  }
 7:  else
 8:  {
 9:  return new EmptyResult();
 10:  }
 11: }

8.  显示  AddNew 连接

打开 Index.html,输入如下代码:

 1: <a href="/Authentication/Logout">Logout</a>
 2: </div>
 3: <hr />
 4: @{
 5:  Html.RenderAction("GetAddNewLink");
 6: }
 7: <div>
 8: <table border="1">
 9: <tr>

Html.RenderAction 执行Action 方法,并将结果直接写入响应流中。

9. 运行

测试1

测试2

第二部分: 直接URL 安全

以上实验实现了非管理员用户没法导航到AddNew连接。这样还不够,若是非管理员用户直接输入AddNew URL,则会直接跳转到此页面。

非管理员用户仍是能够直接访问AddNew方法,为了解决这个问题,咱们会引入MVC action 过滤器。Action 过滤器使得在action方法中添加一些预处理和后处理的逻辑判断问题。在整个实验中,会注重ActionFilters预处理的支持和后处理的功能。

1. 安装过滤器

新建文件夹Filters,新建类”AdminFilter“。

2. 建立过滤器

经过继承 ActionFilterAttribute ,将 AdminFilter类升级为”ActionFilter“,以下:

 1: public class AdminFilter:ActionFilterAttribute
 2: {
 3:  
 4: }

注意:使用”ActionFilterAttribute “须要在文件顶部输入”System.Web.Mvc“。

3. 添加安全验证逻辑

在ActionFliter中重写 OnActionExecuting方法:

 1: public override void OnActionExecuting(ActionExecutingContext filterContext)
 2: {
 3:  if (!Convert.ToBoolean(filterContext.HttpContext.Session["IsAdmin"]))
 4:  {
 5:  filterContext.Result = new ContentResult()
 6:  {
 7:  Content="Unauthorized to access specified resource."
 8:  };
 9:  }
 10: }

4. 绑定过滤器

在AddNew和 SaveEmployee方法中绑定过滤器,以下:

 1: [AdminFilter]
 2: public ActionResult AddNew()
 3: {
 4:  return View("CreateEmployee",new Employee());
 5: }
 6: ...
 7: ...
 8: [AdminFilter]
 9: public ActionResult SaveEmployee(Employee e, string BtnSubmit)
 10: {
 11:  switch (BtnSubmit)
 12:  {
 13:  case "Save Employee":
 14:  if (ModelState.IsValid)
 15:  {
 16:  EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
 17: ....
 18: ....

5. 运行

关于实验23

能够经过浏览器直接调用GetAddNewLink方法吗?

 能够直接调用,也可直接中止”GetAddNewLink“的运行。

Html.Action有什么做用?

与Html.RenderAction做用相同,Html.Action会执行action 方法,并在View中显示结果。

语法:

 1: @Html.Action("GetAddNewLink");

Html.RenderAction 和 Html.Action二者之间有什么不一样?更推荐使用哪一种方法?

Html.RenderAction会将Action 方法的执行结果直接写入HTTP 响应请求流中,而 Html.Action会返回MVCHTMLString。更推荐使用Html.RenderAction,由于它更快。当咱们想在显示前修改action执行的结果时,推荐使用Html.Action。

什么是 ActionFilter ?

与AuthorizationFilter相似,ActionFilter是ASP.NET MVC过滤器中的一种,容许在action 方法中添加预处理和后处理逻辑。

实验24——实现项目外观的一致性

在ASP.NET可以保证外观一致性的是母版页的使用。MVC却不一样于ASP.NET,在RAZOR中,母版页称为布局页面。

在开始实验以前,首先来了解布局页面

1. 带有欢迎消息的页眉

2. 带有数据的页脚

最大的问题是什么?

带有数据的页脚和页眉做为ViewModel的一部分传从Controller传给View。

如今最大的问题是在页眉和页脚移动到布局页面后,如何将数据从View传给Layout页面。

解决方案——继承

可以使用继承原则,经过实验来深刻理解。

1. 建立ViewModel基类

在ViewModel 文件夹下新建ViewModel 类 ”BaseViewModel“,以下:

 1: public class BaseViewModel
 2: {
 3:  public string UserName { get; set; }
 4:  public FooterViewModel FooterData { get; set; }//New Property
 5: }
 

BaseViewModel可封装布局页所须要的全部值。

2. 准备 EmployeeListViewModel

删除EmployeeListViewModel类的 UserName和 FooterData属性,并继承 BaseViewModel:

 1: public class EmployeeListViewModel:BaseViewModel
 2: {
 3:  public List<EmployeeViewModel> Employees { get; set; }
 4: }

3.  建立布局页面

右击shared文件夹,选择添加>>MVC5 Layout Page。输入名称”MyLayout“,点击确认

 1: <!DOCTYPE html>
 2:  
 3: <html>
 4: <head>
 5:  <meta name="viewport" content="width=device-width" />
 6:  <title>@ViewBag.Title</title>
 7: </head>
 8: <body>
 9:  <div>
 10:  @RenderBody()
 11:  </div>
 12: </body>
 13: </html>

4. 将布局转换为强类型布局

 1: @using WebApplication1.ViewModels
 2: @model BaseViewModel

5. 设计布局页面

在布局页面添加页眉,页脚和内容,内容,三部分,以下:

 1: <html>
 2: <head>
 3:  <meta name="viewport" content="width=device-width" />
 4:  <title>@RenderSection("TitleSection")</title>
 5:  @RenderSection("HeaderSection",false)
 6: </head>
 7: <body>
 8:  <div style="text-align:right">
 9:  Hello, @Model.UserName
 10:  <a href="/Authentication/Logout">Logout</a>
 11:  </div>
 12:  <hr />
 13:  <div>
 14:  @RenderSection("ContentBody")
 15:  </div>
 16:  @Html.Partial("Footer",Model.FooterData)
 17: </body>
 18: </html>

如上所示,布局页面包含三部分,TitleSection, HeaderSection 和 ContentBody,内容页面将使用这些部分来定义合适的内容。

6. 在 Index View中绑定布局页面

打开Index.cshtml,在文件顶部会发现如下代码:

 1: @{
 2:  Layout = null;
 3: }

修改:

 1: @{
 2:  Layout = "~/Views/Shared/MyLayout.cshtml";
 3: }

7.设计Index View

  • 从Index View中去除页眉和页脚
  • 在Body标签中复制保留的内容,并存放在某个地方。
  • 复制Title标签中的内容
  • 移除View中全部的HTML 内容,确保只移动了HTML,@model 且没有移动layout语句
  • 在复制的内容中定义TitleSection和 Contentbody

完整的View代码以下:

 1: @using WebApplication1.ViewModels
 2: @model EmployeeListViewModel
 3: @{
 4:  Layout = "~/Views/Shared/MyLayout.cshtml";
 5: }
 6:  
 7: @section TitleSection{
 8:  MyView
 9: }
 10: @section ContentBody{
 11:  <div>
 12:  @{
 13:  Html.RenderAction("GetAddNewLink");
 14:  }
 15:  <table border="1">
 16:  <tr>
 17:  <th>Employee Name</th>
 18:  <th>Salary</th>
 19:  </tr>
 20:  @foreach (EmployeeViewModel item in Model.Employees)
 21:  {
 22:  <tr>
 23:  <td>@item.EmployeeName</td>
 24:  <td style="background-color:@item.SalaryColor">@item.Salary</td>
 25:  </tr>
 26:  }
 27:  </table>
 28:  </div>
 29: }

 

8. 运行

9. 在 CreateEmployee 中绑定布局页面

打开 Index.cshtml,修改顶部代码:

 1: @{
 2:  Layout = "~/Views/Shared/MyLayout.cshtml";
 3: }

10. 设计 CreateEmployee  View

与第7步中的程序相似,定义 CreateEmployee View中的Section ,在本次定义中只添加一项,以下:

 1: @using WebApplication1.Models
 2: @model Employee
 3: @{
 4:  Layout = "~/Views/Shared/MyLayout.cshtml";
 5: }
 6:  
 7: @section TitleSection{
 8:  CreateEmployee
 9: }
 10:  
 11: @section HeaderSection{
 12: <script src="~/Scripts/Validations.js"></script>
 13: <script>
 14:  function ResetForm() {
 15:  document.getElementById('TxtFName').value = "";
 16:  document.getElementById('TxtLName').value = "";
 17:  document.getElementById('TxtSalary').value = "";
 18:  }
 19: </script>
 20: }
 21: @section ContentBody{
 22:  <div>
 23:  <form action="/Employee/SaveEmployee" method="post" id="EmployeeForm">
 24:  <table>
 25:  <tr>
 26:  <td>
 27:  First Name:
 28:  </td>
 29:  <td>
 30:  <input type="text" id="TxtFName" name="FirstName" value="@Model.FirstName" />
 31:  </td>
 32:  </tr>
 33:  <tr>
 34:  <td colspan="2" align="right">
 35:  @Html.ValidationMessage("FirstName")
 36:  </td>
 37:  </tr>
 38:  <tr>
 39:  <td>
 40:  Last Name:
 41:  </td>
 42:  <td>
 43:  <input type="text" id="TxtLName" name="LastName" value="@Model.LastName" />
 44:  </td>
 45:  </tr>
 46:  <tr>
 47:  <td colspan="2" align="right">
 48:  @Html.ValidationMessage("LastName")
 49:  </td>
 50:  </tr>
 51:  
 52:  <tr>
 53:  <td>
 54:  Salary:
 55:  </td>
 56:  <td>
 57:  <input type="text" id="TxtSalary" name="Salary" value="@Model.Salary" />
 58:  </td>
 59:  </tr>
 60:  <tr>
 61:  <td colspan="2" align="right">
 62:  @Html.ValidationMessage("Salary")
 63:  </td>
 64:  </tr>
 65:  
 66:  <tr>
 67:  <td colspan="2">
 68:  
 69:  <input type="submit" name="BtnSubmit" value="Save Employee" onclick="return IsValid();" />
 70:  <input type="submit" name="BtnSubmit" value="Cancel" />
 71:  <input type="button" name="BtnReset" value="Reset" onclick="ResetForm();" />
 72:  </td>
 73:  </tr>
 74:  </table>
 75:  </div>
 76: }

11. 运行

Index View是  EmployeeListViewModel类型的强View类型,是 BaseViewModel的子类,这就是为何Index View可一直发挥做用。CreateEmployee View 是CreateEmployeeViewModel的强类型,并非BaseViewModel的子类,所以会出现以上错误。

12. 准备 CreateEmployeeViewModel

使CreateEmployeeViewModel 继承 BaseViewModel,以下:

 1: public class CreateEmployeeViewModel:BaseViewModel
 2: {
 3: ...

13. 运行

报错,该错误好像与步骤11中的错误彻底不一样,出现这些错误的根本缘由是未初始化AddNew action方法中的Header和Footer数据。

14. 初始化Header和Footer 数据

修改AddNew方法:

 1: public ActionResult AddNew()
 2: {
 3:  CreateEmployeeViewModel employeeListViewModel = new CreateEmployeeViewModel();
 4:  employeeListViewModel.FooterData = new FooterViewModel();
 5:  employeeListViewModel.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value
 6:  employeeListViewModel.FooterData.Year = DateTime.Now.Year.ToString();
 7:  employeeListViewModel.UserName = User.Identity.Name; //New Line
 8:  return View("CreateEmployee", employeeListViewModel);
 9: }

15. 初始化 SaveEmployee中的Header和 FooterData

 1: public ActionResult SaveEmployee(Employee e, string BtnSubmit)
 2: {
 3:  switch (BtnSubmit)
 4:  {
 5:  case "Save Employee":
 6:  if (ModelState.IsValid)
 7:  {
 8:  ...
 9:  }
 10:  else
 11:  {
 12:  CreateEmployeeViewModel vm = new CreateEmployeeViewModel();
 13:  ...
 14:  vm.FooterData = new FooterViewModel();
 15:  vm.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value
 16:  vm.FooterData.Year = DateTime.Now.Year.ToString();
 17:  vm.UserName = User.Identity.Name; //New Line
 18:  return View("CreateEmployee", vm); // Day 4 Change - Passing e here
 19:  }
 20:  case "Cancel":
 21:  return RedirectToAction("Index");
 22:  }
 23:  return new EmptyResult();
 24: }

16. 运行

关于实验24

RenderBody 有什么做用?

以前建立了Layout 页面,包含一个Razor语句如:

 1: @Html.RenderBody()

首先咱们先来了RenderBody是用来作什么的?

在内容页面,一般会定义Section,声明Layout页面。可是奇怪的是,Razor容许定义在Section外部定义一些内容。全部的非section内容会使用RenderBody函数来渲染,下图可以更好的理解:

布局是否可嵌套?

能够嵌套,建立Layout页面,可以使用其余存在的Layout页面,语法相同。

是否须要为每一个View定义Layout页面?

会在View文件夹下发现特殊的文件“__ViewStart.cshtml”,在其内部的设置会应用全部的View。

例如:在__ViewStart.cshtml中输入如下代码,并给全部View 设置 Layout页面。

 1: @{
 2:  Layout = "~/Views/Shared/_Layout.cshtml";
 3: }

是否在每一个Action 方法中须要加入Header和Footer数据代码?

不须要,可在Action 过滤器的帮助下删除重复的代码。

是否强制定义了全部子View中的Section?

是的,若是Section定义为须要的section,默认的值会设置为true。以下

 1: @RenderSection("HeaderSection",false) // Not required
 2: @RenderSection("HeaderSection",true) // required
 3: @RenderSection("HeaderSection") // required

 

实验25——使用Action Fliter让Header和Footer数据更有效

在实验23中,咱们已经知道了使用 ActionFilter的一个优势,如今来看看使用 ActionFilter的其余好处

1. 删除Action 方法中的冗余代码

删除Index,AddNew, SaveEmployee方法中的Header和Footer数据代码。

Header代码如:

 1: bvm.UserName = HttpContext.Current.User.Identity.Name;

Footer代码如:

 1: bvm.FooterData = new FooterViewModel();
 2: bvm.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value
 3: bvm.FooterData.Year = DateTime.Now.Year.ToString();

2.建立HeaderFooter 过滤器

在Filter文件夹下新建类”HeaderFooterFilter“,并经过继承ActionFilterAttribute类升级为Action Filter

3. 升级ViewModel

重写 HeaderFooterFilter类的 OnActionExecuted方法,在该方法中获取当前View Model ,并绑定Header和Footer数据。

 1: public class HeaderFooterFilter : ActionFilterAttribute
 2: {
 3:  public override void OnActionExecuted(ActionExecutedContext filterContext)
 4:  {
 5:  ViewResult v = filterContext.Result as ViewResult;
 6:  if(v!=null) // v will null when v is not a ViewResult
 7:  {
 8:  BaseViewModel bvm = v.Model as BaseViewModel;
 9:  if(bvm!=null)//bvm will be null when we want a view without Header and footer
 10:  {
 11:  bvm.UserName = HttpContext.Current.User.Identity.Name;
 12:  bvm.FooterData = new FooterViewModel();
 13:  bvm.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value
 14:  bvm.FooterData.Year = DateTime.Now.Year.ToString();
 15:  }
 16:  }
 17:  }
 18: }

4. 绑定过滤器

在Index中,AddNew,SaveEmployee的action 方法中绑定 HeaderFooterFilter

 1: [HeaderFooterFilter]
 2: public ActionResult Index()
 3: {
 4:  EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();
 5: ...
 6: }
 7: ...
 8: [AdminFilter]
 9: [HeaderFooterFilter]
 10: public ActionResult AddNew()
 11: {
 12:  CreateEmployeeViewModel employeeListViewModel = new CreateEmployeeViewModel();
 13:  //employeeListViewModel.FooterData = new FooterViewModel();
 14:  //employeeListViewModel.FooterData.CompanyName = "StepByStepSchools";
 15: ...
 16: }
 17: ...
 18: [AdminFilter]
 19: [HeaderFooterFilter]
 20: public ActionResult SaveEmployee(Employee e, string BtnSubmit)
 21: {
 22:  switch (BtnSubmit)
 23:  {
 24:  ...

5. 运行

总结

本文主要介绍了ASP.NET MVC中页眉页脚的添加和Layout页面的使用,并实现了用户角色分配及Action Filter的使用,下一节中咱们将是最难和最有趣的一篇,请持续关注吧!

在学习了本节Layout页面及用户角色管理以后,你是否也跃跃欲试想要进行MVC开发?不妨试试 ComponentOne Studio ASP.NET MVC 这款轻量级控件,它与Visual Studio无缝集成,彻底与MVC6和ASP.NET 5.0兼容,将大幅提升工做效率。

原文连接:http://www.codeproject.com/Articles/1000435/Learn-MVC-Project-in-days-Day

相关文章
相关标签/搜索