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


    day5

    系列文章

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

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

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

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

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

     


    目录

    实验22——加入页脚

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

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

    实验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中我们将实现管理员和非管理员登录的功能。

    需求非常easy:非管理员用户没有创建新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的使用,下一节中我们将是最难和最有趣的一篇。请持续关注吧。

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

  • 相关阅读:
    poj2253 青蛙
    这代码真是好,真是文艺,转来的
    java.text.MessageFormat
    java多线程的两种实现方式
    javascript with
    面向接口编程
    java 多线程 读写锁
    java 多线程 资源共享
    UML:继承、实现、依赖、关联、聚合、组合
    javascript 语言精粹 学习笔记
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5236095.html
Copyright © 2020-2023  润新知