学习MVC项目在7天-第5天

介绍 欢迎来到“7天学习MVC项目”系列的第5天。希望你们在第一天到第四天读得愉快。前几天必须在第5天之前完成。 完整的系列 第1天第2天第3天第4天第5天第6天7天奖金第1天奖金第2天 我们很高兴地宣布,这篇文章现在可以从www.amazon.com和www.flipkart.com获得同样的纸质书 议程 实验室22 -在实验室22实验室23日添加页脚谈实现基于角色的安全第1部分第2部分讨论在实验室23日实验室24 -分配实验室处理CSRF攻击实验室25 -实现一致的外观项目讨论在实验室25实验室26日——头和FooterData代码更高效过滤器的结论与行动 实验室22 -添加页脚 在这个实验室中,我们将在我们的员工屏幕上添加页脚。 本实验室的主要目的是了解部分观点。 什么是“片面观点”? 从逻辑上讲,部分视图是一个永远不会直接显示的可重用视图。它将包含在其他视图中,并显示为该视图的一部分。它类似于Asp中的用户控件。Net web表单,但是没有代码。 步骤1 -为部分视图创建视图模型 右键单击ViewModel文件夹并创建一个名为FooterViewModel的类,如下所示。 隐藏,复制Code

public class FooterViewModel
{
   public string CompanyName { get; set; }
   public string Year { get; set; }
}

步骤2 -创建部分视图 右击“~/Views/Shared”文件夹。,选择Add>的在视图。 将视图名称作为页脚,勾选“创建为部分视图”复选框,然后点击“添加”。 注意:我们在第一天已经讨论了共享文件夹。共享文件夹包含的视图不是特定于特定控制器的。共享文件夹中的视图对所有控制器都可用。 步骤3 -在部分视图中显示数据 打开的页脚。cshtml,并在其中放入下面的HTML。 隐藏,复制Code@using WebApplication1.ViewModels @ model FooterViewModel div style="text-align:right;background-color: silver;color: darkcyan;border: 1px solid gray;margin-top:2px; @ model。公司名称©@Model.Year & lt; / div> 步骤3 -在主视图模型中包括页脚数据 打开EmployeeListViewModel类并添加一个新的属性来保存页脚数据,如下所示。 隐藏,复制Codepublic类EmployeeListViewModel { 公共List< EmployeeViewModel>员工{得到;设置;} 获取;设置;} 获取;设置;} / /新属性 } 在我们的例子中,页脚(部分视图)将显示为索引视图的一部分。 我们将从索引视图向页脚传递必要的数据。 索引视图是EmployeeListViewModel类型的强类型视图,因此页脚视图所需的所有数据都应该封装在EmployeeListViewModel中。 步骤4 -设置页脚数据 打开EmployeeController并在索引操作方法中将值设置为FooterData属性,如下所示。 隐藏,复制Code

public ActionResult Index()
{
   ...
   ...
    employeeListViewModel.FooterData = new FooterViewModel();
    employeeListViewModel.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value
    employeeListViewModel.FooterData.Year = DateTime.Now.Year.ToString();
    return View("Index", employeeListViewModel);
} 

第五步-显示页脚 开放指数。cshtml并在表标记后显示页脚部分视图,如下所示。 隐藏,复制代码& lt; / table> @ { 超文本标记语言RenderPartial方法(“页脚”,Model.FooterData); } & lt; / div> & lt; / body> & lt; / html> 步骤6 -执行和测试 按F5。导航到索引视图。(我相信,你现在知道该怎么做了。) 在22实验室演讲 什么Html。部分做了什么? 就像Html。RenderPartial方法,Html。Partial将用于在视图中显示部分视图。 这是它的语法 隐藏,复制Code

@Html.Partial("Footer", Model.FooterData);

语法比以前的语法简单得多。 两者之间有什么区别? 超文本标记语言RenderPartial将部分视图的结果直接写入HTTP响应流,而Html。Partial将返回结果为MvcHtmlString。 什么是MvcHtmlString和为什么Html。部分返回MvcHtmlString而不是字符串? 首先让我们了解什么是MvcHtmlString? 根据MSDN“MvcHtmlString表示一个html编码的字符串,不应该再次编码”。 让我们简化这个定义。 请看下面的代码。 隐藏,复制Code

@{
   string MyString = "My Simple String";
}
@MyString

它将生成以下输出 如您所见,razor按原样显示了整个内容。许多人可能会想到看到粗体字符串,但Razor Html在显示之前对内容进行编码,这就是为什么我们得到的是纯内容而不是粗体字符串。 当我们不希望razor进行编码时,我们使用MvcHtmlString。MvcHtmlString是对razor的一个指示:“字符串已经编码了,不需要再编码了”。 例如,请看下面的代码。 隐藏,复制Code

@{
   string MyString = "My Simple String";
}
@MvcHtmlString.Create(MyString)

它将生成以下输出 为什么Html。部分返回MvcHtmlString而不是字符串? 我们已经了解了一个事实:“razor总是会编码字符串,但它从不编码MvcHtmlString”。如果部分视图内容被认为是纯字符串,那么它是没有意义的。我们希望它被视为HTML内容,因此我们必须停止razor的编码,因此部分方法被设计为返回MvcHtmlString。 是什么推荐的Html。RenderPartial方法或Html.Partial吗? 超文本标记语言建议使用渲染部分,因为它更快。 当Html。偏爱部分的? 当我们想要在显示前改变部分视图返回的结果时,建议这样做。 开放指数。cshtml并打开页脚代码到下面的代码和测试。 隐藏,复制Code

@{        
    MvcHtmlString result = Html.Partial ("Footer", Model.FooterData);
    string finalResult = result.ToHtmlString().Replace("2015", "20000");            
}
@MvcHtmlString.Create(finalResult)

现在页脚看起来像下面。 为什么将部分视图放在共享文件夹中? 部分视图意味着可重用性,因此它们的最佳位置是共享文件夹。 我们不能把部分视图放在一个特定的控制器文件夹中吗,比如雇员或身份验证? 我们可以这样做,但在这种情况下,它不会只对特定的控制器可用。 例如:当我们在雇员文件夹中保留部分视图时,它将不能用于AuthenticationController或与AuthenticationController相关的视图。 为什么部分视图的定义包含“逻辑”这个词? 在定义中我们已经说过,部分视图是一个可重用的视图,但它不会被自己执行。它必须放在其他视图中,然后作为视图的一部分显示。 我们所说的可重用性是完全正确的,但我们所说的执行只是在逻辑上正确的。从技术上讲,这不是一个正确的说法。我们可以创建一个action方法,它将返回一个ViewResult,如下所示。 隐藏,复制Code

public ActionResult MyFooter()
{
    FooterViewModel FooterData = new FooterViewModel();
    FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value
    FooterData.Year = DateTime.Now.Year.ToString();
    return View("Footer", FooterData);
}

它将显示如下输出 虽然逻辑上说不通,但技术上是可能的。页脚。cshtml不包含适当结构的HTML。它意味着被显示为其他视图的一部分。因此我说,“从逻辑上讲,这没有道理”。 为什么创建部分视图而不是直接在视图中放置页脚内容? 两个优点 可重用性——我们可以在其他视图中重用相同的部分视图。代码维护——将其放在单独的文件中,便于管理和操作。 为什么头不是作为部分视图创建的? 作为一个最佳实践,我们必须为头部创建部分视图,但为了使最初的实验室更简单,我们将其保持内联。 实验室23 -实现基于角色的安全性 在这个实验中,我们将实现管理员和非管理员登录特性。 需求非常简单。 “非管理员用户不能创建新员工”。 通过这个实验,我们将了解MVC中的另外两个主题。 会话操作过滤器 让我们从我们的实验室开始 为了简单起见,让我们把它分成两部分。 第1部分-隐藏AddNew链接从非管理员用户 步骤1 -创建枚举来标识用户状态 右键点击模型文件夹,选择“添加新项目”。 从对话框中选择“代码文件”选项。 把名字设为“UserStatus”,然后点击添加。 “代码文件”选项将创建一个空白“。cs”文件。 在其中创建一个名为UserStatus的枚举,如下所示。 隐藏,复制Codenamespace WebApplication1.Models { 公共enum UserStatus { AuthenticatedAdmin, AuthentucatedUser, NonAuthenticatedUser } } 步骤2 -更改业务层功能 删除IsValidUser函数并创建一个名为GetUserValidity的新函数,如下所示。 隐藏,复制Codepublic UserStatus GetUserValidity(UserDetails u) { 如果(u。用户名==“Admin”&u。密码= =“Admin”) { 返回UserStatus.AuthenticatedAdmin; } else if (u。用户名==“Sukesh”&u。密码= =“Sukesh”) { 返回UserStatus.AuthentucatedUser; } 其他的 { 返回UserStatus.NonAuthenticatedUser; } } 步骤3 -改变行动方法 打开AuthenticationController并更改DoLogin操作方法,如下所示。 隐藏,收缩,复制代码(HttpPost) 公众行动结果DoLogin(用户详情u) { 如果(ModelState.IsValid) { bal = new EmployeeBusinessLayer(); / /新代码开始 UserStatus status = bal.GetUserValidity(u); bool IsAdmin = false; 如果状态= = UserStatus.AuthenticatedAdmin) { IsAdmin = true; } else if (status == UserStatus.AuthentucatedUser) { IsAdmin = false; } 其他的 { 模型状态。AddModelError(“CredentialError”,“无效的用户名或密码”); 返回视图(“登录”); } FormsAuthentication.SetAuthCookie (u。用户名错误); 会话(“IsAdmin”)= IsAdmin; 返回RedirectToAction(“指数”,“员工”); / /新代码 } 其他的 { 返回视图(“登录”); } } 如您所见,我们使用session变量来标识用户是admin用户还是非admin用户。 不知道会议? 会话是Asp的特性。在asp.net中重用。净MVC。 我们使用会话变量来保存用户相关的数据。会话变量的生命周期就是用户的生命周期。它将一直可用到当前会议结束。 步骤4 -删除现有的AddNew链接 开放指数。cshtml视图从“~/Views/Employee”文件夹和删除“添加新”超链接完全。 隐藏,警察y Code< !——从索引中删除以下行。cshtml——比; & lt; a href = " /员工/ AddNew”在添加New< / a> 步骤5 -克里特岛部分视图 右击“~/Views/Employee”文件夹,选择Add>>View。将视图名称设置为“AddNewLink”,并确保选中“创建部分视图”复选框。 步骤6 -将内容放在部分视图中 只需在新创建的部分视图中放入以下内容。 隐藏,复制Code

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

步骤7 -创建行动方法 打开EmployeeController并创建一个名为“GetAddNewLink”的新操作方法,如下所示。 隐藏,复制Codepublic ActionResult GetAddNewLink() { 如果(Convert.ToBoolean(会话(“IsAdmin”))) { 返回局部视图(“AddNewLink”); } 其他的 { 返回新EmptyResult (); } } 步骤8 -显示添加新链接 打开Index.html并简单地将以下代码放入其中。 隐藏,复制Code

<ahref="/Authentication/Logout">Logout</a>
</div>
<hr/>
@{
  Html.RenderAction("GetAddNewLink");
}
<div>
<tableborder="1">
<tr>

超文本标记语言RenderAction执行动作方法并直接将结果写入响应流。 步骤9 -执行和测试 按F5并执行应用程序。 测试1 测试2 第2部分-直接URL安全 有了以上的逻辑,有一件事是可以保证的。现在,非管理员用户将不能通过超链接导航到AddNew action。 是足够的吗? 不,这还不够。如果一个非管理员用户直接尝试通过URL导航到AddNew操作。 正如您在上面的示例中看到的,非管理员用户能够访问AddNew操作。 为了解决这个问题,我们将使用MVC ActionFilters。动作过滤器让我们向动作方法中添加一些预处理和后处理逻辑。在这个实验室里,我们会研究ActionFilters的预处理支持,在接下来的实验室里,我们也会研究后处理功能。 步骤1 -设置过滤器。 在项目中创建一个名为Filters的新文件夹,并创建一个名为AdminFilter的新类。 步骤2 -创建过滤器 通过从ActionFilterAttribute类继承简单的AdminFilter类,将其升级为ActionFilter,如下所示。 隐藏,复制Codepublic类AdminFilter:ActionFilterAttribute { } 注意:要使用ActionFilterAttribute,你必须使用System.Web。Mvc在顶部。 步骤3 -添加安全验证逻辑 在ActionFilter中覆盖onactionexecution如下。 隐藏,复制代码公共覆盖void onactionexecute (ActionExecutingContext filterContext) { 如果(! Convert.ToBoolean (filterContext.HttpContext.Session [" IsAdmin "])) { filterContext。Result = new ContentResult() { Content="未授权访问指定资源。" }; } } 步骤4 -安装过滤器 将筛选器同时附加到AddNew和SaveEmployee操作方法,如下所示。 隐藏,复制代码(AdminFilter) 公共ActionResult AddNew () { ,,返回视图(“CreateEmployee”,新员工()); } … … (AdminFilter) SaveEmployee(雇员e,字符串BtnSubmit) { ,,开关(BtnSubmit) ,,{ ,,,,例“拯救员工”: ,,,,,,如果(ModelState.IsValid) ,,,,,,{ ,,,,,,,,EmployeeBusinessLayer empBal = new EmployeeBusinessLayer(); … … 步骤5 -执行和测试 按F5并执行应用程序。使用非管理凭证登录,并尝试通过放置AddNew动作的URL导航到AddNew动作方法。 如您所见,现在您的操作方法是完全安全的。 注意:无论我们在这个实验室中使用什么策略和逻辑来实现基于角色的安全性,都可能不是最好的解决方案。您可能有更好的逻辑来实现这种行为。这只是实现目标的方法之一。 在23实验室演讲 我们可以通过浏览器地址栏直接调用GetAddNewLink吗? 是的,我们已经在“22号实验室谈话”部分讨论过这种行为。 有没有可能停止直接执行GetAddNewLink? 用ChildActionOnly属性修饰GetAddNewLink。 隐藏,复制代码(ChildActionOnly) 公共ActionResult GetAddNewLink () { ,,如果(Convert.ToBoolean(会话(“IsAdmin”))) ,,{ 什么Html。行动呢? 就像Html。RenderAction, Html。Action将执行Action方法并在视图中显示结果。 这是它的语法 隐藏,复制Code@Html.Action(“GetAddNewLink”); 语法比以前的语法简单得多。 两者之间有什么区别? 超文本标记语言RenderAction将把动作方法执行的结果直接写入HTTP响应流,而不是Html。操作将以MvcHtmlString的形式返回结果。 什么是推荐的Html。RenderAction还是Html.Action ? 超文本标记语言建议使用RenderAction,因为它更快。 当Html。行动将是首选? 当我们想在显示之前改变动作方法执行所返回的结果时,建议使用此方法。 ActionFilter是什么? 就像AuthorizationFilter, ActionFilter是Asp中的一种过滤器。净MVC。它允许我们添加预处理和后处理逻辑to动作方法执行。 注意:在每次实验之后,我们都在尽我们最大的努力来涵盖开发人员可能遇到的每一个问题。如果您认为还需要添加更多问题,请将您的问题发送到SukeshMarla@Gmail.com 实验室24 -任务实验室-处理CSRF攻击 从安全的角度来看,我们还必须处理CSRF对项目的攻击。这个我将留给你们。 我建议您阅读本文并实现SaveEmployee操作方法。 http://www.codeproject.com/Articles/994759/What-is-CSRF-attack-and-how-can-we-prevent-the-sam 实验25 -在整个项目中实现一致的外观 在ASP。NET世界一致的布局意味着母版。 ASP。NET MVC和它没有什么不同。在Razor中,母版页称为布局页。 在我们开始我们的实验室之前,首先让我们讨论一下在布局页面中需要放置的所有东西 页眉与欢迎消息页脚与页脚数据 最大的问题? 页脚和页眉的数据作为ViewModel的一部分从控制器传递给视图。 现在最大的问题是,在页眉和页脚被移动到布局页面后,数据将如何从视图传递到布局页面。 解决方案——继承 在这里,我们可以简单地遵循面向对象继承原则。让我们用实验室来理解它。 步骤1 -创建基类ViewModel 在ViewModel文件夹中创建一个名为BaseViewModel类的新视图模型,如下所示。 隐藏,复制Codepublic类BaseViewModel { ,,获取;设置;} ,,获取;设置;} / /新属性 }, 正如你所看到的,BaseViewModel封装了布局页面所需的一切 步骤2 -准备EmployeeListViewModel 从EmployeeListViewModel类中删除用户名和FooterData属性,并从BaseViewModel继承它。 隐藏,复制Codepublic类EmployeeListViewModel:BaseViewModel { 公共List< EmployeeViewModel>员工{得到;设置;} } 步骤3 -创建布局页面 右击共享文件夹。选择MVC 5布局页面。将名称设置为MyLayout并单击ok。 它将创建一个如下所示的结构。 隐藏,Code<复印件;!DOCTYPE html> & lt; html> & lt; head> meta name="viewport" content="width=device-width" /> & lt; title> @ViewBag.Title< / title> & lt; / head> & lt; body> & lt; div> @RenderBody () & lt; / div> & lt; / body> & lt; / html> 步骤4 -将布局转换为强类型布局 只需将以下语句放在布局页面的顶部,并使其成为强类型布局。 隐藏,复制Code@using WebApplication1.ViewModels @ model BaseViewModel 步骤5 -设计布局页面 在布局页面添加页眉,页脚和三个部分的内容如下。 隐藏,复制Code< html> & lt; head> ,,meta name="viewport" content="width=device-width" /> ,,& lt; title> @RenderSection(“TitleSection”)& lt; / title> ,,@RenderSection(“HeaderSection”,假) & lt; / head> & lt; body> ,,& lt; div风格= " text-align:对"比; ,,,,你好,@Model.UserName ,,,,& lt; a href = " /认证/注销”祝辞Logout< / a> ,,& lt; / div> ,,& lt;人力资源/比; ,,& lt; div> ,,@RenderSection(“ContentBody”) ,,& lt; / div> ,,@Html.Partial(“页脚”,Model.FooterData) & lt; / body> & lt; / html> 如您所见,我们在布局页面中创建了三个部分。标题部分,标题部分和内容体。内容页将使用这些部分来定义适当的内容。 注意:在定义HeaderSection时,传递第二个参数。这个参数决定它是可选的部分还是必须的部分。False表示它是可选的部分。 步骤6 -附加布局页到索引视图 开放指数。cshtml,在顶部您将发现以下代码。 隐藏,复制Code@ { ,,布局=零; } 将其更改为以下代码。 隐藏,复制Code@ { ,,布局= " ~ /视图/共享/ MyLayout.cshtml”; } 步骤7 -设计索引视图 从索引视图中取出页眉和页脚。复制正文标签中的剩余内容并将其保存在某个地方。从视图中删除所有的HTML内容。确保你只是删除了HTML, @model和布局语句不应该被触动。使用之前复制的内容定义标题和Contentbody。 完整的视图如下所示。 隐藏,收缩,复制Code@using WebApplication1.ViewModels @ model EmployeeListViewModel @ { 布局= " ~ /视图/共享/ MyLayout.cshtml”; } @section TitleSection { MyView } @section ContentBody { & lt; div> @ { Html.RenderAction(“GetAddNewLink”); } & lt;表边界=“1”在 & lt; tr> & lt; th>员工Name< / th> & lt; th>萨拉ry< / th> & lt; / tr> @foreach (employee . employees中的EmployeeViewModel项) { & lt; tr> & lt; td> @item.EmployeeName< / td> & lt; td风格= " background: @item.SalaryColor "祝辞@item.Salary< / td> & lt; / tr> } & lt; / table> & lt; / div> } 如您所见,视图中的所有内容都是在某个部分中定义的。 步骤8 -执行和测试 按F5并执行应用程序。导航到索引操作。 步骤9 -附加布局页面到CreateEmployee视图 开放指数。cshtml,在顶部您将发现以下代码。 隐藏,复制Code

@{
    Layout = null;
}

将其更改为以下代码。 隐藏,复制Code

@{
    Layout = "~/Views/Shared/MyLayout.cshtml";
}

步骤10 -设计CreateEmployee视图 按照相同的步骤7在CreateEmployee视图中定义节。这一次将增加一项功能。我们还将定义HeaderSection。 完整的HTML如下所示。 隐藏,收缩,复制Code

@using WebApplication1.Models
@model Employee
@{
    Layout = "~/Views/Shared/MyLayout.cshtml";
}

@section TitleSection{
    CreateEmployee
}

@section HeaderSection{
<scriptsrc="~/Scripts/Validations.js"></script>
<script>
    function ResetForm() {
        document.getElementById('TxtFName').value = "";
        document.getElementById('TxtLName').value = "";
        document.getElementById('TxtSalary').value = "";
    }
</script>
}
@section ContentBody{ 
    <div>
        <formaction="/Employee/SaveEmployee"method="post"id="EmployeeForm">
            <table>
            <tr>
                <td>
                    First Name:
                </td>
                <td>
                    <inputtype="text"id="TxtFName"name="FirstName"value="@Model.FirstName"/>
                </td>
            </tr>
            <tr>
                <tdcolspan="2"align="right">
                    @Html.ValidationMessage("FirstName")
                </td>
            </tr>
            <tr>
                <td>
                    Last Name:
                </td>
                <td>
                    <inputtype="text"id="TxtLName"name="LastName"value="@Model.LastName"/>
                </td>
            </tr>
            <tr>
                <tdcolspan="2"align="right">
                    @Html.ValidationMessage("LastName")
                </td>
            </tr>

            <tr>
                <td>
                    Salary:
                </td>
                <td>
                    <inputtype="text"id="TxtSalary"name="Salary"value="@Model.Salary"/>
                </td>
            </tr>
            <tr>
                <tdcolspan="2"align="right">
                    @Html.ValidationMessage("Salary")
                </td>
            </tr>

            <tr>
                <tdcolspan="2">

                    <inputtype="submit"name="BtnSubmit"value="Save Employee"onclick="return IsValid();"/>
                    <inputtype="submit"name="BtnSubmit"value="Cancel"/>
                    <inputtype="button"name="BtnReset"value="Reset"onclick="ResetForm();"/>
                </td>
            </tr>
            </table>
    </div>
}

步骤11 -执行和测试 按F5并执行应用程序,然后尝试通过超链接导航到AddNew操作。 索引视图是EmployeeListViewModel类型的强类型视图它是BaseViewModel的子视图这就是它能工作的原因CreateEmployee视图是CreateEmployeeViewModel类型的强类型视图,它不是BaseViewModel的子视图,因此发生了这样的错误。 步骤12 -准备CreateEmployeeViewModel 从BaseViewModel继承CreateEmployeeViewModel,如下所示 隐藏,复制Code

public class CreateEmployeeViewModel:BaseViewModel
{
...

步骤13 -执行和测试 再做一次测试。 这个错误看起来和实际的J很不一样 出现这种错误的真正原因是,我们没有初始化AddNew动作中的Header和FooterData。 第14步-初始化页眉和页脚数据 将AddNew操作方法代码更改为如下。 隐藏,复制Code

public ActionResult AddNew()
{
    CreateEmployeeViewModel employeeListViewModel = new CreateEmployeeViewModel();
    employeeListViewModel.FooterData = new FooterViewModel();
    employeeListViewModel.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value
    employeeListViewModel.FooterData.Year = DateTime.Now.Year.ToString();
    employeeListViewModel.UserName = User.Identity.Name; //New Line
    return View("CreateEmployee", employeeListViewModel);
}

步骤15 -初始化SaveEmployee中的头和脚数据 在SaveEmployee操作方法中执行相同的操作。 隐藏,复制Code

public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
    switch (BtnSubmit)
    {
        case "Save Employee":
            if (ModelState.IsValid)
            {
                ...
            }
            else
            {
                CreateEmployeeViewModel vm = new CreateEmployeeViewModel();
                ...
                vm.FooterData = new FooterViewModel();
                vm.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value
                vm.FooterData.Year = DateTime.Now.Year.ToString();
                vm.UserName = User.Identity.Name; //New Line
                return View("CreateEmployee", vm); // Day 4 Change - Passing e here
            }
        case "Cancel":
            return RedirectToAction("Index");
    }
    return new EmptyResult();
}

步骤16 -执行和测试 按F5并执行应用程序。 在25实验室演讲 RenderBody做什么? 当我们第一次创建布局页面时,它有一个razor stamen,如下所示。 隐藏,复制Code

@Html.RenderBody()

我们来看看它是做什么的? 在内容页面中,我们通常定义在布局页面中声明的部分。 但奇怪的是,Razor也允许我们定义section之外的一些内容。 内容页面中的所有非节内容将由RenderBody函数呈现 下面的图片解释得更好。 。 我们可以有嵌套布局吗? 是的,我们可以。我们可以创建一个布局页面,它将使用一些其他的布局页面。语法是相同的。 是否需要在每个视图中指定布局页面? 您将发现一个特殊的视图,称为摔打视图。视图文件夹中的cshtml。在此定义的设置将应用于所有视图。 示例——简单地将以下代码放入剩余的viewstart中。cshtml,它将设置布局页为所有其他视图。 隐藏,复制Code

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

是否需要在每个动作方法中放入Header和FooterData代码? 不,不是必须的。我们可以通过动作过滤器来消除这种重复。这将是我们的下一个实验室。 在子视图中定义所有的section是必须的吗? 如果节声明为必修节,则为。默认值为true。 隐藏,复制Code

@RenderSection("HeaderSection",false) // Not required
@RenderSection("HeaderSection",true) // required
@RenderSection("HeaderSection") // required

实验室26 -使页眉和页脚数据代码更有效的行动过滤器 在23号实验室里,我们已经看到了ActionFilter的一个优点,现在是时候做第二个了。 步骤1 -从动作方法中删除冗余代码 从Index、AddNew和SaveEmployee方法(在Employee控制器中)中删除Header和FooterData代码。 作为引用,标题代码如下所示 隐藏,复制Code

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

页脚代码看起来像这样 隐藏,复制Code

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

步骤2 -创建HeaderFooterFilter 在Filters文件夹中创建一个名为HeaderFooterFilter的新类,并通过从ActionFilterAttribute类继承将其升级为Action filter 步骤2 -升级视图模型 在HeaderFooterFilter类中重写onactionexecution。在此方法中,获取当前视图模型并附加页眉和页脚数据。 隐藏,复制Code

public class HeaderFooterFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        ViewResult v = filterContext.Result as ViewResult;
        if(v!=null) // v will null when v is not a ViewResult
        {
                BaseViewModel bvm = v.Model as BaseViewModel;
                if(bvm!=null)//bvm will be null when we want a view without Header and footer
                {
                        bvm.UserName = HttpContext.Current.User.Identity.Name;
                        bvm.FooterData = new FooterViewModel();
                        bvm.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value
                        bvm.FooterData.Year = DateTime.Now.Year.ToString();            
                }
        }
    }
}

onactionexecution将用于向动作方法执行添加后期处理逻辑。 步骤4 -安装过滤器 将HeaderFooterFilter附加到Index、AddNew和SaveEmployee操作方法。 隐藏,复制Code

[HeaderFooterFilter]
public ActionResult Index()
{
    EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();
...
}
...
[AdminFilter]
[HeaderFooterFilter]
public ActionResult AddNew()
{
    CreateEmployeeViewModel employeeListViewModel = new CreateEmployeeViewModel();
    //employeeListViewModel.FooterData = new FooterViewModel();
    //employeeListViewModel.FooterData.CompanyName = "StepByStepSchools";
...
}
...
[AdminFilter]
[HeaderFooterFilter]
public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
    switch (BtnSubmit)
    {
        ...

步骤5 -执行和测试 按F5并执行应用程序。 结论 现在我们完成了第5天。第六天将是最艰难和最有趣的一天。请继续关注我 你的评论,邮件总是激励我们做更多。把你的想法和评论写在下面,或者发送邮件到SukeshMarla@Gmail.com 在Facebook, LinkedIn或twitter上联系我们,以保持最新的版本。 如需在孟买进行线下技术培训,请访问StepByStepSchools.Net 对于在线培训访问Compile.com或www.Sukesh-Marla.com 如果你想开始与MVC 5开始与下面的视频学习MVC 5在2天。 本文转载于:http://www.diyabc.com/frontweb/news1729.html

posted @ 2020-08-08 08:48  Dincat  阅读(118)  评论(0编辑  收藏  举报