{"id":605,"date":"2025-04-05T11:41:47","date_gmt":"2025-04-05T03:41:47","guid":{"rendered":"https:\/\/www.hyy.net\/?p=605"},"modified":"2025-04-05T11:41:47","modified_gmt":"2025-04-05T03:41:47","slug":"asp-net-core-in-action-17-rendering-html-using-razor-views","status":"publish","type":"post","link":"https:\/\/diji.net\/?p=605","title":{"rendered":"ASP.NET Core in Action 17 Rendering HTML using Razor views"},"content":{"rendered":"<p>17 Rendering HTML using Razor views<br \/>\n17 \u4f7f\u7528 Razor \u89c6\u56fe\u5448\u73b0 HTML<\/p>\n<p>This chapter covers<br \/>\n\u672c\u7ae0\u6db5\u76d6<br \/>\n\u2022  Creating Razor views to display HTML to a user<br \/>\n\u521b\u5efa Razor \u89c6\u56fe\u4ee5\u5411\u7528\u6237\u663e\u793a HTML<br \/>\n\u2022  Using C# and the Razor markup syntax to generate HTML dynamically<br \/>\n\u4f7f\u7528 C# \u548c Razor \u6807\u8bb0\u8bed\u6cd5\u52a8\u6001\u751f\u6210 HTML<br \/>\n\u2022  Reusing common code with layouts and partial views<br \/>\n\u5c06\u901a\u7528\u4ee3\u7801\u4e0e\u5e03\u5c40\u548c\u90e8\u5206\u89c6\u56fe\u91cd\u590d\u4f7f\u7528<\/p>\n<p>It\u2019s easy to get confused between the terms involved in Razor Pages\u2014PageModel, page handlers, Razor views\u2014especially as some of the terms describe concrete features, and others describe patterns and concepts. We\u2019ve touched on all these terms in detail in previous chapters, but it\u2019s important to get them straight in your mind:<br \/>\nRazor Pages \u4e2d\u6d89\u53ca\u7684\u672f\u8bed\uff08PageModel\u3001\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u3001Razor \u89c6\u56fe\uff09\u5f88\u5bb9\u6613\u6df7\u6dc6\uff0c\u5c24\u5176\u662f\u5f53\u5176\u4e2d\u4e00\u4e9b\u672f\u8bed\u63cf\u8ff0\u5177\u4f53\u529f\u80fd\uff0c\u800c\u53e6\u4e00\u4e9b\u672f\u8bed\u63cf\u8ff0\u6a21\u5f0f\u548c\u6982\u5ff5\u65f6\u3002\u6211\u4eec\u5728\u524d\u9762\u7684\u7ae0\u8282\u4e2d\u8be6\u7ec6\u4ecb\u7ecd\u4e86\u6240\u6709\u8fd9\u4e9b\u672f\u8bed\uff0c\u4f46\u8bf7\u52a1\u5fc5\u5c06\u5b83\u4eec\u6e05\u6670\u5730\u8bb0\u5728\u8111\u6d77\u4e2d\uff1a<\/p>\n<p>\u2022  Razor Pages\u2014Razor Pages generally refers to the page-based paradigm that combines routing, model binding, and HTML generation using Razor views.<br \/>\nRazor Pages - Razor Pages \u901a\u5e38\u662f\u6307\u57fa\u4e8e Page \u7684\u8303\u4f8b\uff0c\u5b83\u4f7f\u7528 Razor \u89c6\u56fe\u5c06\u8def\u7531\u3001\u6a21\u578b\u7ed1\u5b9a\u548c HTML \u751f\u6210\u76f8\u7ed3\u5408\u3002<\/p>\n<p>\u2022  Razor Page\u2014A single Razor Page represents a single page or endpoint. It typically consists of two files: a .cshtml file containing the Razor view and a .cshtml.cs file containing the page\u2019s PageModel.<br \/>\nRazor \u9875\u9762 - \u5355\u4e2a Razor \u9875\u9762\u8868\u793a\u5355\u4e2a\u9875\u9762\u6216\u7aef\u70b9\u3002\u5b83\u901a\u5e38\u7531\u4e24\u4e2a\u6587\u4ef6\u7ec4\u6210\uff1a\u4e00\u4e2a\u5305\u542b Razor \u89c6\u56fe\u7684 .cshtml \u6587\u4ef6\u548c\u4e00\u4e2a\u5305\u542b\u9875\u9762 PageModel \u7684 .cshtml.cs \u6587\u4ef6\u3002<\/p>\n<p>\u2022  PageModel\u2014The PageModel for a Razor Page is where most of the action happens. It\u2019s where you define the binding models for a page, which extracts data from the incoming request. It\u2019s also where you define the page\u2019s page handlers.<br \/>\nPageModel - Razor \u9875\u9762\u7684 PageModel \u662f\u5927\u591a\u6570\u4f5c\u53d1\u751f\u7684\u4f4d\u7f6e\u3002\u60a8\u53ef\u4ee5\u5728\u6b64\u5904\u5b9a\u4e49\u9875\u9762\u7684\u7ed1\u5b9a\u6a21\u578b\uff0c\u8be5\u9875\u9762\u4ece\u4f20\u5165\u8bf7\u6c42\u4e2d\u63d0\u53d6\u6570\u636e\u3002\u60a8\u8fd8\u53ef\u4ee5\u5728\u6b64\u5904\u5b9a\u4e49\u9875\u9762\u7684\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u3002<\/p>\n<p>\u2022  Page handler\u2014Each Razor Page typically handles a single route, but it can handle multiple HTTP verbs such as GET and POST. Each page handler typically handles a single HTTP verb.<br \/>\n\u9875\u9762\u5904\u7406\u7a0b\u5e8f - \u6bcf\u4e2a Razor \u9875\u9762\u901a\u5e38\u5904\u7406\u5355\u4e2a\u8def\u7531\uff0c\u4f46\u4e5f\u53ef\u4ee5\u5904\u7406\u591a\u4e2a HTTP \u52a8\u8bcd\uff0c\u4f8b\u5982 GET \u548c POST\u3002\u6bcf\u4e2a\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u901a\u5e38\u5904\u7406\u4e00\u4e2a HTTP \u52a8\u8bcd\u3002<\/p>\n<p>\u2022  Razor view\u2014Razor views (also called Razor templates) are used to generate HTML. They are typically used in the final stage of a Razor Page to generate the HTML response to send back to the user.<br \/>\nRazor \u89c6\u56fe - Razor \u89c6\u56fe \uff08\u4e5f\u79f0\u4e3a Razor \u6a21\u677f\uff09 \u7528\u4e8e\u751f\u6210 HTML\u3002\u5b83\u4eec\u901a\u5e38\u7528\u4e8e Razor \u9875\u9762\u7684\u6700\u540e\u9636\u6bb5\uff0c\u4ee5\u751f\u6210 HTML \u54cd\u5e94\u4ee5\u53d1\u9001\u56de\u7528\u6237\u3002<\/p>\n<p>In the previous four chapters, I covered a whole cross section of Razor Pages, including the Model-View-Controller (MVC) design pattern, the Razor Page PageModel, page handlers, routing, and binding models. This chapter covers the last part of the MVC pattern: using a view to generate the HTML that\u2019s delivered to the user\u2019s browser.<br \/>\n\u5728\u524d\u56db\u7ae0\u4e2d\uff0c\u6211\u4ecb\u7ecd\u4e86 Razor Pages \u7684\u6574\u4e2a\u6a2a\u622a\u9762\uff0c\u5305\u62ec\u6a21\u578b-\u89c6\u56fe-\u63a7\u5236\u5668 \uff08MVC\uff09 \u8bbe\u8ba1\u6a21\u5f0f\u3001Razor Page PageModel\u3001\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u3001\u8def\u7531\u548c\u7ed1\u5b9a\u6a21\u578b\u3002\u672c\u7ae0\u4ecb\u7ecd MVC \u6a21\u5f0f\u7684\u6700\u540e\u4e00\u90e8\u5206\uff1a\u4f7f\u7528\u89c6\u56fe\u751f\u6210\u4f20\u9001\u5230\u7528\u6237\u6d4f\u89c8\u5668\u7684 HTML\u3002<\/p>\n<p>In ASP.NET Core, views are normally created using the Razor markup syntax (sometimes described as a templating language), which uses a mixture of HTML and C# to generate the final HTML. This chapter covers some of the features of Razor and how to use it to build the view templates for your application. Generally speaking, users will have two sorts of interactions with your app: they\u2019ll read data that your app displays, and they\u2019ll send data or commands back to it. The Razor language contains several constructs that make it simple to build both types of applications.<br \/>\n\u5728 ASP.NET Core \u4e2d\uff0c\u89c6\u56fe\u901a\u5e38\u4f7f\u7528 Razor \u6807\u8bb0\u8bed\u6cd5\uff08\u6709\u65f6\u63cf\u8ff0\u4e3a\u6a21\u677f\u8bed\u8a00\uff09\u521b\u5efa\uff0c\u8be5\u8bed\u6cd5\u4f7f\u7528 HTML \u548c C# \u7684\u6df7\u5408\u6765\u751f\u6210\u6700\u7ec8\u7684 HTML\u3002\u672c\u7ae0\u4ecb\u7ecd Razor \u7684\u4e00\u4e9b\u529f\u80fd\uff0c\u4ee5\u53ca\u5982\u4f55\u4f7f\u7528\u5b83\u6765\u4e3a\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u6784\u5efa\u89c6\u56fe\u6a21\u677f\u3002\u4e00\u822c\u6765\u8bf4\uff0c\u7528\u6237\u5c06\u4e0e\u4f60\u7684\u5e94\u7528\u8fdb\u884c\u4e24\u79cd\u7c7b\u578b\u7684\u4ea4\u4e92\uff1a\u4ed6\u4eec\u5c06\u8bfb\u53d6\u4f60\u7684\u5e94\u7528\u663e\u793a\u7684\u6570\u636e\uff0c\u5e76\u5c06\u6570\u636e\u6216\u547d\u4ee4\u53d1\u9001\u56de\u5b83\u3002Razor \u8bed\u8a00\u5305\u542b\u591a\u4e2a\u6784\u9020\uff0c\u4f7f\u6784\u5efa\u8fd9\u4e24\u79cd\u7c7b\u578b\u7684\u5e94\u7528\u7a0b\u5e8f\u53d8\u5f97\u7b80\u5355\u3002<\/p>\n<p>When displaying data, you can use the Razor language to easily combine static HTML with values from your PageModel. Razor can use C# as a control mechanism, so adding conditional elements and loops is simple\u2014something you couldn\u2019t achieve with HTML alone.<br \/>\n\u663e\u793a\u6570\u636e\u65f6\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528 Razor \u8bed\u8a00\u8f7b\u677e\u5730\u5c06\u9759\u6001 HTML \u4e0e PageModel \u4e2d\u7684\u503c\u7ec4\u5408\u5728\u4e00\u8d77\u3002Razor \u53ef\u4ee5\u4f7f\u7528 C# \u4f5c\u4e3a\u63a7\u5236\u673a\u5236\uff0c\u56e0\u6b64\u6dfb\u52a0\u6761\u4ef6\u5143\u7d20\u548c\u5faa\u73af\u5f88\u7b80\u5355\uff0c\u8fd9\u662f\u5355\u72ec\u4f7f\u7528 HTML \u65e0\u6cd5\u5b9e\u73b0\u7684\u3002<\/p>\n<p>The normal approach to sending data to web applications is with HTML forms. Virtually every dynamic app you build will use forms; some applications will be pretty much nothing but forms! ASP.NET Core and the Razor templating language include Tag Helpers that make generating HTML forms easy.<br \/>\n\u5c06\u6570\u636e\u53d1\u9001\u5230 Web \u5e94\u7528\u7a0b\u5e8f\u7684\u6b63\u5e38\u65b9\u6cd5\u662f\u4f7f\u7528 HTML \u8868\u5355\u3002\u60a8\u6784\u5efa\u7684\u51e0\u4e4e\u6bcf\u4e2a\u52a8\u6001\u5e94\u7528\u7a0b\u5e8f\u90fd\u5c06\u4f7f\u7528\u8868\u5355;\u6709\u4e9b\u5e94\u7528\u7a0b\u5e8f\u51e0\u4e4e\u53ea\u4e0d\u8fc7\u662f\u8868\u5355\uff01ASP.NET Core \u548c Razor \u6a21\u677f\u8bed\u8a00\u5305\u62ec\u6807\u8bb0\u5e2e\u52a9\u7a0b\u5e8f\uff0c\u4f7f\u751f\u6210 HTML \u8868\u5355\u53d8\u5f97\u5bb9\u6613\u3002<\/p>\n<p><b>NOTE<\/b> You\u2019ll get a brief glimpse of Tag Helpers in section 17.1, but I explore them in detail in chapter 18.<br \/>\n\u6ce8\u610f:\u60a8\u5c06\u5728 17.1 \u8282\u4e2d\u7b80\u8981\u4e86\u89e3\u6807\u8bb0\u5e2e\u52a9\u7a0b\u5e8f\uff0c\u4f46\u6211\u4f1a\u5728\u7b2c 18 \u7ae0\u4e2d\u8be6\u7ec6\u63a2\u8ba8\u5b83\u4eec\u3002<\/p>\n<p>In this chapter we\u2019ll be focusing primarily on displaying data and generating HTML using Razor rather than creating forms. You\u2019ll see how to render values from your PageModel to the HTML, and how to use C# to control the generated output. Finally, you\u2019ll learn how to extract the common elements of your views into subviews called layouts and partial views, and how to compose them to create the final HTML page.<br \/>\n\u5728\u672c\u7ae0\u4e2d\uff0c\u6211\u4eec\u5c06\u4e3b\u8981\u5173\u6ce8\u4f7f\u7528 Razor \u663e\u793a\u6570\u636e\u548c\u751f\u6210 HTML\uff0c\u800c\u4e0d\u662f\u521b\u5efa\u8868\u5355\u3002\u60a8\u5c06\u4e86\u89e3\u5982\u4f55\u5c06 PageModel \u4e2d\u7684\u503c\u5448\u73b0\u5230 HTML\uff0c\u4ee5\u53ca\u5982\u4f55\u4f7f\u7528 C# \u63a7\u5236\u751f\u6210\u7684\u8f93\u51fa\u3002\u6700\u540e\uff0c\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u5c06\u89c6\u56fe\u7684\u5e38\u89c1\u5143\u7d20\u63d0\u53d6\u5230\u79f0\u4e3a\u5e03\u5c40\u548c\u5206\u90e8\u89c6\u56fe\u7684\u5b50\u89c6\u56fe\u4e2d\uff0c\u4ee5\u53ca\u5982\u4f55\u7f16\u5199\u5b83\u4eec\u4ee5\u521b\u5efa\u6700\u7ec8\u7684 HTML \u9875\u9762\u3002<\/p>\n<h2>17.1 Views: Rendering the user interface<\/h2>\n<p>17.1 \u89c6\u56fe\uff1a\u6e32\u67d3\u7528\u6237\u754c\u9762<\/p>\n<p>In this section I provide a quick introduction to rendering HTML using Razor views. We\u2019ll recap the MVC design pattern used by Razor Pages and where the view fits in. Then I\u2019ll show how Razor syntax allows you to mix C# and HTML to generate dynamic UIs.<br \/>\n\u5728\u672c\u8282\u4e2d\uff0c\u6211\u5c06\u7b80\u8981\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528 Razor \u89c6\u56fe\u5448\u73b0 HTML\u3002\u6211\u4eec\u5c06\u56de\u987e Razor Pages \u4f7f\u7528\u7684 MVC \u8bbe\u8ba1\u6a21\u5f0f\u4ee5\u53ca\u89c6\u56fe\u7684\u9002\u7528\u4f4d\u7f6e\u3002\u7136\u540e\uff0c\u6211\u5c06\u5c55\u793a Razor \u8bed\u6cd5\u5982\u4f55\u5141\u8bb8\u60a8\u6df7\u5408\u4f7f\u7528 C# \u548c HTML \u6765\u751f\u6210\u52a8\u6001 UI\u3002<\/p>\n<p>As you know from earlier chapters on the MVC design pattern, it\u2019s the job of the Razor Page\u2019s page handler to choose what to return to the client. For example, if you\u2019re developing a to-do list application, imagine a request to view a particular to-do item, as shown in figure 17.1.<br \/>\n\u6b63\u5982\u60a8\u5728\u524d\u9762\u6709\u5173 MVC \u8bbe\u8ba1\u6a21\u5f0f\u7684\u7ae0\u8282\u4e2d\u6240\u77e5\uff0cRazor Page \u7684\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u7684\u5de5\u4f5c\u662f\u9009\u62e9\u8981\u8fd4\u56de\u7ed9\u5ba2\u6237\u7aef\u7684\u5185\u5bb9\u3002\u4f8b\u5982\uff0c\u5982\u679c\u60a8\u6b63\u5728\u5f00\u53d1\u4e00\u4e2a\u5f85\u529e\u4e8b\u9879\u5217\u8868\u5e94\u7528\u7a0b\u5e8f\uff0c\u8bf7\u60f3\u8c61\u4e00\u4e2a\u67e5\u770b\u7279\u5b9a\u5f85\u529e\u4e8b\u9879\u7684\u8bf7\u6c42\uff0c\u5982\u56fe 17.1 \u6240\u793a\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1701.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 17.1 Handling a request for a to-do list item using ASP.NET Core Razor Pages. The page handler builds the data required by the view and exposes it as properties on the PageModel. The view generates HTML based only on the data provided; it doesn\u2019t need to know where that data comes from.<br \/>\n\u56fe 17.1 \u4f7f\u7528 ASP.NET Core Razor Pages \u5904\u7406\u5f85\u529e\u4e8b\u9879\u5217\u8868\u9879\u7684\u8bf7\u6c42\u3002\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u6784\u5efa\u89c6\u56fe\u6240\u9700\u7684\u6570\u636e\uff0c\u5e76\u5c06\u5176\u4f5c\u4e3a PageModel \u4e0a\u7684\u5c5e\u6027\u516c\u5f00\u3002\u89c6\u56fe\u4ec5\u6839\u636e\u63d0\u4f9b\u7684\u6570\u636e\u751f\u6210 HTML;\u5b83\u4e0d\u9700\u8981\u77e5\u9053\u8fd9\u4e9b\u6570\u636e\u6765\u81ea\u54ea\u91cc\u3002<\/p>\n<p>A typical request follows the steps shown in figure 17.1:<br \/>\n\u5178\u578b\u7684\u8bf7\u6c42\u9075\u5faa\u56fe 17.1 \u4e2d\u6240\u793a\u7684\u6b65\u9aa4\uff1a<\/p>\n<p>\u2022  The middleware pipeline receives the request, and the routing middleware determines the endpoint to invoke\u2014in this case, the View Razor Page in the ToDo folder.<br \/>\n\u4e2d\u95f4\u4ef6\u7ba1\u9053\u63a5\u6536\u8bf7\u6c42\uff0c\u8def\u7531\u4e2d\u95f4\u4ef6\u786e\u5b9a\u8981\u8c03\u7528\u7684\u7ec8\u7ed3\u70b9 - \u5728\u672c\u4f8b\u4e2d\u4e3a ToDo \u6587\u4ef6\u5939\u4e2d\u7684 View Razor Page\u3002<\/p>\n<p>\u2022  The model binder (part of the Razor Pages framework) uses the request to build the binding models for the page, as you saw in chapter 16. The binding models are set as properties on the Razor Page or are passed to the page handler method as arguments when the handler is executed. The page handler checks that you passed a valid id for the to-do item and marks the ModelState as valid if so.<br \/>\n\u6a21\u578b\u7ed1\u5b9a\u5668 \uff08Razor Pages \u6846\u67b6\u7684\u4e00\u90e8\u5206\uff09 \u4f7f\u7528\u8bf7\u6c42\u4e3a\u9875\u9762\u6784\u5efa\u7ed1\u5b9a\u6a21\u578b\uff0c\u5982\u7b2c 16 \u7ae0\u6240\u793a\u3002\u7ed1\u5b9a\u6a21\u578b\u5728 Razor Page \u4e0a\u8bbe\u7f6e\u4e3a\u5c5e\u6027\uff0c\u6216\u8005\u5728\u6267\u884c\u5904\u7406\u7a0b\u5e8f\u65f6\u4f5c\u4e3a\u53c2\u6570\u4f20\u9012\u7ed9\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u65b9\u6cd5\u3002\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u68c0\u67e5\u60a8\u662f\u5426\u4e3a\u5f85\u529e\u4e8b\u9879\u4f20\u9012\u4e86\u6709\u6548\u7684 ID\uff0c\u5982\u679c\u662f\uff0c\u5219\u5c06 ModelState \u6807\u8bb0\u4e3a\u6709\u6548\u3002<\/p>\n<p>\u2022  If the request is valid, the page handler calls out to the various services that make up the application model. This might load the details about the to-do from a database or from the filesystem, returning them to the handler. As part of this process, either the application model or the page handler itself generates values to pass to the view and sets them as properties on the Razor Page PageModel.<br \/>\n\u5982\u679c\u8bf7\u6c42\u6709\u6548\uff0c\u5219\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u5c06\u8c03\u7528\u6784\u6210\u5e94\u7528\u7a0b\u5e8f\u6a21\u578b\u7684\u5404\u79cd\u670d\u52a1\u3002\u8fd9\u53ef\u80fd\u4f1a\u4ece\u6570\u636e\u5e93\u6216\u6587\u4ef6\u7cfb\u7edf\u52a0\u8f7d\u6709\u5173 to-do \u7684\u8be6\u7ec6\u4fe1\u606f\uff0c\u5e76\u5c06\u5b83\u4eec\u8fd4\u56de\u7ed9\u5904\u7406\u7a0b\u5e8f\u3002\u5728\u6b64\u8fc7\u7a0b\u4e2d\uff0c\u5e94\u7528\u7a0b\u5e8f\u6a21\u578b\u6216\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u672c\u8eab\u4f1a\u751f\u6210\u8981\u4f20\u9012\u7ed9\u89c6\u56fe\u7684\u503c\uff0c\u5e76\u5c06\u5176\u8bbe\u7f6e\u4e3a Razor Page PageModel \u4e0a\u7684\u5c5e\u6027\u3002<br \/>\nOnce the page handler has executed, the PageModel should contain all the data required to render a view. In this example, it contains details about the to-do itself, but it might also contain other data, such as how many to-dos you have left, whether you have any to-dos scheduled for today, your username, and so on\u2014anything that controls how to generate the end UI for the request.<br \/>\n\u6267\u884c\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u540e\uff0c PageModel \u5e94\u5305\u542b\u5448\u73b0\u89c6\u56fe\u6240\u9700\u7684\u6240\u6709\u6570\u636e\u3002\u5728\u6b64\u793a\u4f8b\u4e2d\uff0c\u5b83\u5305\u542b\u6709\u5173\u5f85\u529e\u4e8b\u9879\u672c\u8eab\u7684\u8be6\u7ec6\u4fe1\u606f\uff0c\u4f46\u5b83\u4e5f\u53ef\u80fd\u5305\u542b\u5176\u4ed6\u6570\u636e\uff0c\u4f8b\u5982\u60a8\u8fd8\u5269\u4e0b\u591a\u5c11\u4e2a\u5f85\u529e\u4e8b\u9879\u3001\u60a8\u4eca\u5929\u662f\u5426\u5b89\u6392\u4e86\u4efb\u4f55\u5f85\u529e\u4e8b\u9879\u3001\u60a8\u7684\u7528\u6237\u540d\u7b49 \u2014 \u63a7\u5236\u5982\u4f55\u4e3a\u8bf7\u6c42\u751f\u6210\u6700\u7ec8 UI \u7684\u4efb\u4f55\u5185\u5bb9\u3002<\/p>\n<p>\u2022  The Razor view template uses the PageModel to generate the final response and returns it to the user via the middleware pipeline.<br \/>\nRazor \u89c6\u56fe\u6a21\u677f\u4f7f\u7528 PageModel \u751f\u6210\u6700\u7ec8\u54cd\u5e94\uff0c\u5e76\u901a\u8fc7\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5c06\u5176\u8fd4\u56de\u7ed9\u7528\u6237\u3002<\/p>\n<p>A common thread throughout this discussion of MVC is the separation of concerns MVC brings, and it\u2019s no different when it comes to your views. It would be easy enough to generate the HTML directly in your application model or in your controller actions, but instead you delegate that responsibility to a single component: the view.<br \/>\n\u8d2f\u7a7f\u672c\u6b21 MVC \u8ba8\u8bba\u7684\u4e00\u4e2a\u5171\u540c\u70b9\u662f MVC \u5e26\u6765\u7684\u5173\u6ce8\u70b9\u5206\u79bb\uff0c\u5bf9\u4e8e\u60a8\u7684\u89c6\u56fe\u6765\u8bf4\uff0c\u8fd9\u6ca1\u6709\u4ec0\u4e48\u4e0d\u540c\u3002\u76f4\u63a5\u5728\u5e94\u7528\u7a0b\u5e8f\u6a21\u578b\u6216\u63a7\u5236\u5668\u4f5c\u4e2d\u751f\u6210 HTML \u5f88\u5bb9\u6613\uff0c\u4f46\u60a8\u5c06\u8be5\u8d23\u4efb\u59d4\u6258\u7ed9\u5355\u4e2a\u7ec4\u4ef6\uff1a\u89c6\u56fe\u3002<\/p>\n<p>But even more than that, you separate the data required to build the view from the process of building it by using properties on the PageModel. These properties should contain all the dynamic data the view needs to generate the final output.<br \/>\n\u4f46\u66f4\u91cd\u8981\u7684\u662f\uff0c\u901a\u8fc7\u4f7f\u7528 PageModel \u4e0a\u7684\u5c5e\u6027\uff0c\u5c06\u6784\u5efa\u89c6\u56fe\u6240\u9700\u7684\u6570\u636e\u4e0e\u6784\u5efa\u89c6\u56fe\u7684\u8fc7\u7a0b\u5206\u5f00\u3002\u8fd9\u4e9b\u5c5e\u6027\u5e94\u5305\u542b\u89c6\u56fe\u751f\u6210\u6700\u7ec8\u8f93\u51fa\u6240\u9700\u7684\u6240\u6709\u52a8\u6001\u6570\u636e\u3002<\/p>\n<p><b>Tip<\/b> Views shouldn\u2019t call methods on the PageModel. The view should generally only be accessing data that has already been collected and exposed as properties.<br \/>\n\u63d0\u793a:\u89c6\u56fe\u4e0d\u5e94\u8c03\u7528 PageModel \u4e0a\u7684\u65b9\u6cd5\u3002\u89c6\u56fe\u901a\u5e38\u5e94\u4ec5\u8bbf\u95ee\u5df2\u6536\u96c6\u5e76\u4f5c\u4e3a\u5c5e\u6027\u516c\u5f00\u7684\u6570\u636e\u3002<\/p>\n<p>Razor Page handlers indicate that the Razor view should be rendered by returning a PageResult (or by returning void), as you saw in chapter 15. The Razor Pages infrastructure executes the Razor view associated with a given Razor Page to generate the final response. The use of C# in the Razor template means you can dynamically generate the final HTML sent to the browser. This allows you to, for example, display the name of the current user in the page, hide links the current user doesn\u2019t have access to, or render a button for every item in a list.<br \/>\nRazor Page \u5904\u7406\u7a0b\u5e8f\u6307\u793a\u5e94\u901a\u8fc7\u8fd4\u56de PageResult\uff08\u6216\u8fd4\u56de void\uff09\u6765\u5448\u73b0 Razor \u89c6\u56fe\uff0c\u5982\u7b2c 15 \u7ae0\u6240\u793a\u3002Razor Pages \u57fa\u7840\u7ed3\u6784\u6267\u884c\u4e0e\u7ed9\u5b9a Razor \u9875\u9762\u5173\u8054\u7684 Razor \u89c6\u56fe\uff0c\u4ee5\u751f\u6210\u6700\u7ec8\u54cd\u5e94\u3002\u5728 Razor \u6a21\u677f\u4e2d\u4f7f\u7528 C# \u610f\u5473\u7740\u60a8\u53ef\u4ee5\u52a8\u6001\u751f\u6210\u53d1\u9001\u5230\u6d4f\u89c8\u5668\u7684\u6700\u7ec8 HTML\u3002\u4f8b\u5982\uff0c\u8fd9\u5141\u8bb8\u60a8\u5728\u9875\u9762\u4e2d\u663e\u793a\u5f53\u524d\u7528\u6237\u7684\u540d\u79f0\uff0c\u9690\u85cf\u5f53\u524d\u7528\u6237\u65e0\u6743\u8bbf\u95ee\u7684\u94fe\u63a5\uff0c\u6216\u8005\u4e3a\u5217\u8868\u4e2d\u7684\u6bcf\u4e2a\u9879\u76ee\u5448\u73b0\u4e00\u4e2a\u6309\u94ae\u3002<\/p>\n<p>Imagine your boss asks you to add a page to your application that displays a list of the application\u2019s users. You should also be able to view a user from the page or create a new one, as shown in figure 17.2.<br \/>\n\u5047\u8bbe\u60a8\u7684\u8001\u677f\u8981\u6c42\u60a8\u5411\u5e94\u7528\u7a0b\u5e8f\u6dfb\u52a0\u4e00\u4e2a\u9875\u9762\uff0c\u8be5\u9875\u9762\u663e\u793a\u5e94\u7528\u7a0b\u5e8f\u7684\u7528\u6237\u5217\u8868\u3002\u60a8\u8fd8\u5e94\u8be5\u80fd\u591f\u4ece\u9875\u9762\u67e5\u770b\u7528\u6237\u6216\u521b\u5efa\u65b0\u7528\u6237\uff0c\u5982\u56fe 17.2 \u6240\u793a\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1702.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 17.2 The use of C# in Razor lets you easily generate dynamic HTML that varies at runtime. In this example, using a foreach loop inside the Razor view dramatically reduces the duplication in the HTML that you would otherwise have to write.<br \/>\n\u56fe 17.2 \u5728 Razor \u4e2d\u4f7f\u7528 C# \u53ef\u8ba9\u60a8\u8f7b\u677e\u751f\u6210\u5728\u8fd0\u884c\u65f6\u53d8\u5316\u7684\u52a8\u6001 HTML\u3002\u5728\u6b64\u793a\u4f8b\u4e2d\uff0c\u5728 Razor \u89c6\u56fe\u4e2d\u4f7f\u7528 foreach \u5faa\u73af\u53ef\u663e\u8457\u51cf\u5c11 HTML \u4e2d\u5fc5\u987b\u7f16\u5199\u7684\u91cd\u590d\u9879\u3002<\/p>\n<p>With Razor templates, generating this sort of dynamic content is simple. Listing 17.1 shows a template that could be used to generate the interface in figure 17.2. It combines standard HTML with C# statements and uses Tag Helpers to generate the form elements.<br \/>\n\u4f7f\u7528 Razor \u6a21\u677f\uff0c\u751f\u6210\u6b64\u7c7b\u52a8\u6001\u5185\u5bb9\u975e\u5e38\u7b80\u5355\u3002\u6e05\u5355 17.1 \u663e\u793a\u4e86\u4e00\u4e2a\u53ef\u7528\u4e8e\u751f\u6210\u56fe 17.2 \u4e2d\u63a5\u53e3\u7684\u6a21\u677f\u3002\u5b83\u5c06\u6807\u51c6 HTML \u4e0e C# \u8bed\u53e5\u76f8\u7ed3\u5408\uff0c\u5e76\u4f7f\u7528\u6807\u8bb0\u5e2e\u52a9\u7a0b\u5e8f\u751f\u6210\u8868\u5355\u5143\u7d20\u3002<\/p>\n<p>Listing 17.1 A Razor template to list users and a form for adding a new user<br \/>\n\u6e05\u5355 17.1 \u7528\u4e8e\u5217\u51fa\u7528\u6237\u7684 Razor \u6a21\u677f\u548c\u7528\u4e8e\u6dfb\u52a0\u65b0\u7528\u6237\u7684\u8868\u5355<\/p>\n<pre><code>@page\n@model IndexViewModel\n&lt;div class=&quot;row&quot;&gt; \u2776\n&lt;div class=&quot;col-md-6&quot;&gt; \u2776\n&lt;form method=&quot;post&quot;&gt;\n&lt;div class=&quot;form-group&quot;&gt;\n&lt;label asp-for=&quot;NewUser&quot;&gt;&lt;\/label&gt; \u2777\n&lt;input class=&quot;form-control&quot; asp-for=&quot;NewUser&quot; \/&gt; \u2777\n&lt;span asp-validation-for=&quot;NewUser&quot;&gt;&lt;\/span&gt; \u2777\n&lt;\/div&gt;\n&lt;div class=&quot;form-group&quot;&gt;\n&lt;button type=&quot;submit&quot;\nclass=&quot;btn btn-success&quot;&gt;Add&lt;\/button&gt;\n&lt;\/div&gt;\n&lt;\/form&gt;\n&lt;\/div&gt;\n&lt;\/div&gt;\n&lt;h4&gt;Number of users: @Model.ExistingUsers.Count&lt;\/h4&gt; \u2778\n&lt;div class=&quot;row&quot;&gt;\n&lt;div class=&quot;col-md-6&quot;&gt;\n&lt;ul class=&quot;list-group&quot;&gt;\n@foreach (var user in Model.ExistingUsers) \u2779\n{\n&lt;li class=&quot;list-group-item d-flex justify-content-between&quot;&gt;\n&lt;span&gt;@user&lt;\/span&gt;\n&lt;a class=&quot;btn btn-info&quot;\nasp-page=&quot;ViewUser&quot; \u277a\nasp-route-userName=&quot;@user&quot;&gt;View&lt;\/a&gt; \u277a\n&lt;\/li&gt;\n}\n&lt;\/ul&gt;\n&lt;\/div&gt;\n&lt;\/div&gt;<\/code><\/pre>\n<p>\u2776 Normal HTML is sent to the browser unchanged.<br \/>\n\u666e\u901a HTML \u539f\u5c01\u4e0d\u52a8\u5730\u53d1\u9001\u5230\u6d4f\u89c8\u5668\u3002<br \/>\n\u2777 Tag Helpers attach to HTML elements to create forms.<br \/>\n\u6807\u7b7e\u52a9\u624b\u9644\u52a0\u5230 HTML \u5143\u7d20\u4ee5\u521b\u5efa\u8868\u5355\u3002<br \/>\n\u2778 Values can be written from C# objects to the HTML.<br \/>\n\u503c\u53ef\u4ee5\u4ece C# \u5bf9\u8c61\u5199\u5165 HTML\u3002<br \/>\n\u2779 C# constructs such as for loops can be used in Razor.<br \/>\n\u53ef\u4ee5\u5728 Razor \u4e2d\u4f7f\u7528 for \u5faa\u73af\u7b49 C# \u6784\u9020\u3002<br \/>\n\u277a Tag Helpers can also be used outside forms to help in other HTML generation.<br \/>\n\u6807\u7b7e\u52a9\u624b\u4e5f\u53ef\u4ee5\u5728\u8868\u5355\u4e4b\u5916\u4f7f\u7528\uff0c\u4ee5\u5e2e\u52a9\u751f\u6210\u5176\u4ed6 HTML\u3002<\/p>\n<p>This example demonstrates a variety of Razor features. There\u2019s a mixture of HTML that\u2019s written unmodified to the response output, and there are various C# constructs used to generate HTML dynamically. In addition, you can see several Tag Helpers. These look like normal HTML attributes that start with asp-, but they\u2019re part of the Razor language. They can customize the HTML element they\u2019re attached to, changing how it\u2019s rendered. They make building HTML forms much simpler than they would be otherwise. Don\u2019t worry if this template is a bit overwhelming at the moment; we\u2019ll break it all down as you progress through this chapter and the next.<br \/>\n\u6b64\u793a\u4f8b\u6f14\u793a\u4e86\u5404\u79cd Razor \u529f\u80fd\u3002\u54cd\u5e94\u8f93\u51fa\u4e2d\u6df7\u5408\u4e86\u672a\u7ecf\u4fee\u6539\u7684 HTML\uff0c\u5e76\u4e14\u6709\u5404\u79cd C# \u6784\u9020\u7528\u4e8e\u52a8\u6001\u751f\u6210 HTML\u3002\u6b64\u5916\uff0c\u60a8\u8fd8\u53ef\u4ee5\u770b\u5230\u591a\u4e2a Tag Helpers\u3002\u8fd9\u4e9b\u770b\u8d77\u6765\u7c7b\u4f3c\u4e8e\u4ee5 asp- \u5f00\u5934\u7684\u666e\u901a HTML \u5c5e\u6027\uff0c\u4f46\u5b83\u4eec\u662f Razor \u8bed\u8a00\u7684\u4e00\u90e8\u5206\u3002\u4ed6\u4eec\u53ef\u4ee5\u81ea\u5b9a\u4e49\u9644\u52a0\u5230\u7684 HTML \u5143\u7d20\uff0c\u4ece\u800c\u66f4\u6539\u5176\u5448\u73b0\u65b9\u5f0f\u3002\u5b83\u4eec\u4f7f\u6784\u5efa HTML \u8868\u5355\u6bd4\u5176\u4ed6\u65b9\u5f0f\u7b80\u5355\u5f97\u591a\u3002\u5982\u679c\u8fd9\u4e2a\u6a21\u677f\u76ee\u524d\u6709\u70b9\u8ba9\u4eba\u4e0d\u77e5\u6240\u63aa\uff0c\u8bf7\u4e0d\u8981\u62c5\u5fc3;\u968f\u7740\u60a8\u5b8c\u6210\u672c\u7ae0\u548c\u4e0b\u4e00\u7ae0\uff0c\u6211\u4eec\u5c06\u5bf9\u5176\u8fdb\u884c\u5168\u90e8\u5206\u89e3\u3002<\/p>\n<p>Razor Pages are compiled when you build your application. Behind the scenes, they become another C# class in your application. It\u2019s also possible to enable runtime compilation of your Razor Pages. This allows you to modify your Razor Pages while your app is running without having to explicitly stop and rebuild. This can be handy when developing locally, but it\u2019s best avoided when you deploy to production. You can read how to enable this at <a href=\"http:\/\/mng.bz\/jP2P\">http:\/\/mng.bz\/jP2P<\/a>.<br \/>\nRazor Pages \u662f\u5728\u6784\u5efa\u5e94\u7528\u7a0b\u5e8f\u65f6\u7f16\u8bd1\u7684\u3002\u5728\u540e\u53f0\uff0c\u5b83\u4eec\u6210\u4e3a\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u53e6\u4e00\u4e2a C# \u7c7b\u3002\u8fd8\u53ef\u4ee5\u542f\u7528 Razor Pages \u7684\u8fd0\u884c\u65f6\u7f16\u8bd1\u3002\u8fd9\u6837\uff0c\u60a8\u5c31\u53ef\u4ee5\u5728\u5e94\u7528\u8fd0\u884c\u65f6\u4fee\u6539 Razor Pages\uff0c\u800c\u65e0\u9700\u663e\u5f0f\u505c\u6b62\u548c\u91cd\u65b0\u751f\u6210\u3002\u5728\u672c\u5730\u5f00\u53d1\u65f6\uff0c\u8fd9\u53ef\u80fd\u5f88\u65b9\u4fbf\uff0c\u4f46\u5728\u90e8\u7f72\u5230\u751f\u4ea7\u73af\u5883\u65f6\u6700\u597d\u907f\u514d\u3002\u60a8\u53ef\u4ee5\u5728 <a href=\"http:\/\/mng.bz\/jP2P\">http:\/\/mng.bz\/jP2P<\/a> \u9605\u8bfb\u5982\u4f55\u542f\u7528\u6b64\u529f\u80fd\u3002<\/p>\n<p><b>NOTE<\/b> As with most things in ASP.NET Core, it\u2019s possible to swap out the Razor templating engine and replace it with your own server-side rendering engine. You can\u2019t replace Razor with a client-side framework like Angular or React. If you want to take this approach, you\u2019d use minimal APIs or web API controllers instead and a separate client-side framework.<br \/>\n\u6ce8\u610f:\u4e0e ASP.NET Core \u4e2d\u7684\u5927\u591a\u6570\u5185\u5bb9\u4e00\u6837\uff0c\u53ef\u4ee5\u6362\u51fa Razor \u6a21\u677f\u5f15\u64ce\uff0c\u5e76\u5c06\u5176\u66ff\u6362\u4e3a\u60a8\u81ea\u5df1\u7684\u670d\u52a1\u5668\u7aef\u6e32\u67d3\u5f15\u64ce\u3002\u60a8\u4e0d\u80fd\u5c06 Razor \u66ff\u6362\u4e3a Angular \u6216 React \u7b49\u5ba2\u6237\u7aef\u6846\u67b6\u3002\u5982\u679c\u8981\u91c7\u7528\u6b64\u65b9\u6cd5\uff0c\u5219\u9700\u8981\u4f7f\u7528\u6700\u5c11\u7684 API \u6216 Web API \u63a7\u5236\u5668\u4ee5\u53ca\u5355\u72ec\u7684\u5ba2\u6237\u7aef\u6846\u67b6\u3002<\/p>\n<p>In the next section we\u2019ll look in more detail at how Razor views fit into the Razor Pages framework and how you can pass data from your Razor Page handlers to the Razor view to help build the HTML response.<br \/>\n\u5728\u4e0b\u4e00\u90e8\u5206\u4e2d\uff0c\u6211\u4eec\u5c06\u66f4\u8be6\u7ec6\u5730\u4e86\u89e3 Razor \u89c6\u56fe\u5982\u4f55\u9002\u5e94 Razor Pages \u6846\u67b6\uff0c\u4ee5\u53ca\u5982\u4f55\u5c06\u6570\u636e\u4ece Razor Page \u5904\u7406\u7a0b\u5e8f\u4f20\u9012\u5230 Razor \u89c6\u56fe\u4ee5\u5e2e\u52a9\u6784\u5efa HTML \u54cd\u5e94\u3002<\/p>\n<h2>17.2 Creating Razor views<\/h2>\n<p>17.2 \u521b\u5efa Razor \u89c6\u56fe<\/p>\n<p>In this section we\u2019ll look at how Razor views fit into the Razor Pages framework. You\u2019ll learn how to pass data from your page handlers to your Razor views and how you can use that data to generate dynamic HTML.<br \/>\n\u5728\u672c\u90e8\u5206\u4e2d\uff0c\u6211\u4eec\u5c06\u4e86\u89e3 Razor \u89c6\u56fe\u5982\u4f55\u9002\u5e94 Razor Pages \u6846\u67b6\u3002\u60a8\u5c06\u4e86\u89e3\u5982\u4f55\u5c06\u6570\u636e\u4ece\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u4f20\u9012\u5230 Razor \u89c6\u56fe\uff0c\u4ee5\u53ca\u5982\u4f55\u4f7f\u7528\u8be5\u6570\u636e\u751f\u6210\u52a8\u6001 HTML\u3002<\/p>\n<p>With ASP.NET Core, whenever you need to display an HTML response to the user, you should use a view to generate it. Although it\u2019s possible to directly generate a string from your page handlers, which will be rendered as HTML in the browser, this approach doesn\u2019t adhere to the MVC separation of concerns and will quickly leave you tearing your hair out.<br \/>\n\u4f7f\u7528 ASP.NET Core\uff0c\u6bcf\u5f53\u9700\u8981\u5411\u7528\u6237\u663e\u793a HTML \u54cd\u5e94\u65f6\uff0c\u90fd\u5e94\u8be5\u4f7f\u7528\u89c6\u56fe\u6765\u751f\u6210\u5b83\u3002\u5c3d\u7ba1\u53ef\u4ee5\u76f4\u63a5\u4ece\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u751f\u6210\u5b57\u7b26\u4e32\uff0c\u8be5\u5b57\u7b26\u4e32\u5c06\u5728\u6d4f\u89c8\u5668\u4e2d\u5448\u73b0\u4e3a HTML\uff0c\u4f46\u8fd9\u79cd\u65b9\u6cd5\u4e0d\u7b26\u5408 MVC \u5173\u6ce8\u70b9\u5206\u79bb\uff0c\u5e76\u4e14\u5f88\u5feb\u5c31\u4f1a\u8ba9\u60a8\u611f\u5230\u56f0\u60d1\u3002<\/p>\n<p><b>NOTE<\/b> Some middleware, such as the WelcomePageMiddleware you saw in chapter 4, may generate HTML responses without using a view, which can make sense in some situations. But your Razor Page and MVC controllers should always generate HTML using views.<br \/>\n\u6ce8\u610f:\u4e00\u4e9b\u4e2d\u95f4\u4ef6\uff0c\u6bd4\u5982\u4f60\u5728\u7b2c 4 \u7ae0\u4e2d\u770b\u5230\u7684 WelcomePageMiddleware\uff0c\u53ef\u80fd\u4f1a\u5728\u4e0d\u4f7f\u7528\u89c6\u56fe\u7684\u60c5\u51b5\u4e0b\u751f\u6210 HTML \u54cd\u5e94\uff0c\u8fd9\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\u662f\u6709\u610f\u4e49\u7684\u3002\u4f46 Razor Page \u548c MVC \u63a7\u5236\u5668\u5e94\u59cb\u7ec8\u4f7f\u7528\u89c6\u56fe\u751f\u6210 HTML\u3002<\/p>\n<p>Instead, by relying on Razor views to generate the response, you get access to a wide variety of features, as well as editor tooling to help. This section serves as a gentle introduction to Razor views, the things you can do with them, and the various ways you can pass data to them.<br \/>\n\u76f8\u53cd\uff0c\u901a\u8fc7\u4f9d\u9760 Razor \u89c6\u56fe\u751f\u6210\u54cd\u5e94\uff0c\u60a8\u53ef\u4ee5\u8bbf\u95ee\u5404\u79cd\u529f\u80fd\u4ee5\u53ca\u63d0\u4f9b\u5e2e\u52a9\u7684\u7f16\u8f91\u5668\u5de5\u5177\u3002\u672c\u8282\u7b80\u8981\u4ecb\u7ecd\u4e86 Razor \u89c6\u56fe\u3001\u60a8\u53ef\u4ee5\u4f7f\u7528\u5b83\u4eec\u6267\u884c\u7684\u4f5c\u4ee5\u53ca\u5411\u5b83\u4eec\u4f20\u9012\u6570\u636e\u7684\u5404\u79cd\u65b9\u5f0f\u3002<\/p>\n<h3>17.2.1 Razor views and code-behind<\/h3>\n<p>17.2.1 Razor \u89c6\u56fe\u548c\u4ee3\u7801\u9690\u85cf<\/p>\n<p>In this book you\u2019ve already seen that Razor Pages typically consist of two files:<br \/>\n\u5728\u672c\u4e66\u4e2d\uff0c\u60a8\u5df2\u7ecf\u770b\u5230 Razor Pages \u901a\u5e38\u7531\u4e24\u4e2a\u6587\u4ef6\u7ec4\u6210\uff1a<br \/>\n\u2022  The .cshtml file, commonly called the Razor view<br \/>\n.cshtml \u6587\u4ef6\uff0c\u901a\u5e38\u79f0\u4e3a Razor \u89c6\u56fe<br \/>\n\u2022  The .cshtml.cs file, commonly called the code-behind, which contains the PageModel<br \/>\n.cshtml.cs \u6587\u4ef6\uff0c\u901a\u5e38\u79f0\u4e3a\u4ee3\u7801\u9690\u85cf\uff0c\u5176\u4e2d\u5305\u542b PageModel<\/p>\n<p>The Razor view contains the @page directive, which makes it a Razor Page, as you\u2019ve seen previously. Without this directive, the Razor Pages framework will not route requests to the page, and the file is ignored for most purposes.<br \/>\nRazor \u89c6\u56fe\u5305\u542b @page \u6307\u4ee4\uff0c\u8fd9\u4f7f\u5176\u6210\u4e3a Razor \u9875\u9762\uff0c\u5982\u524d\u6240\u8ff0\u3002\u5982\u679c\u6ca1\u6709\u6b64\u6307\u4ee4\uff0cRazor Pages \u6846\u67b6\u4e0d\u4f1a\u5c06\u8bf7\u6c42\u8def\u7531\u5230\u9875\u9762\uff0c\u5e76\u4e14\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\u4f1a\u5ffd\u7565\u8be5\u6587\u4ef6\u3002<\/p>\n<p><b>DEFINITION<\/b> A directive is a statement in a Razor file that changes the way the template is parsed or compiled. Another common directive is the @using newNamespace directive, which makes objects in the newNamespace namespace available.<br \/>\n\u5b9a\u4e49:\u6307\u4ee4\u662f Razor \u6587\u4ef6\u4e2d\u7684\u4e00\u6761\u8bed\u53e5\uff0c\u7528\u4e8e\u66f4\u6539\u6a21\u677f\u7684\u5206\u6790\u6216\u7f16\u8bd1\u65b9\u5f0f\u3002\u53e6\u4e00\u4e2a\u5e38\u89c1\u6307\u4ee4\u662f @using newNamespace \u6307\u4ee4\uff0c\u5b83\u4f7f newNamespace \u547d\u540d\u7a7a\u95f4\u4e2d\u7684\u5bf9\u8c61\u53ef\u7528\u3002<\/p>\n<p>The code-behind .cshtml.cs file contains the PageModel for an associated Razor Page. It contains the page handlers that respond to requests, and it is where the Razor Page typically interacts with other parts of your application.<br \/>\n\u4ee3\u7801\u9690\u85cf .cshtml.cs \u6587\u4ef6\u5305\u542b\u5173\u8054 Razor \u9875\u9762\u7684 PageModel\u3002\u5b83\u5305\u542b\u54cd\u5e94\u8bf7\u6c42\u7684\u9875\u9762\u5904\u7406\u7a0b\u5e8f\uff0c\u5e76\u4e14\u662f Razor Page \u901a\u5e38\u4e0e\u5e94\u7528\u7a0b\u5e8f\u7684\u5176\u4ed6\u90e8\u5206\u4ea4\u4e92\u7684\u4f4d\u7f6e\u3002<\/p>\n<p>Even though the .cshtml and .cshtml.cs files have the same name, such as ToDoItem.cshtml and ToDoItem.cshtml.cs, it\u2019s not the filename that\u2019s linking them. But if it\u2019s not by filename, how does the Razor Pages framework know which PageModel is associated with a given Razor Page view file?<br \/>\n\u5373\u4f7f .cshtml \u548c .cshtml.cs \u6587\u4ef6\u5177\u6709\u76f8\u540c\u7684\u540d\u79f0\uff08\u5982 ToDoItem.cshtml \u548c ToDoItem.cshtml.cs\uff09\uff0c\u4e5f\u4e0d\u662f\u94fe\u63a5\u5b83\u4eec\u7684\u6587\u4ef6\u540d\u3002\u4f46\u662f\uff0c\u5982\u679c\u4e0d\u662f\u6309\u6587\u4ef6\u540d\uff0cRazor Pages \u6846\u67b6\u5982\u4f55\u77e5\u9053\u54ea\u4e2a PageModel \u4e0e\u7ed9\u5b9a\u7684 Razor Page \u89c6\u56fe\u6587\u4ef6\u76f8\u5173\u8054\uff1f<\/p>\n<p>At the top of each Razor Page, after the @page directive, is the @model directive with a Type, indicating which PageModel is associated with the Razor view. The following directives indicate that the ToDoItemModel is the PageModel associated with the Razor Page:<br \/>\n\u5728\u6bcf\u4e2a Razor \u9875\u9762\u7684\u9876\u90e8\uff0c@page \u6307\u4ee4\u540e\u9762\u662f\u5e26\u6709 Type \u7684 @model \u6307\u4ee4\uff0c\u6307\u793a\u54ea\u4e2a PageModel \u4e0e Razor \u89c6\u56fe\u76f8\u5173\u8054\u3002\u4ee5\u4e0b\u6307\u4ee4\u6307\u793a ToDoItemModel \u662f\u4e0e Razor Page \u5173\u8054\u7684 PageModel\uff1a<\/p>\n<pre><code>@page\n@model ToDoItemModel<\/code><\/pre>\n<p>Once a request is routed to a Razor Page, as covered in chapter 14, the framework looks for the @model directive to decide which PageModel to use. Based on the PageModel selected, it then binds to any properties in the PageModel marked with the [BindProperty] attribute (as we covered in chapter 16) and executes the appropriate page handler (based on the request\u2019s HTTP verb, as described in chapter 15).<br \/>\n\u5c06\u8bf7\u6c42\u8def\u7531\u5230 Razor Page \u540e\uff08\u5982\u7b2c 14 \u7ae0\u6240\u8ff0\uff09\uff0c\u6846\u67b6\u4f1a\u67e5\u627e @model \u6307\u4ee4\u6765\u51b3\u5b9a\u4f7f\u7528\u54ea\u4e2a PageModel\u3002\u7136\u540e\uff0c\u6839\u636e\u6240\u9009\u7684 PageModel\uff0c\u5b83\u7ed1\u5b9a\u5230 PageModel \u4e2d\u6807\u6709 [BindProperty] \u5c5e\u6027\u7684\u4efb\u4f55\u5c5e\u6027\uff08\u5982\u7b2c 16 \u7ae0\u6240\u8ff0\uff09\uff0c\u5e76\u6267\u884c\u76f8\u5e94\u7684\u9875\u9762\u5904\u7406\u7a0b\u5e8f\uff08\u57fa\u4e8e\u8bf7\u6c42\u7684 HTTP \u52a8\u8bcd\uff0c\u5982\u7b2c 15 \u7ae0\u6240\u8ff0\uff09\u3002<\/p>\n<p><b>NOTE<\/b> Technically, the PageModel and @model directive are optional. If you don\u2019t specify a PageModel, the framework executes an implicit page handler, as you saw in chapter 15, and renders the view directly. It\u2019s also possible to combine the .cshtml and .cshtml.cs files into a single .cshtml file. You can read more about this approach in Razor Pages in Action, by Mark Brind (Manning, 2022).<br \/>\n\u6ce8\u610f:\u4ece\u6280\u672f\u4e0a\u8bb2\uff0cPageModel \u548c @model \u6307\u4ee4\u662f\u53ef\u9009\u7684\u3002\u5982\u679c\u4f60\u6ca1\u6709\u6307\u5b9a PageModel\uff0c\u6846\u67b6\u5c06\u6267\u884c\u4e00\u4e2a\u9690\u5f0f\u9875\u9762\u5904\u7406\u7a0b\u5e8f\uff0c\u5c31\u50cf\u4f60\u5728\u7b2c 15 \u7ae0\u4e2d\u770b\u5230\u7684\u90a3\u6837\uff0c\u5e76\u76f4\u63a5\u6e32\u67d3\u89c6\u56fe\u3002\u8fd8\u53ef\u4ee5\u5c06 .cshtml \u548c .cshtml.cs \u6587\u4ef6\u5408\u5e76\u5230\u5355\u4e2a .cshtml \u6587\u4ef6\u4e2d\u3002\u60a8\u53ef\u4ee5\u5728 Mark Brind \u7684 Razor Pages in Action\uff08Manning\uff0c2022 \u5e74\uff09\u4e2d\u9605\u8bfb\u6709\u5173\u6b64\u65b9\u6cd5\u7684\u66f4\u591a\u4fe1\u606f\u3002<\/p>\n<p>In addition to the @page and @model directives, the Razor view file contains the Razor template that is executed to generate the HTML response.<br \/>\n\u9664\u4e86 @page \u548c @model \u6307\u4ee4\u4e4b\u5916\uff0cRazor \u89c6\u56fe\u6587\u4ef6\u8fd8\u5305\u542b\u4e3a\u751f\u6210 HTML \u54cd\u5e94\u800c\u6267\u884c\u7684 Razor \u6a21\u677f\u3002<\/p>\n<h3>17.2.2 Introducing Razor templates<\/h3>\n<p>17.2.2 Razor \u6a21\u677f\u7b80\u4ecb<\/p>\n<p>Razor view templates contain a mixture of HTML and C# code interspersed with one another. The HTML markup lets you easily describe exactly what should be sent to the browser, whereas the C# code can be used to dynamically change what is rendered. The following listing shows an example of Razor rendering a list of strings representing to-do items.<br \/>\nRazor \u89c6\u56fe\u6a21\u677f\u5305\u542b\u76f8\u4e92\u7a7f\u63d2\u7684 HTML \u548c C# \u4ee3\u7801\u7684\u6df7\u5408\u3002HTML \u6807\u8bb0\u53ef\u8ba9\u60a8\u8f7b\u677e\u51c6\u786e\u63cf\u8ff0\u5e94\u53d1\u9001\u5230\u6d4f\u89c8\u5668\u7684\u5185\u5bb9\uff0c\u800c C# \u4ee3\u7801\u53ef\u7528\u4e8e\u52a8\u6001\u66f4\u6539\u5448\u73b0\u7684\u5185\u5bb9\u3002\u4ee5\u4e0b\u6e05\u5355\u663e\u793a\u4e86 Razor \u5448\u73b0\u8868\u793a\u5f85\u529e\u4e8b\u9879\u7684\u5b57\u7b26\u4e32\u5217\u8868\u7684\u793a\u4f8b\u3002<\/p>\n<p>Listing 17.2 Razor template for rendering a list of strings<br \/>\n\u6e05\u5355 17.2 \u7528\u4e8e\u6e32\u67d3\u5b57\u7b26\u4e32\u5217\u8868\u7684 Razor \u6a21\u677f<\/p>\n<pre><code>@page\n@{ \u2776\nvar tasks = new List&lt;string&gt; \u2776\n{ &quot;Buy milk&quot;, &quot;Buy eggs&quot;, &quot;Buy bread&quot; }; \u2776\n} \u2776\n&lt;h1&gt;Tasks to complete&lt;\/h1&gt; \u2777\n&lt;ul&gt;\n@for(var i=0; i&lt; tasks.Count; i++) \u2778\n{ \u2778\nvar task = tasks[i]; \u2778\n&lt;li&gt;@i - @task&lt;\/li&gt; \u2778\n} \u2778\n&lt;\/ul&gt;<\/code><\/pre>\n<p>\u2776 Arbitrary C# can be executed in a template. Variables remain in scope throughout the page.<br \/>\n\u53ef\u4ee5\u5728\u6a21\u677f\u4e2d\u6267\u884c\u4efb\u610f C#\u3002\u53d8\u91cf\u5728\u6574\u4e2a\u9875\u9762\u4e2d\u4fdd\u6301\u8303\u56f4\u5185\u3002<br \/>\n\u2777 Standard HTML markup will be rendered to the output unchanged.<br \/>\n\u6807\u51c6 HTML \u6807\u8bb0\u5c06\u539f\u5c01\u4e0d\u52a8\u5730\u5448\u73b0\u5230\u8f93\u51fa\u3002<br \/>\n\u2778 Mixing C# and HTML allows you to create HTML dynamically at runtime.<br \/>\n\u6df7\u5408\u4f7f\u7528 C# \u548c HTML \u5141\u8bb8\u60a8\u5728\u8fd0\u884c\u65f6\u52a8\u6001\u521b\u5efa HTML\u3002<\/p>\n<p>The pure HTML sections in this template are in the angle brackets. The Razor engine copies this HTML directly to the output, unchanged, as though you were writing a normal HTML file.<br \/>\n\u6b64\u6a21\u677f\u4e2d\u7684\u7eaf HTML \u90e8\u5206\u4f4d\u4e8e\u5c16\u62ec\u53f7\u4e2d\u3002Razor \u5f15\u64ce\u5c06\u6b64 HTML \u76f4\u63a5\u590d\u5236\u5230\u8f93\u51fa\u4e2d\uff0c\u4fdd\u6301\u4e0d\u53d8\uff0c\u5c31\u50cf\u60a8\u6b63\u5728\u7f16\u5199\u666e\u901a\u7684 HTML \u6587\u4ef6\u4e00\u6837\u3002<\/p>\n<p><b>NOTE<\/b> The ability of Razor syntax to know when you are switching between HTML and C# can be both uncanny and infuriating at times. I discuss how to control this transition in section 17.3.<br \/>\n\u6ce8\u610f:Razor \u8bed\u6cd5\u80fd\u591f\u77e5\u9053\u60a8\u4f55\u65f6\u5728 HTML \u548c C# \u4e4b\u95f4\u5207\u6362\uff0c\u8fd9\u6709\u65f6\u65e2\u4e0d\u53ef\u601d\u8bae\u53c8\u4ee4\u4eba\u607c\u706b\u3002\u6211\u5728 17.3 \u8282\u4e2d\u8ba8\u8bba\u4e86\u5982\u4f55\u63a7\u5236\u8fd9\u79cd\u8f6c\u6362\u3002<\/p>\n<p>As well as HTML, you can see several C# statements in there. The advantage of being able to, for example, use a for loop rather than having to explicitly write out each <code>&lt;li&gt;<\/code> element should be self-evident. I\u2019ll dive a little deeper into more of the C# features of Razor in the next section. When rendered, the template in listing 17.2 produces the following HTML.<br \/>\n\u9664\u4e86 HTML\uff0c\u60a8\u8fd8\u53ef\u4ee5\u5728\u5176\u4e2d\u770b\u5230\u51e0\u4e2a C# \u8bed\u53e5\u3002\u4f8b\u5982\uff0c\u80fd\u591f\u4f7f\u7528 for \u5faa\u73af\u800c\u4e0d\u662f\u663e\u5f0f\u5199\u51fa\u6bcf\u4e2a<code>&lt;li&gt;<\/code> \u5143\u7d20\u5e94\u8be5\u662f\u4e0d\u8a00\u800c\u55bb\u7684\u3002\u5728\u4e0b\u4e00\u8282\u4e2d\uff0c\u6211\u5c06\u66f4\u6df1\u5165\u5730\u4ecb\u7ecd Razor \u7684\u66f4\u591a C# \u529f\u80fd\u3002\u5448\u73b0\u540e\uff0c\u6e05\u5355 17.2 \u4e2d\u7684\u6a21\u677f\u5c06\u751f\u6210\u4ee5\u4e0b HTML\u3002<\/p>\n<p>Listing 17.3 HTML output produced by rendering a Razor template<br \/>\n\u5217\u8868 17.3 \u901a\u8fc7\u5448\u73b0 Razor \u6a21\u677f\u751f\u6210\u7684 HTML \u8f93\u51fa<\/p>\n<pre><code>&lt;h1&gt;Tasks to complete&lt;\/h1&gt; \u2776\n&lt;ul&gt; \u2776\n&lt;li&gt;0 - Buy milk&lt;\/li&gt; \u2777\n&lt;li&gt;1 - Buy eggs&lt;\/li&gt; \u2777\n&lt;li&gt;2 - Buy bread&lt;\/li&gt; \u2777\n&lt;\/ul&gt;<\/code><\/pre>\n<p>\u2776 HTML from the Razor template is written directly to the output.<br \/>\nRazor \u6a21\u677f\u4e2d\u7684 HTML \u76f4\u63a5\u5199\u5165\u8f93\u51fa\u3002<br \/>\n\u2777 The <code>&lt;li&gt;<\/code> elements are generated dynamically by the for loop, based on the data provided.<br \/>\n\u8be5<code>&lt;li&gt;<\/code> \u5143\u7d20\u7531 for \u5faa\u73af\u6839\u636e\u63d0\u4f9b\u7684\u6570\u636e\u52a8\u6001\u751f\u6210\u3002<br \/>\n\u2778 HTML from the Razor template is written directly to the output.<br \/>\nRazor \u6a21\u677f\u4e2d\u7684 HTML \u76f4\u63a5\u5199\u5165\u8f93\u51fa\u3002<\/p>\n<p>As you can see, the final output of a Razor template after it\u2019s rendered is simple HTML. There\u2019s nothing complicated left, only straight HTML markup that can be sent to the browser and rendered. Figure 17.3 shows how a browser would render it.<br \/>\n\u5982\u4f60\u6240\u89c1\uff0cRazor \u6a21\u677f\u5728\u5448\u73b0\u540e\u7684\u6700\u7ec8\u8f93\u51fa\u662f\u7b80\u5355\u7684 HTML\u3002\u6ca1\u6709\u7559\u4e0b\u4efb\u4f55\u590d\u6742\u7684\u5185\u5bb9\uff0c\u53ea\u6709\u53ef\u4ee5\u76f4\u63a5\u53d1\u9001\u5230\u6d4f\u89c8\u5668\u5e76\u5448\u73b0\u7684 HTML \u6807\u8bb0\u3002\u56fe 17.3 \u663e\u793a\u4e86\u6d4f\u89c8\u5668\u5982\u4f55\u5448\u73b0\u5b83\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1703.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 17.3 Razor templates can be used to generate the HTML dynamically at runtime from C# objects. In this case, a for loop is used to create repetitive HTML <code>&lt;li&gt;<\/code> elements.<br \/>\n\u56fe 17.3 Razor \u6a21\u677f\u53ef\u7528\u4e8e\u5728\u8fd0\u884c\u65f6\u4ece C# \u5bf9\u8c61\u52a8\u6001\u751f\u6210 HTML\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f7f\u7528 for \u5faa\u73af\u521b\u5efa\u91cd\u590d\u7684 HTML<code>&lt;li&gt;<\/code> \u5143\u7d20\u3002<\/p>\n<p>In this example, I hardcoded the list values for simplicity; no dynamic data was provided. This is often the case on simple Razor Pages, like those you might have on your home page; you need to display an almost static page. For the rest of your application, it will be far more common to have some sort of data you need to display, typically exposed as properties on your PageModel.<br \/>\n\u5728\u6b64\u793a\u4f8b\u4e2d\uff0c\u4e3a\u7b80\u5355\u8d77\u89c1\uff0c\u6211\u5bf9\u5217\u8868\u503c\u8fdb\u884c\u4e86\u786c\u7f16\u7801;\u672a\u63d0\u4f9b\u52a8\u6001\u6570\u636e\u3002\u8fd9\u5728\u7b80\u5355\u7684 Razor \u9875\u9762\u4e0a\u901a\u5e38\u5c31\u662f\u8fd9\u79cd\u60c5\u51b5\uff0c\u5c31\u50cf\u4f60\u5728\u4e3b\u9875\u4e0a\u53ef\u80fd\u62e5\u6709\u7684\u90a3\u4e9b\u4e00\u6837;\u60a8\u9700\u8981\u663e\u793a\u4e00\u4e2a\u51e0\u4e4e\u9759\u6001\u7684\u9875\u9762\u3002\u5bf9\u4e8e\u5e94\u7528\u7a0b\u5e8f\u7684\u5176\u4f59\u90e8\u5206\uff0c\u9700\u8981\u663e\u793a\u67d0\u79cd\u7c7b\u578b\u7684\u6570\u636e\uff08\u901a\u5e38\u4f5c\u4e3a PageModel \u4e0a\u7684\u5c5e\u6027\u516c\u5f00\uff09\u5c06\u66f4\u52a0\u5e38\u89c1\u3002<\/p>\n<h3>17.2.3 Passing data to views<\/h3>\n<p>17.2.3 \u5c06\u6570\u636e\u4f20\u9012\u7ed9\u89c6\u56fe<\/p>\n<p>In ASP.NET Core, you have several ways of passing data from a page handler in a Razor Page to its view. Which approach is best depends on the data you\u2019re trying to pass through, but in general you should use the mechanisms in the following order:<br \/>\n\u5728 ASP.NET Core \u4e2d\uff0c\u53ef\u4ee5\u901a\u8fc7\u591a\u79cd\u65b9\u5f0f\u5c06\u6570\u636e\u4ece Razor \u9875\u9762\u4e2d\u7684\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u4f20\u9012\u5230\u5176\u89c6\u56fe\u3002\u54ea\u79cd\u65b9\u6cd5\u6700\u597d\u53d6\u51b3\u4e8e\u60a8\u5c1d\u8bd5\u4f20\u9012\u7684\u6570\u636e\uff0c\u4f46\u901a\u5e38\u5e94\u6309\u4ee5\u4e0b\u987a\u5e8f\u4f7f\u7528\u673a\u5236\uff1a<\/p>\n<p>\u2022  PageModel properties\u2014You should generally expose any data that needs to be displayed as properties on your PageModel. Any data that is specific to the associated Razor view should be exposed this way. The PageModel object is available in the view when it\u2019s rendered, as you\u2019ll see shortly.<br \/>\nPageModel \u5c5e\u6027 - \u901a\u5e38\u5e94\u516c\u5f00\u9700\u8981\u5728 PageModel \u4e0a\u663e\u793a\u4e3a\u5c5e\u6027\u7684\u4efb\u4f55\u6570\u636e\u3002\u7279\u5b9a\u4e8e\u5173\u8054 Razor \u89c6\u56fe\u7684\u4efb\u4f55\u6570\u636e\u90fd\u5e94\u4ee5\u8fd9\u79cd\u65b9\u5f0f\u516c\u5f00\u3002PageModel \u5bf9\u8c61\u5728\u5448\u73b0\u65f6\u5728\u89c6\u56fe\u4e2d\u53ef\u7528\uff0c\u60a8\u5f88\u5feb\u5c31\u4f1a\u770b\u5230\u3002<\/p>\n<p>\u2022  ViewData\u2014This is a dictionary of objects with string keys that can be used to pass arbitrary data from the page handler to the view. In addition, it allows you to pass data to layout files, as you\u2019ll see in section 17.4. Layout files are the main reason for using ViewData instead of setting properties on the PageModel.<br \/>\nViewData - \u8fd9\u662f\u5e26\u6709\u5b57\u7b26\u4e32\u952e\u7684\u5bf9\u8c61\u5b57\u5178\uff0c\u53ef\u7528\u4e8e\u5c06\u4efb\u610f\u6570\u636e\u4ece\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u4f20\u9012\u5230\u89c6\u56fe\u3002\u6b64\u5916\uff0c\u5b83\u8fd8\u5141\u8bb8\u60a8\u5c06\u6570\u636e\u4f20\u9012\u7ed9 layout \u6587\u4ef6\uff0c\u5982 Section 17.4 \u6240\u793a\u3002\u5e03\u5c40\u6587\u4ef6\u662f\u4f7f\u7528 ViewData \u800c\u4e0d\u662f\u5728 PageModel \u4e0a\u8bbe\u7f6e\u5c5e\u6027\u7684\u4e3b\u8981\u539f\u56e0\u3002<\/p>\n<p>\u2022  TempData\u2014TempData is a dictionary of objects with string keys, similar to ViewData, that is stored until it\u2019s read in a different request. This is commonly used to temporarily persist data when using the POST-REDIRECT-GET pattern. By default TempData stores the data in an encrypted cookie, but other storage options are available, as described in the documentation at <a href=\"http:\/\/mng.bz\/Wzx1\">http:\/\/mng.bz\/Wzx1<\/a>.<br \/>\nTempData - TempData \u662f\u5177\u6709\u5b57\u7b26\u4e32\u952e\u7684\u5bf9\u8c61\u5b57\u5178\uff0c\u7c7b\u4f3c\u4e8e ViewData\uff0c\u5728\u8bfb\u53d6\u5176\u4ed6\u8bf7\u6c42\u4e4b\u524d\u4f1a\u4e00\u76f4\u5b58\u50a8\u3002\u8fd9\u901a\u5e38\u7528\u4e8e\u5728\u4f7f\u7528 POST-REDIRECT-GET \u6a21\u5f0f\u65f6\u4e34\u65f6\u4fdd\u7559\u6570\u636e\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cTempData \u5c06\u6570\u636e\u5b58\u50a8\u5728\u52a0\u5bc6\u7684 Cookie \u4e2d\uff0c\u4f46\u4e5f\u63d0\u4f9b\u4e86\u5176\u4ed6\u5b58\u50a8\u9009\u9879\uff0c\u5982 <a href=\"http:\/\/mng.bz\/Wzx1\">http:\/\/mng.bz\/Wzx1<\/a> \u4e2d\u7684\u6587\u6863\u4e2d\u6240\u8ff0\u3002<\/p>\n<p>\u2022  HttpContext\u2014Technically, the HttpContext object is available in both the page handler and Razor view, so you could use it to transfer data between them. But don\u2019t\u2014there\u2019s no need for it with the other methods available to you.<br \/>\nHttpContext - \u4ece\u6280\u672f\u4e0a\u8bb2\uff0cHttpContext \u5bf9\u8c61\u5728\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u548c Razor \u89c6\u56fe\u4e2d\u5747\u53ef\u7528\uff0c\u56e0\u6b64\u60a8\u53ef\u4ee5\u4f7f\u7528\u5b83\u6765\u5728\u5b83\u4eec\u4e4b\u95f4\u4f20\u8f93\u6570\u636e\u3002\u4f46\u4e0d\u8981 - \u6ca1\u6709\u5fc5\u8981\u4f7f\u7528\u5176\u4ed6\u53ef\u7528\u7684\u65b9\u6cd5\u3002<\/p>\n<p>\u2022  @inject services\u2014You can use dependency injection (DI) to make services available in your views, though this should normally be used sparingly. Using the directive @inject Service myService injects a variable called myService of type Service from the DI container, which you can use in your Razor view.<br \/>\n@inject\u670d\u52a1 - \u60a8\u53ef\u4ee5\u4f7f\u7528\u4f9d\u8d56\u5173\u7cfb\u6ce8\u5165 \uff08DI\uff09 \u4f7f\u670d\u52a1\u5728\u89c6\u56fe\u4e2d\u53ef\u7528\uff0c\u4f46\u901a\u5e38\u5e94\u8c28\u614e\u4f7f\u7528\u3002\u4f7f\u7528\u6307\u4ee4 @inject Service myService \u4f1a\u4ece DI \u5bb9\u5668\u4e2d\u6ce8\u5165\u4e00\u4e2a\u540d\u4e3a myService \u7684 Service \u7c7b\u578b\u53d8\u91cf\uff0c\u60a8\u53ef\u4ee5\u5728 Razor \u89c6\u56fe\u4e2d\u4f7f\u7528\u8be5\u53d8\u91cf\u3002<\/p>\n<p>Far and away the best approach for passing data from a page handler to a view is to use properties on the PageModel. There\u2019s nothing special about the properties themselves; you can store anything there to hold the data you require.<br \/>\n\u5c06\u6570\u636e\u4ece\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u4f20\u9012\u5230\u89c6\u56fe\u7684\u6700\u4f73\u65b9\u6cd5\u65e0\u7591\u662f\u4f7f\u7528 PageModel \u4e0a\u7684\u5c5e\u6027\u3002\u5c5e\u6027\u672c\u8eab\u5e76\u6ca1\u6709\u4ec0\u4e48\u7279\u522b\u4e4b\u5904;\u60a8\u53ef\u4ee5\u5728\u90a3\u91cc\u5b58\u50a8\u4efb\u4f55\u5185\u5bb9\u6765\u4fdd\u5b58\u60a8\u9700\u8981\u7684\u6570\u636e\u3002<\/p>\n<p><b>NOTE<\/b> Many frameworks have the concept of a data context for binding UI components. The PageModel is a similar concept, in that it contains values to display in the UI, but the binding is one-directional; the PageModel provides values to the UI, and once the UI is built and sent as a response, the PageModel is destroyed.<br \/>\n\u6ce8\u610f:\u8bb8\u591a\u6846\u67b6\u5177\u6709\u7528\u4e8e\u7ed1\u5b9a UI \u7ec4\u4ef6\u7684\u6570\u636e\u4e0a\u4e0b\u6587\u7684\u6982\u5ff5\u3002PageModel \u662f\u4e00\u4e2a\u7c7b\u4f3c\u7684\u6982\u5ff5\uff0c\u56e0\u4e3a\u5b83\u5305\u542b\u8981\u5728 UI \u4e2d\u663e\u793a\u7684\u503c\uff0c\u4f46\u7ed1\u5b9a\u662f\u5355\u5411\u7684;PageModel \u5411 UI \u63d0\u4f9b\u503c\uff0c\u4e00\u65e6\u6784\u5efa\u4e86 UI \u5e76\u5c06\u5176\u4f5c\u4e3a\u54cd\u5e94\u53d1\u9001\uff0cPageModel \u5c31\u4f1a\u88ab\u9500\u6bc1\u3002<\/p>\n<p>As I described in section 17.2.1, the @model directive at the top of your Razor view describes which Type of PageModel is associated with a given Razor Page. The PageModel associated with a Razor Page contains one or more page handlers and exposes data as properties for use in the Razor view, as shown in the following listing.<br \/>\n\u5982\u7b2c 17.2.1 \u8282\u6240\u8ff0\uff0cRazor \u89c6\u56fe\u9876\u90e8\u7684 @model \u6307\u4ee4\u63cf\u8ff0\u4e86\u4e0e\u7ed9\u5b9a Razor \u9875\u9762\u5173\u8054\u7684 PageModel \u7c7b\u578b\u3002\u4e0e Razor \u9875\u9762\u5173\u8054\u7684 PageModel \u5305\u542b\u4e00\u4e2a\u6216\u591a\u4e2a\u9875\u9762\u5904\u7406\u7a0b\u5e8f\uff0c\u5e76\u5c06\u6570\u636e\u516c\u5f00\u4e3a\u5c5e\u6027\uff0c\u4ee5\u4fbf\u5728 Razor \u89c6\u56fe\u4e2d\u4f7f\u7528\uff0c\u5982\u4e0b\u9762\u7684\u6e05\u5355\u6240\u793a\u3002<\/p>\n<p>Listing 17.4 Exposing data as properties on a PageModel<br \/>\n\u6e05\u5355 17.4 \u5c06\u6570\u636e\u4f5c\u4e3a PageModel \u4e0a\u7684\u5c5e\u6027\u516c\u5f00<\/p>\n<pre><code>public class ToDoItemModel : PageModel \u2776\n{\npublic List&lt;string&gt; Tasks { get; set; } \u2777\npublic string Title { get; set; } \u2777\npublic void OnGet(int id)\n{\nTitle = &quot;Tasks for today&quot;; \u2778\nTasks = new List&lt;string&gt; \u2778\n{ \u2778\n&quot;Get fuel&quot;, \u2778\n&quot;Check oil&quot;, \u2778\n&quot;Check tyre pressure&quot; \u2778\n}; \u2778\n}\n}<\/code><\/pre>\n<p>\u2776 The PageModel is passed to the Razor view when it executes.<br \/>\nPageModel \u5728\u6267\u884c\u65f6\u4f20\u9012\u5230 Razor \u89c6\u56fe\u3002<br \/>\n\u2777 The public properties can be accessed from the Razor view.<br \/>\n\u53ef\u4ee5\u4ece Razor \u89c6\u56fe\u8bbf\u95ee\u516c\u5171\u5c5e\u6027\u3002<br \/>\n\u2778 Building the required data: this would normally call out to a service or database to load the data.<br \/>\n\u6784\u5efa\u6240\u9700\u7684\u6570\u636e\uff1a\u8fd9\u901a\u5e38\u4f1a\u8c03\u7528\u670d\u52a1\u6216\u6570\u636e\u5e93\u6765\u52a0\u8f7d\u6570\u636e\u3002<\/p>\n<p>You can access the PageModel instance itself from the Razor view using the Model property. For example, to display the Title property of the ToDoItemModel in the Razor view, you\u2019d use <code>&lt;h1&gt;@Model.Title&lt;\/h1&gt;<\/code>. This would render the string provided in the ToDoItemModel.Title property, producing the <code>&lt;h1&gt;Tasks for today&lt;\/h1&gt;<\/code> HTML.<br \/>\n\u53ef\u4ee5\u4f7f\u7528 Model \u5c5e\u6027\u4ece Razor \u89c6\u56fe\u8bbf\u95ee PageModel \u5b9e\u4f8b\u672c\u8eab\u3002\u4f8b\u5982\uff0c\u8981\u5728 Razor \u89c6\u56fe\u4e2d\u663e\u793a ToDoItemModel \u7684 Title \u5c5e\u6027\uff0c\u8bf7\u4f7f\u7528 <code>&lt;h1&gt;@Model.Title&lt;\/h1&gt;<\/code>.\u8fd9\u5c06\u5448\u73b0 ToDoItemModel.Title \u5c5e\u6027\u4e2d\u63d0\u4f9b\u7684\u5b57\u7b26\u4e32\uff0c\u4ece\u800c\u751f\u6210 HTML <code>&lt;h1&gt;Tasks for today&lt;\/h1&gt;<\/code>\u3002<\/p>\n<p><b>Tip<\/b> Note that the @model directive should be at the top of your view, immediately after the @page directive, and it has a lowercase m. The Model property can be accessed anywhere in the view and has an uppercase M.<br \/>\n\u63d0\u793a:\u8bf7\u6ce8\u610f\uff0c@model \u6307\u4ee4\u5e94\u4f4d\u4e8e\u89c6\u56fe\u9876\u90e8\uff0c\u7d27\u8ddf\u5728 @page \u6307\u4ee4\u4e4b\u540e\uff0c\u5e76\u4e14\u5b83\u6709\u4e00\u4e2a\u5c0f\u5199\u7684 m\u3002Model \u5c5e\u6027\u53ef\u4ee5\u5728\u89c6\u56fe\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u8bbf\u95ee\uff0c\u5e76\u4e14\u5177\u6709\u5927\u5199\u7684 M\u3002<\/p>\n<p>In most cases, using public properties on your PageModel is the way to go; it\u2019s the standard mechanism for passing data between the page handler and the view. But in some circumstances, properties on your PageModel might not be the best fit. This is often the case when you want to pass data between view layouts. You\u2019ll see how this works in section 17.4.<br \/>\n\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u5728 PageModel \u4e0a\u4f7f\u7528\u516c\u5171\u5c5e\u6027\u662f\u53ef\u884c\u7684\u65b9\u6cd5;\u5b83\u662f\u5728 Page \u5904\u7406\u7a0b\u5e8f\u548c View \u4e4b\u95f4\u4f20\u9012\u6570\u636e\u7684\u6807\u51c6\u673a\u5236\u3002\u4f46\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0cPageModel \u4e0a\u7684\u5c5e\u6027\u53ef\u80fd\u4e0d\u662f\u6700\u5408\u9002\u7684\u3002\u5f53\u60a8\u60f3\u5728\u89c6\u56fe\u5e03\u5c40\u4e4b\u95f4\u4f20\u9012\u6570\u636e\u65f6\uff0c\u901a\u5e38\u4f1a\u51fa\u73b0\u8fd9\u79cd\u60c5\u51b5\u3002\u60a8\u5c06\u5728 Section 17.4 \u4e2d\u770b\u5230\u5b83\u662f\u5982\u4f55\u5de5\u4f5c\u7684\u3002<\/p>\n<p>A common example is the title of the page. You need to provide a title for every page in your application, so you could create a base class with a Title property and make every PageModel inherit from it. But that\u2019s cumbersome, so a common approach for this situation is to use the ViewData collection to pass data around.<br \/>\n\u4e00\u4e2a\u5e38\u89c1\u7684\u793a\u4f8b\u662f\u9875\u9762\u7684\u6807\u9898\u3002\u60a8\u9700\u8981\u4e3a\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u6bcf\u4e2a\u9875\u9762\u63d0\u4f9b\u4e00\u4e2a\u6807\u9898\uff0c\u4ee5\u4fbf\u60a8\u53ef\u4ee5\u521b\u5efa\u4e00\u4e2a\u5177\u6709 Title \u5c5e\u6027\u7684\u57fa\u7c7b\uff0c\u5e76\u4f7f\u6bcf\u4e2a PageModel \u90fd\u7ee7\u627f\u81ea\u8be5\u57fa\u7c7b\u3002\u4f46\u8fd9\u5f88\u9ebb\u70e6\uff0c\u56e0\u6b64\u8fd9\u79cd\u60c5\u51b5\u7684\u5e38\u89c1\u65b9\u6cd5\u662f\u4f7f\u7528 ViewData \u96c6\u5408\u6765\u4f20\u9012\u6570\u636e\u3002<\/p>\n<p>In fact, the standard Razor Page templates use this approach by default, by setting values on the ViewData dictionary from within the view itself:<br \/>\n\u4e8b\u5b9e\u4e0a\uff0c\u6807\u51c6 Razor \u9875\u9762\u6a21\u677f\u9ed8\u8ba4\u4f7f\u7528\u6b64\u65b9\u6cd5\uff0c\u65b9\u6cd5\u662f\u4ece\u89c6\u56fe\u672c\u8eab\u4e2d\u8bbe\u7f6e ViewData \u5b57\u5178\u7684\u503c\uff1a<\/p>\n<pre><code>@{\n    ViewData[&quot;Title&quot;] = &quot;Home Page&quot;;\n}\n&lt;h2&gt;@ViewData[&quot;Title&quot;].&lt;\/h2&gt;<\/code><\/pre>\n<p>This template sets the value of the &quot;Title&quot; key in the ViewData dictionary to &quot;Home Page&quot; and then fetches the key to render in the template. This set and immediate fetch might seem superfluous, but as the ViewData dictionary is shared throughout the request, it makes the title of the page available in layouts, as you\u2019ll see later. When rendered, the preceding template would produce the following output:<br \/>\n\u6b64\u6a21\u677f\u5c06 ViewData \u5b57\u5178\u4e2d \u201cTitle\u201d \u952e\u7684\u503c\u8bbe\u7f6e\u4e3a \u201cHome Page\u201d\uff0c\u7136\u540e\u83b7\u53d6\u8981\u5728\u6a21\u677f\u4e2d\u5448\u73b0\u7684\u952e\u3002\u8fd9\u79cd set \u548c immediate fetch \u53ef\u80fd\u770b\u8d77\u6765\u662f\u591a\u4f59\u7684\uff0c\u4f46\u662f\u7531\u4e8e ViewData \u5b57\u5178\u5728\u6574\u4e2a\u8bf7\u6c42\u4e2d\u662f\u5171\u4eab\u7684\uff0c\u56e0\u6b64\u5b83\u4f7f\u9875\u9762\u7684\u6807\u9898\u5728\u5e03\u5c40\u4e2d\u53ef\u7528\uff0c\u60a8\u7a0d\u540e\u5c06\u770b\u5230\u3002\u6e32\u67d3\u65f6\uff0c\u524d\u9762\u7684\u6a21\u677f\u5c06\u751f\u6210\u4ee5\u4e0b\u8f93\u51fa\uff1a<\/p>\n<pre><code>&lt;h2&gt;Home Page.&lt;\/h2&gt;<\/code><\/pre>\n<p>You can also set values in the ViewData dictionary from your page handlers in two different ways, as shown in the following listing.<br \/>\n\u60a8\u8fd8\u53ef\u4ee5\u901a\u8fc7\u4e24\u79cd\u4e0d\u540c\u7684\u65b9\u5f0f\u4ece\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u4e2d\u8bbe\u7f6e ViewData \u5b57\u5178\u4e2d\u7684\u503c\uff0c\u5982\u4e0b\u9762\u7684\u6e05\u5355\u6240\u793a\u3002<\/p>\n<p>Listing 17.5 Setting ViewData values using an attribute<br \/>\n\u793a\u4f8b 17.5 \u4f7f\u7528\u5c5e\u6027\u8bbe\u7f6e ViewData \u503c<\/p>\n<pre><code>public class IndexModel: PageModel\n{\n    [ViewData]                        #A\n    public string Title { get; set; }\n\n    public void OnGet()\n    {\n        Title = &quot;Home Page&quot;;             #B\n        ViewData[&quot;Subtitle&quot;] = &quot;Welcome&quot;;     #C\n    }\n}<\/code><\/pre>\n<p>You can display the values in the template in the same way as before:<br \/>\n\u60a8\u53ef\u4ee5\u50cf\u4ee5\u524d\u4e00\u6837\u5728\u6a21\u677f\u4e2d\u663e\u793a\u503c\uff1a<\/p>\n<pre><code>&lt;h1&gt;@ViewData[&quot;Title&quot;]&lt;\/h3&gt;\n&lt;h2&gt;@ViewData[&quot;Subtitle&quot;]&lt;\/h3&gt;<\/code><\/pre>\n<p><b>Tip<\/b> I don\u2019t find the [ViewData] attribute especially useful, but it\u2019s another feature to look out for. Instead, I create a set of global, static constants for any ViewData keys, and I reference those instead of typing &quot;Title&quot; repeatedly. You\u2019ll get IntelliSense for the values, they\u2019re refactor-safe, and you\u2019ll avoid hard-to-spot typos.<br \/>\n\u63d0\u793a:\u6211\u4e0d\u89c9\u5f97 [ViewData] \u5c5e\u6027\u7279\u522b\u6709\u7528\uff0c\u4f46\u5b83\u662f\u53e6\u4e00\u4e2a\u9700\u8981\u6ce8\u610f\u7684\u529f\u80fd\u3002\u76f8\u53cd\uff0c\u6211\u4e3a\u4efb\u4f55 ViewData \u952e\u521b\u5efa\u4e00\u7ec4\u5168\u5c40\u9759\u6001\u5e38\u91cf\uff0c\u5e76\u5f15\u7528\u8fd9\u4e9b\u5e38\u91cf\uff0c\u800c\u4e0d\u662f\u91cd\u590d\u952e\u5165\u201cTitle\u201d\u3002\u60a8\u5c06\u83b7\u5f97\u503c\u7684 IntelliSense\uff0c\u5b83\u4eec\u662f\u91cd\u6784\u5b89\u5168\u7684\uff0c\u5e76\u4e14\u60a8\u5c06\u907f\u514d\u96be\u4ee5\u53d1\u73b0\u7684\u62fc\u5199\u9519\u8bef\u3002<\/p>\n<p>As I mentioned previously, there are mechanisms besides PageModel properties and ViewData that you can use to pass data around, but these two are the only ones I use personally, as you can do everything you need with them. As a reminder, always use PageModel properties where possible, as you benefit from strong typing and IntelliSense. Only fall back to ViewData for values that need to be accessed outside of your Razor view.<br \/>\n\u6b63\u5982\u6211\u524d\u9762\u63d0\u5230\u7684\uff0c\u9664\u4e86 PageModel \u5c5e\u6027\u548c ViewData \u4e4b\u5916\uff0c\u8fd8\u6709\u4e00\u4e9b\u673a\u5236\u53ef\u7528\u4e8e\u4f20\u9012\u6570\u636e\uff0c\u4f46\u8fd9\u4e24\u79cd\u673a\u5236\u662f\u6211\u4e2a\u4eba\u552f\u4e00\u4f7f\u7528\u7684\u673a\u5236\uff0c\u56e0\u4e3a\u60a8\u53ef\u4ee5\u4f7f\u7528\u5b83\u4eec\u6267\u884c\u4efb\u4f55\u9700\u8981\u7684\u4f5c\u3002\u63d0\u9192\u4e00\u4e0b\uff0c\u8bf7\u5c3d\u53ef\u80fd\u4f7f\u7528 PageModel \u5c5e\u6027\uff0c\u56e0\u4e3a\u5f3a\u7c7b\u578b\u5316\u548c IntelliSense \u4f1a\u8ba9\u60a8\u53d7\u76ca\u3002\u5bf9\u4e8e\u9700\u8981\u5728 Razor \u89c6\u56fe\u4e4b\u5916\u8bbf\u95ee\u7684\u503c\uff0c\u8bf7\u4ec5\u56de\u9000\u5230 ViewData\u3002<\/p>\n<p>You\u2019ve had a small taste of the power available to you in Razor templates, but in the next section we\u2019ll dive a little deeper into some of the available C# capabilities.<br \/>\n\u60a8\u5df2\u7ecf\u5bf9 Razor \u6a21\u677f\u4e2d\u53ef\u7528\u7684\u529f\u80fd\u6709\u4e86\u4e00\u4e9b\u4e86\u89e3\uff0c\u4f46\u5728\u4e0b\u4e00\u8282\u4e2d\uff0c\u6211\u4eec\u5c06\u66f4\u6df1\u5165\u5730\u4ecb\u7ecd\u4e00\u4e9b\u53ef\u7528\u7684 C# \u529f\u80fd\u3002<\/p>\n<h2>17.3 Creating dynamic web pages with Razor<\/h2>\n<p>17.3 \u4f7f\u7528 Razor \u521b\u5efa\u52a8\u6001\u7f51\u9875<\/p>\n<p>You might be glad to know that pretty much anything you can do in C# is possible in Razor syntax. Under the covers, the .cshtml files are compiled into normal C# code (with string for the raw HTML sections), so whatever weird and wonderful behavior you need can be created!<br \/>\n\u60a8\u53ef\u80fd\u5f88\u9ad8\u5174\u5730\u77e5\u9053\uff0c\u5728 C# \u4e2d\u53ef\u4ee5\u6267\u884c\u7684\u51e0\u4e4e\u4efb\u4f55\u4e8b\u60c5\u90fd\u53ef\u4ee5\u5728 Razor \u8bed\u6cd5\u4e2d\u5b8c\u6210\u3002\u5728\u540e\u53f0\uff0c.cshtml \u6587\u4ef6\u88ab\u7f16\u8bd1\u6210\u666e\u901a\u7684 C# \u4ee3\u7801\uff08\u539f\u59cb HTML \u90e8\u5206\u5e26\u6709\u5b57\u7b26\u4e32\uff09\uff0c\u56e0\u6b64\u4f60\u53ef\u4ee5\u521b\u5efa\u4f60\u9700\u8981\u7684\u4efb\u4f55\u5947\u602a\u800c\u7f8e\u5999\u7684\u884c\u4e3a\uff01<\/p>\n<p>Having said that, just because you can do something doesn\u2019t mean you should. You\u2019ll find it much easier to work with, and maintain, your files if you keep them as simple as possible. This is true of pretty much all programming, but I find it to be especially so with Razor templates.<br \/>\n\u8bdd\u867d\u5982\u6b64\uff0c\u4ec5\u4ec5\u56e0\u4e3a\u60a8\u53ef\u4ee5\u505a\u67d0\u4e8b\u5e76\u4e0d\u610f\u5473\u7740\u60a8\u5e94\u8be5\u8fd9\u6837\u505a\u3002\u60a8\u4f1a\u53d1\u73b0\uff0c\u5982\u679c\u60a8\u5c3d\u53ef\u80fd\u7b80\u5316\u6587\u4ef6\uff0c\u90a3\u4e48\u5904\u7406\u548c\u7ef4\u62a4\u6587\u4ef6\u4f1a\u5bb9\u6613\u5f97\u591a\u3002\u51e0\u4e4e\u6240\u6709\u7f16\u7a0b\u90fd\u662f\u5982\u6b64\uff0c\u4f46\u6211\u53d1\u73b0 Razor \u6a21\u677f\u5c24\u5176\u5982\u6b64\u3002<\/p>\n<p>This section covers some of the more common C# constructs you can use. If you find you need to achieve something a bit more exotic, refer to the Razor syntax documentation at <a href=\"http:\/\/mng.bz\/8rMw\">http:\/\/mng.bz\/8rMw<\/a>.<br \/>\n\u672c\u90e8\u5206\u4ecb\u7ecd\u4e00\u4e9b\u53ef\u4ee5\u4f7f\u7528\u7684\u66f4\u5e38\u89c1\u7684 C# \u6784\u9020\u3002\u5982\u679c\u60a8\u53d1\u73b0\u9700\u8981\u5b9e\u73b0\u4e00\u4e9b\u66f4\u5947\u7279\u7684\u4e1c\u897f\uff0c\u8bf7\u53c2\u9605 <a href=\"http:\/\/mng.bz\/8rMw\">http:\/\/mng.bz\/8rMw<\/a> \u4e0a\u7684 Razor \u8bed\u6cd5\u6587\u6863\u3002<\/p>\n<h3>17.3.1 Using C# in Razor templates<\/h3>\n<p>17.3.1 \u5728 Razor \u6a21\u677f\u4e2d\u4f7f\u7528 C#<\/p>\n<p>One of the most common requirements when working with Razor templates is to render a value you\u2019ve calculated in C# to the HTML. For example, you might want to print the current year to use with a copyright statement in your HTML, to give this result:<br \/>\n\u4f7f\u7528 Razor \u6a21\u677f\u65f6\uff0c\u6700\u5e38\u89c1\u7684\u8981\u6c42\u4e4b\u4e00\u662f\u5c06\u60a8\u5728 C# \u4e2d\u8ba1\u7b97\u7684\u503c\u5448\u73b0\u5230 HTML\u3002\u4f8b\u5982\uff0c\u60a8\u53ef\u80fd\u5e0c\u671b\u6253\u5370\u5f53\u524d\u5e74\u4efd\u4ee5\u4e0e HTML \u4e2d\u7684\u7248\u6743\u58f0\u660e\u4e00\u8d77\u4f7f\u7528\uff0c\u4ee5\u5f97\u5230\u4ee5\u4e0b\u7ed3\u679c\uff1a<\/p>\n<pre><code>&lt;p&gt;Copyright 2022 \u00a9&lt;\/p&gt;<\/code><\/pre>\n<p>Or you might want to print the result of a calculation:<br \/>\n\u6216\u8005\u60a8\u53ef\u80fd\u5e0c\u671b\u6253\u5370\u8ba1\u7b97\u7ed3\u679c\uff1a<\/p>\n<pre><code>&lt;p&gt;The sum of 1 and 2 is &lt;i&gt;3&lt;\/i&gt;&lt;p&gt;<\/code><\/pre>\n<p>You can do this in two ways, depending on the exact C# code you need to execute. If the code is a single statement, you can use the @ symbol to indicate you want to write the result to the HTML output, as shown in figure 17.4. You\u2019ve already seen this used to write out values from the PageModel or from ViewData.<br \/>\n\u60a8\u53ef\u4ee5\u901a\u8fc7\u4e24\u79cd\u65b9\u5f0f\u6267\u884c\u6b64\u4f5c\uff0c\u5177\u4f53\u53d6\u51b3\u4e8e\u60a8\u9700\u8981\u6267\u884c\u7684\u786e\u5207 C# \u4ee3\u7801\u3002\u5982\u679c\u4ee3\u7801\u662f\u5355\u4e2a\u8bed\u53e5\uff0c\u5219\u53ef\u4ee5\u4f7f\u7528 @ \u7b26\u53f7\u6765\u6307\u793a\u8981\u5c06\u7ed3\u679c\u5199\u5165 HTML \u8f93\u51fa\uff0c\u5982\u56fe 17.4 \u6240\u793a\u3002\u60a8\u5df2\u7ecf\u770b\u5230\u5b83\u7528\u4e8e\u4ece PageModel \u6216 ViewData \u4e2d\u5199\u51fa\u503c\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1704.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 17.4 Writing the result of a C# expression to HTML. The @ symbol indicates where the C# code begins, and the expression ends at the end of the statement, in this case at the space.<br \/>\n\u56fe 17.4 \u5c06 C# \u8868\u8fbe\u5f0f\u7684\u7ed3\u679c\u5199\u5165 HTML\u3002@ \u7b26\u53f7\u6307\u793a C# \u4ee3\u7801\u7684\u5f00\u59cb\u4f4d\u7f6e\uff0c\u8868\u8fbe\u5f0f\u5728\u8bed\u53e5\u7684\u672b\u5c3e\u7ed3\u675f\uff0c\u5728\u672c\u4f8b\u4e2d\u5728\u7a7a\u683c\u5904\u3002<\/p>\n<p>If the C# you want to execute is something that needs a space, you need to use parentheses to demarcate the C#, as shown in figure 17.5.<br \/>\n\u5982\u679c\u8981\u6267\u884c\u7684 C# \u9700\u8981\u7a7a\u683c\uff0c\u5219\u9700\u8981\u4f7f\u7528\u62ec\u53f7\u6765\u5206\u9694 C#\uff0c\u5982\u56fe 17.5 \u6240\u793a\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1705.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 17.5 When a C# expression contains whitespace, you must wrap it in parentheses using @() so the Razor engine knows where the C# stops and HTML begins.<br \/>\n\u56fe 17.5 \u5f53 C# \u8868\u8fbe\u5f0f\u5305\u542b\u7a7a\u683c\u65f6\uff0c\u5fc5\u987b\u4f7f\u7528 @\uff08\uff09 \u5c06\u5176\u62ec\u5728\u62ec\u53f7\u4e2d\uff0c\u4ee5\u4fbf Razor \u5f15\u64ce\u77e5\u9053 C# \u505c\u6b62\u548c HTML \u5f00\u59cb\u7684\u4f4d\u7f6e\u3002<\/p>\n<p>These two approaches, in which C# is evaluated and written directly to the HTML output, are called Razor expressions.<br \/>\n\u8fd9\u4e24\u79cd\u65b9\u6cd5\uff08\u5176\u4e2d C# \u88ab\u8ba1\u7b97\u5e76\u76f4\u63a5\u5199\u5165 HTML \u8f93\u51fa\uff09\u79f0\u4e3a Razor \u8868\u8fbe\u5f0f\u3002<\/p>\n<p><b>Tip<\/b> If you want to write a literal @ character rather than a C# expression, use a second @ character: @@.<br \/>\n\u63d0\u793a:\u5982\u679c\u8981\u7f16\u5199\u6587\u672c @ \u5b57\u7b26\u800c\u4e0d\u662f C# \u8868\u8fbe\u5f0f\uff0c\u8bf7\u4f7f\u7528\u7b2c\u4e8c\u4e2a @ \u5b57\u7b26\uff1a@@\u3002<\/p>\n<p>Sometimes you\u2019ll want to execute some C#, but you don\u2019t need to output the values. We used this technique when we were setting values in ViewData:<br \/>\n\u6709\u65f6\uff0c\u60a8\u9700\u8981\u6267\u884c\u4e00\u4e9b C#\uff0c\u4f46\u4e0d\u9700\u8981\u8f93\u51fa\u503c\u3002\u6211\u4eec\u5728 ViewData \u4e2d\u8bbe\u7f6e\u503c\u65f6\u4f7f\u7528\u4e86\u8fd9\u79cd\u6280\u672f\uff1a<\/p>\n<pre><code>@{\n    ViewData[&quot;Title&quot;] = &quot;Home Page&quot;;\n}<\/code><\/pre>\n<p>This example demonstrates a Razor code block, which is normal C# code, identified by the @{} structure. Nothing is written to the HTML output here; it\u2019s all compiled as though you\u2019d written it in any other normal C# file.<br \/>\n\u6b64\u793a\u4f8b\u6f14\u793a Razor \u4ee3\u7801\u5757\uff0c\u8fd9\u662f\u7531 @{} \u7ed3\u6784\u6807\u8bc6\u7684\u666e\u901a C# \u4ee3\u7801\u3002\u6b64\u5904\u7684 HTML \u8f93\u51fa\u4e0d\u4f1a\u5199\u5165\u4efb\u4f55\u5185\u5bb9;\u5b83\u5168\u90e8\u7f16\u8bd1\uff0c\u5c31\u50cf\u60a8\u7528\u4efb\u4f55\u5176\u4ed6\u666e\u901a\u7684 C# \u6587\u4ef6\u7f16\u5199\u5b83\u4e00\u6837\u3002<\/p>\n<p><b>Tip<\/b> When you execute code within code blocks, it must be valid C#, so you need to add semicolons. Conversely, when you\u2019re writing values directly to the response using Razor expressions, you don\u2019t need them. If your output HTML breaks unexpectedly, keep an eye out for missing or rogue extra semicolons.<br \/>\n\u63d0\u793a:\u5728\u4ee3\u7801\u5757\u4e2d\u6267\u884c\u4ee3\u7801\u65f6\uff0c\u5b83\u5fc5\u987b\u662f\u6709\u6548\u7684 C#\uff0c\u56e0\u6b64\u9700\u8981\u6dfb\u52a0\u5206\u53f7\u3002\u76f8\u53cd\uff0c\u5f53\u60a8\u4f7f\u7528 Razor \u8868\u8fbe\u5f0f\u5c06\u503c\u76f4\u63a5\u5199\u5165\u54cd\u5e94\u65f6\uff0c\u60a8\u4e0d\u9700\u8981\u5b83\u4eec\u3002\u5982\u679c\u8f93\u51fa HTML \u610f\u5916\u4e2d\u65ad\uff0c\u8bf7\u7559\u610f\u7f3a\u5931\u6216\u6d41\u6c13\u7684\u989d\u5916\u5206\u53f7\u3002<\/p>\n<p>Razor expressions are one of the most common ways of writing data from your PageModel to the HTML output. You\u2019ll see the other approach, using Tag Helpers, in the next chapter. Razor\u2019s capabilities extend far further than this, however, as you\u2019ll see in section 17.3.2, where you\u2019ll learn how to include traditional C# structures in your templates.<br \/>\nRazor \u8868\u8fbe\u5f0f\u662f\u5c06\u6570\u636e\u4ece PageModel \u5199\u5165 HTML \u8f93\u51fa\u7684\u6700\u5e38\u7528\u65b9\u6cd5\u4e4b\u4e00\u3002\u60a8\u5c06\u5728\u4e0b\u4e00\u7ae0\u4e2d\u770b\u5230\u53e6\u4e00\u79cd\u65b9\u6cd5\uff0c\u5373\u4f7f\u7528 Tag Helpers\u3002\u4f46\u662f\uff0cRazor \u7684\u529f\u80fd\u8fdc\u4e0d\u6b62\u4e8e\u6b64\uff0c\u5982\u7b2c 17.3.2 \u8282\u6240\u793a\uff0c\u60a8\u5c06\u5728\u5176\u4e2d\u5b66\u4e60\u5982\u4f55\u5728\u6a21\u677f\u4e2d\u5305\u542b\u4f20\u7edf\u7684 C# \u7ed3\u6784\u3002<\/p>\n<h3>17.3.2 Adding loops and conditionals to Razor templates<\/h3>\n<p>17.3.2 \u5411 Razor \u6a21\u677f\u6dfb\u52a0\u5faa\u73af\u548c\u6761\u4ef6\u8bed\u53e5<\/p>\n<p>One of the biggest advantages of using Razor templates over static HTML is the ability to generate the output dynamically. Being able to write values from your PageModel to the HTML using Razor expressions is a key part of that, but another common use is loops and conditionals. With these, you can hide sections of the UI, or produce HTML for every item in a list, for example.<br \/>\n\u4e0e\u9759\u6001 HTML \u76f8\u6bd4\uff0c\u4f7f\u7528 Razor \u6a21\u677f\u7684\u6700\u5927\u4f18\u52bf\u4e4b\u4e00\u662f\u80fd\u591f\u52a8\u6001\u751f\u6210\u8f93\u51fa\u3002\u80fd\u591f\u4f7f\u7528 Razor \u8868\u8fbe\u5f0f\u5c06\u503c\u4ece PageModel \u5199\u5165 HTML \u662f\u5176\u4e2d\u7684\u5173\u952e\u90e8\u5206\uff0c\u4f46\u53e6\u4e00\u4e2a\u5e38\u89c1\u7528\u9014\u662f\u5faa\u73af\u548c\u6761\u4ef6\u3002\u4f8b\u5982\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528\u8fd9\u4e9b\u529f\u80fd\u9690\u85cf UI \u7684\u5404\u4e2a\u90e8\u5206\uff0c\u6216\u8005\u4e3a\u5217\u8868\u4e2d\u7684\u6bcf\u4e2a\u9879\u76ee\u751f\u6210 HTML\u3002<\/p>\n<p>Loops and conditionals include constructs such as if and for loops. Using them in Razor templates is almost identical to C#, but you need to prefix their usage with the @ symbol. In case you\u2019re not getting the hang of Razor yet, when in doubt, throw in another @!<br \/>\n\u5faa\u73af\u548c\u6761\u4ef6\u5305\u62ec\u8bf8\u5982 if \u548c for \u5faa\u73af\u4e4b\u7c7b\u7684\u7ed3\u6784\u3002\u5728 Razor \u6a21\u677f\u4e2d\u4f7f\u7528\u5b83\u4eec\u4e0e C# \u51e0\u4e4e\u76f8\u540c\uff0c\u4f46\u60a8\u9700\u8981\u5728\u5b83\u4eec\u7684\u7528\u6cd5\u524d\u9762\u52a0\u4e0a @ \u7b26\u53f7\u3002\u5982\u679c\u60a8\u8fd8\u6ca1\u6709\u638c\u63e1 Razor \u7684\u7a8d\u95e8\uff0c\u5982\u6709\u7591\u95ee\uff0c\u8bf7\u518d\u8f93\u5165\u4e00\u4e2a @\uff01<\/p>\n<p>One of the big advantages of Razor in the context of ASP.NET Core is that it uses languages you\u2019re already familiar with: C# and HTML. There\u2019s no need to learn a whole new set of primitives for some other templating language: it\u2019s the same if, foreach, and while constructs you already know. And when you don\u2019t need them, you\u2019re writing raw HTML, so you can see exactly what the user is getting in their browser.<br \/>\nRazor \u5728 ASP.NET Core \u4e0a\u4e0b\u6587\u4e2d\u7684\u4e00\u5927\u4f18\u52bf\u662f\u5b83\u4f7f\u7528\u60a8\u5df2\u7ecf\u719f\u6089\u7684\u8bed\u8a00\uff1aC# \u548c HTML\u3002\u6ca1\u6709\u5fc5\u8981\u4e3a\u5176\u4ed6\u6a21\u677f\u8bed\u8a00\u5b66\u4e60\u4e00\u6574\u5957\u65b0\u7684\u539f\u8bed\uff1a\u5b83\u4e0e\u4f60\u5df2\u7ecf\u77e5\u9053\u7684 if\u3001foreach \u548c while \u7ed3\u6784\u76f8\u540c\u3002\u5f53\u60a8\u4e0d\u9700\u8981\u5b83\u4eec\u65f6\uff0c\u60a8\u6b63\u5728\u7f16\u5199\u539f\u59cb HTML\uff0c\u56e0\u6b64\u60a8\u53ef\u4ee5\u51c6\u786e\u5730\u770b\u5230\u7528\u6237\u5728\u6d4f\u89c8\u5668\u4e2d\u83b7\u5f97\u7684\u5185\u5bb9\u3002<\/p>\n<p>In listing 17.6, I\u2019ve applied a few of these techniques in a template to display a to-do item. The PageModel has a bool IsComplete property, as well as a List<string> property called Tasks, which contains any outstanding tasks.<br \/>\n\u5728\u5217\u8868 17.6 \u4e2d\uff0c\u6211\u5728\u6a21\u677f\u4e2d\u5e94\u7528\u4e86\u4e00\u4e9b\u6280\u672f\u6765\u663e\u793a\u5f85\u529e\u4e8b\u9879\u3002PageModel \u5177\u6709\u4e00\u4e2a bool IsComplete \u5c5e\u6027\uff0c\u4ee5\u53ca\u4e00\u4e2a\u540d\u4e3a Tasks \u7684 List \u5c5e\u6027\uff0c\u5176\u4e2d\u5305\u542b\u4efb\u4f55\u672a\u5b8c\u6210\u7684\u4efb\u52a1\u3002<\/p>\n<p>Listing 17.6 Razor template for rendering a ToDoItemViewModel<br \/>\n\u5217\u8868 17.6 \u7528\u4e8e\u5448\u73b0 ToDoItemViewModel \u7684 Razor \u6a21\u677f<\/p>\n<pre><code>@page\n@model ToDoItemModel \u2776\n&lt;div&gt;\n@if (Model.IsComplete)\n{ \u2777\n&lt;strong&gt;Well done, you\u2019re all done!&lt;\/strong&gt; \u2777\n} \u2777\nelse\n{\n&lt;strong&gt;The following tasks remain:&lt;\/strong&gt;\n&lt;ul&gt;\n@foreach (var task in Model.Tasks) \u2778\n{\n&lt;li&gt;@task&lt;\/li&gt; \u2779\n}\n&lt;\/ul&gt;\n}\n&lt;\/div&gt;<\/code><\/pre>\n<p>\u2776 The @model directive indicates the type of PageModel in Model.<br \/>\n@model \u6307\u4ee4\u6307\u793a Model \u4e2d PageModel \u7684\u7c7b\u578b\u3002<br \/>\n\u2777 The if control structure checks the value of the PageModel\u2019s IsComplete property at runtime.<br \/>\nif \u63a7\u4ef6\u7ed3\u6784\u5728\u8fd0\u884c\u65f6\u68c0\u67e5 PageModel \u7684 IsComplete \u5c5e\u6027\u7684\u503c\u3002<br \/>\n\u2778 The foreach structure will generate the <code>&lt;li&gt;<\/code> elements once for each task in Model.Tasks.<br \/>\nforeach \u7ed3\u6784\u4f53\u5c06\u751f\u6210<code>&lt;li&gt;<\/code>\u5143\u7d20\u3002<br \/>\n\u2779 A Razor expression is used to write the task to the HTML output.<br \/>\nRazor \u8868\u8fbe\u5f0f\u7528\u4e8e\u5c06\u4efb\u52a1\u5199\u5165 HTML \u8f93\u51fa\u3002<\/p>\n<p>This code definitely lives up to the promise of mixing C# and HTML! There are traditional C# control structures, such as if and foreach, that you\u2019d expect in any normal C# program, interspersed with the HTML markup that you want to send to the browser. As you can see, the @ symbol is used to indicate when you\u2019re starting a control statement, but you generally let the Razor template infer when you\u2019re switching back and forth between HTML and C#.<br \/>\n\u8fd9\u6bb5\u4ee3\u7801\u7edd\u5bf9\u5151\u73b0\u4e86\u6df7\u5408 C# \u548c HTML \u7684\u627f\u8bfa\uff01\u5728\u4efb\u4f55\u666e\u901a C# \u7a0b\u5e8f\u4e2d\uff0c\u90fd\u6709\u60a8\u671f\u671b\u4f7f\u7528\u7684\u4f20\u7edf C# \u63a7\u5236\u7ed3\u6784\uff0c\u4f8b\u5982 if \u548c foreach\uff0c\u5176\u4e2d\u7a7f\u63d2\u7740\u8981\u53d1\u9001\u5230\u6d4f\u89c8\u5668\u7684 HTML \u6807\u8bb0\u3002\u5982\u4f60\u6240\u89c1\uff0c@ \u7b26\u53f7\u7528\u4e8e\u6307\u793a\u4f55\u65f6\u542f\u52a8\u63a7\u5236\u8bed\u53e5\uff0c\u4f46\u4f60\u901a\u5e38\u4f1a\u8ba9 Razor \u6a21\u677f\u63a8\u65ad\u4f60\u5728 HTML \u548c C# \u4e4b\u95f4\u6765\u56de\u5207\u6362\u3002<\/p>\n<p>The template shows how to generate dynamic HTML at runtime, depending on the exact data provided. If the model has outstanding Tasks, the HTML generates a list item for each task, producing output something like that shown in figure 17.6.<br \/>\n\u8be5\u6a21\u677f\u6f14\u793a\u5982\u4f55\u5728\u8fd0\u884c\u65f6\u751f\u6210\u52a8\u6001 HTML\uff0c\u5177\u4f53\u53d6\u51b3\u4e8e\u63d0\u4f9b\u7684\u786e\u5207\u6570\u636e\u3002\u5982\u679c\u6a21\u578b\u6709\u672a\u5b8c\u6210\u7684\u4efb\u52a1\uff0cHTML \u4f1a\u4e3a\u6bcf\u4e2a\u4efb\u52a1\u751f\u6210\u4e00\u4e2a\u5217\u8868\u9879\uff0c\u4ea7\u751f\u5982\u56fe 17.6 \u6240\u793a\u7684\u8f93\u51fa\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1706.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 17.6 The Razor template generates a <code>&lt;li&gt;<\/code> item for each remaining task, depending on the data passed to the view at runtime. You can use an if block to render completely different HTML depending on the values in your model.<\/p>\n<p>\u56fe 17.6 Razor \u6a21\u677f\u4f1a\u751f\u6210\u4e00\u4e2a<code>&lt;li&gt;<\/code> item \u7684 SET \u4efb\u52a1\uff0c\u5177\u4f53\u53d6\u51b3\u4e8e\u5728\u8fd0\u884c\u65f6\u4f20\u9012\u7ed9\u89c6\u56fe\u7684\u6570\u636e\u3002\u60a8\u53ef\u4ee5\u4f7f\u7528 if \u5757\u6839\u636e\u6a21\u578b\u4e2d\u7684\u503c\u5448\u73b0\u5b8c\u5168\u4e0d\u540c\u7684 HTML\u3002<\/p>\n<blockquote>\n<p>IntelliSense and tooling support<br \/>\nIntelliSense \u548c\u5de5\u5177\u652f\u6301<\/p>\n<p>The mixture of C# and HTML might seem hard to read in the book, and that\u2019s a reasonable complaint. It\u2019s also another valid argument for trying to keep your Razor templates as simple as possible.<br \/>\nC# \u548c HTML \u7684\u6df7\u5408\u5728\u4e66\u4e2d\u4f3c\u4e4e\u5f88\u96be\u9605\u8bfb\uff0c\u8fd9\u662f\u4e00\u4e2a\u5408\u7406\u7684\u62b1\u6028\u3002\u8fd9\u4e5f\u662f\u5c1d\u8bd5\u4f7f Razor \u6a21\u677f\u5c3d\u53ef\u80fd\u7b80\u5355\u7684\u53e6\u4e00\u4e2a\u6709\u6548\u8bba\u70b9\u3002<\/p>\n<p>Luckily, if you\u2019re using an editor like Visual Studio or Visual Studio Code, the tooling can help somewhat. As you can see in this figure, Visual Studio highlights the transition between the C# portions of the code and the surrounding HTML, though this is less pronounced in recent versions of Visual Studio.<br \/>\n\u5e78\u8fd0\u7684\u662f\uff0c\u5982\u679c\u60a8\u4f7f\u7528\u7684\u662f Visual Studio \u6216 Visual Studio Code \u7b49\u7f16\u8f91\u5668\uff0c\u8fd9\u4e9b\u5de5\u5177\u53ef\u80fd\u4f1a\u6709\u6240\u5e2e\u52a9\u3002\u6b63\u5982\u60a8\u5728\u6b64\u56fe\u4e2d\u6240\u770b\u5230\u7684\uff0cVisual Studio \u7a81\u51fa\u663e\u793a\u4e86\u4ee3\u7801\u7684 C# \u90e8\u5206\u4e0e\u5468\u56f4 HTML \u4e4b\u95f4\u7684\u8f6c\u6362\uff0c\u5c3d\u7ba1\u8fd9\u5728\u6700\u65b0\u7248\u672c\u7684 Visual Studio \u4e2d\u4e0d\u592a\u660e\u663e\u3002<\/p>\n<\/blockquote>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1707.png\" alt=\"alt text\" \/><\/p>\n<blockquote>\n<p>Visual Studio highlights the @ symbols where C# transitions to HTML and uses C# syntax coloring for C# code. This makes the Razor templates somewhat easier to read that than the pure plain text.<br \/>\nVisual Studio \u7a81\u51fa\u663e\u793a C# \u8f6c\u6362\u4e3a HTML \u7684 @ \u7b26\u53f7\uff0c\u5e76\u5bf9 C# \u4ee3\u7801\u4f7f\u7528 C# \u8bed\u6cd5\u7740\u8272\u3002\u8fd9\u4f7f\u5f97 Razor \u6a21\u677f\u6bd4\u7eaf\u6587\u672c\u66f4\u5bb9\u6613\u9605\u8bfb\u3002<\/p>\n<p>Although the ability to use loops and conditionals is powerful\u2014they\u2019re one of the advantages of Razor over static HTML\u2014they also add to the complexity of your view. Try to limit the amount of logic in your views to make them as easy to understand and maintain as possible.<br \/>\n\u5c3d\u7ba1\u4f7f\u7528\u5faa\u73af\u548c\u6761\u4ef6\u7684\u529f\u80fd\u975e\u5e38\u5f3a\u5927\uff08\u5b83\u4eec\u662f Razor \u76f8\u5bf9\u4e8e\u9759\u6001 HTML \u7684\u4f18\u52bf\u4e4b\u4e00\uff09\uff0c\u4f46\u5b83\u4eec\u4e5f\u589e\u52a0\u4e86\u89c6\u56fe\u7684\u590d\u6742\u6027\u3002\u5c1d\u8bd5\u9650\u5236\u89c6\u56fe\u4e2d\u7684\u903b\u8f91\u6570\u91cf\uff0c\u4f7f\u5176\u5c3d\u53ef\u80fd\u6613\u4e8e\u7406\u89e3\u548c\u7ef4\u62a4\u3002<\/p>\n<\/blockquote>\n<p>A common trope of the ASP.NET Core team is that they try to ensure you \u201cfall into the pit of success\u201d when building an application. This refers to the idea that by default, the easiest way to do something should be the correct way of doing it. This is a great philosophy, as it means you shouldn\u2019t get burned by, for example, security problems if you follow the standard approaches. Occasionally, however, you may need to step beyond the safety rails; a common use case is when you need to render some HTML contained in a C# object to the output, as you\u2019ll see in the next section.<br \/>\nASP.NET Core \u56e2\u961f\u7684\u4e00\u4e2a\u5e38\u89c1\u6bd4\u55bb\u662f\uff0c\u4ed6\u4eec\u8bd5\u56fe\u786e\u4fdd\u60a8\u5728\u6784\u5efa\u5e94\u7528\u7a0b\u5e8f\u65f6 \u201c\u6389\u8fdb\u6210\u529f\u7684\u5751\u201d\u3002\u8fd9\u6307\u7684\u662f\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u6267\u884c\u67d0\u9879\u4f5c\u7684\u6700\u7b80\u5355\u65b9\u6cd5\u5e94\u8be5\u662f\u6b63\u786e\u7684\u6267\u884c\u65b9\u5f0f\u3002\u8fd9\u662f\u4e00\u4e2a\u5f88\u68d2\u7684\u7406\u5ff5\uff0c\u56e0\u4e3a\u5b83\u610f\u5473\u7740\u5982\u679c\u60a8\u9075\u5faa\u6807\u51c6\u65b9\u6cd5\uff0c\u60a8\u5c31\u4e0d\u5e94\u8be5\u88ab\u5b89\u5168\u95ee\u9898\u7b49\u95ee\u9898\u6240\u56f0\u6270\u3002\u4f46\u662f\uff0c\u6709\u65f6\u60a8\u53ef\u80fd\u9700\u8981\u8de8\u51fa\u5b89\u5168\u680f\u6746;\u4e00\u4e2a\u5e38\u89c1\u7684\u7528\u4f8b\u662f\u5f53\u60a8\u9700\u8981\u5c06 C# \u5bf9\u8c61\u4e2d\u5305\u542b\u7684\u4e00\u4e9b HTML \u6e32\u67d3\u5230\u8f93\u51fa\u65f6\uff0c\u60a8\u5c06\u5728\u4e0b\u4e00\u8282\u4e2d\u770b\u5230\u3002<\/p>\n<h3>17.3.3 Rendering HTML with Raw<\/h3>\n<p>17.3.3 \u4f7f\u7528 Raw \u6e32\u67d3 HTML<\/p>\n<p>In the previous example, we rendered the list of tasks to HTML by writing the string task using the @task Razor expression. But what if the task variable contains HTML you want to display, so instead of &quot;Check oil&quot; it contains &quot;<code>&lt;strong&gt;Check oil&lt;\/strong&gt;<\/code>&quot;? If you use a Razor expression to output this as you did previously, you might hope to get this:<br \/>\n\u5728\u524d\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u901a\u8fc7\u4f7f\u7528 @task Razor \u8868\u8fbe\u5f0f\u7f16\u5199\u5b57\u7b26\u4e32 task \u5c06\u4efb\u52a1\u5217\u8868\u5448\u73b0\u4e3a HTML\u3002\u4f46\u662f\uff0c\u5982\u679c\u4efb\u52a1\u53d8\u91cf\u5305\u542b\u8981\u663e\u793a\u7684 HTML\uff0c\u90a3\u4e48\u5b83\u4e0d\u662f\u201cCheck oil\u201d\uff0c\u800c\u662f&quot;<code>&lt;strong&gt;Check oil&lt;\/strong&gt;<\/code>&quot;\uff0c\u8be5\u600e\u4e48\u529e\uff1f\u5982\u679c\u60a8\u50cf\u4ee5\u524d\u4e00\u6837\u4f7f\u7528 Razor \u8868\u8fbe\u5f0f\u6765\u8f93\u51fa\u6b64\u8868\u8fbe\u5f0f\uff0c\u60a8\u53ef\u80fd\u5e0c\u671b\u5f97\u5230\u4ee5\u4e0b\u5185\u5bb9\uff1a<\/p>\n<pre><code>&lt;li&gt;&lt;strong&gt;Check oil&lt;\/strong&gt;&lt;\/li&gt;<\/code><\/pre>\n<p>But that\u2019s not the case. The HTML generated comes out like this:<br \/>\n\u4f46\u4e8b\u5b9e\u5e76\u975e\u5982\u6b64\u3002\u751f\u6210\u7684 HTML \u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<pre><code>&lt;li&gt;&lt;strong&gt;Check oil&lt;\/strong&gt;&lt;\/li&gt;<\/code><\/pre>\n<p>Hmm, looks odd, right? What\u2019s happened here? Why did the template not write your variable to the HTML, like it has in previous examples? If you look at how a browser displays this HTML, like in figure 17.7, I hope that it makes more sense.<br \/>\n\u55ef\uff0c\u770b\u8d77\u6765\u5f88\u5947\u602a\uff0c\u5bf9\u5427\uff1f\u8fd9\u91cc\u53d1\u751f\u4e86\u4ec0\u4e48\uff1f\u4e3a\u4ec0\u4e48\u6a21\u677f\u6ca1\u6709\u50cf\u524d\u9762\u7684\u793a\u4f8b\u90a3\u6837\u5c06\u53d8\u91cf\u5199\u5165 HTML\uff1f\u5982\u679c\u60a8\u67e5\u770b\u6d4f\u89c8\u5668\u5982\u4f55\u663e\u793a\u6b64 HTML\uff0c\u5982\u56fe 17.7 \u6240\u793a\uff0c\u6211\u5e0c\u671b\u5b83\u66f4\u6709\u610f\u4e49\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1708.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 17.7 The second item, <code> &quot;&lt;strong&gt;Check oil&lt;\/strong&gt;&quot; <\/code> has been HTML-encoded, so the <code> &lt;strong&gt; <\/code> elements are visible to the user as part of the task. This prevents any security problems, as users can\u2019t inject malicious scripts into your HTML.<br \/>\n\u56fe 17.7 \u7b2c\u4e8c\u9879<code> &quot;&lt;strong&gt;Check oil&lt;\/strong&gt;&quot; <\/code>\u5df2\u7ecf\u8fc7 HTML \u7f16\u7801\uff0c\u56e0\u6b64<code> &lt;strong&gt; <\/code>\u5143\u7d20\u4f5c\u4e3a\u4efb\u52a1\u7684\u4e00\u90e8\u5206\u5bf9\u7528\u6237\u53ef\u89c1\u3002\u8fd9\u53ef\u4ee5\u9632\u6b62\u4efb\u4f55\u5b89\u5168\u95ee\u9898\uff0c\u56e0\u4e3a\u7528\u6237\u65e0\u6cd5\u5c06\u6076\u610f\u811a\u672c\u6ce8\u5165\u60a8\u7684 HTML\u3002<\/p>\n<p>Razor templates HTML-encode C# expressions before they\u2019re written to the output stream. This is primarily for security reasons; writing out arbitrary strings to your HTML could allow users to inject malicious data and JavaScript into your website. Consequently, the C# variables you print in your Razor template get written as HTML-encoded values.<br \/>\nRazor \u6a21\u677f\u5728\u5c06 C# \u8868\u8fbe\u5f0f\u5199\u5165\u8f93\u51fa\u6d41\u4e4b\u524d\u5bf9\u5176\u8fdb\u884c HTML \u7f16\u7801\u3002\u8fd9\u4e3b\u8981\u662f\u51fa\u4e8e\u5b89\u5168\u539f\u56e0;\u5c06\u4efb\u610f\u5b57\u7b26\u4e32\u5199\u51fa\u5230 HTML \u4e2d\u53ef\u80fd\u4f1a\u5141\u8bb8\u7528\u6237\u5c06\u6076\u610f\u6570\u636e\u548c JavaScript \u6ce8\u5165\u60a8\u7684\u7f51\u7ad9\u3002\u56e0\u6b64\uff0c\u5728 Razor \u6a21\u677f\u4e2d\u6253\u5370\u7684 C# \u53d8\u91cf\u5c06\u5199\u5165 HTML \u7f16\u7801\u7684\u503c\u3002<\/p>\n<p><b>NOTE<\/b> Razor also renders non-ASCII Unicode characters, such as \u00f3 and \u00e8, as HTML entities: &#243; and &egrave;. You can customize this behavior using WebEncoderOptions in Program.cs, as in this example: <code> builder.Services.Configure&lt;WebEncoderOptions&gt;(o =&gt; o.AllowCharacter(&#039;\u00f3&#039;)) <\/code>.<\/p>\n<p>\u6ce8\u610f:Razor \u8fd8\u5c06\u975e ASCII Unicode \u5b57\u7b26\uff08\u5982 \u00f3 \u548c \u00e8\uff09\u5448\u73b0\u4e3a HTML \u5b9e\u4f53\uff1a\u00f3 \u548c \u00e8\u3002\u60a8\u53ef\u4ee5\u4f7f\u7528 Program.cs \u4e2d\u7684 WebEncoderOptions \u81ea\u5b9a\u4e49\u6b64\u884c\u4e3a\uff0c\u5982\u4ee5\u4e0b\u793a\u4f8b\u6240\u793a\uff1a\u3002 `builder.Services.Configure<WebEncoderOptions>(o =&gt; o.AllowCharacter('\u00f3'))<\/p>\n<p>In some cases, you might need to directly write out HTML contained in a string to the response. If you find yourself in this situation, first, stop. Do you really need to do this? If the values you\u2019re writing have been entered by a user, or were created based on values provided by users, there\u2019s a serious risk of creating a security hole in your website.<br \/>\n\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u60a8\u53ef\u80fd\u9700\u8981\u76f4\u63a5\u5c06\u5b57\u7b26\u4e32\u4e2d\u5305\u542b\u7684 HTML \u5199\u51fa\u5230\u54cd\u5e94\u4e2d\u3002\u5982\u679c\u60a8\u53d1\u73b0\u81ea\u5df1\u5904\u4e8e\u8fd9\u79cd\u60c5\u51b5\uff0c\u8bf7\u5148\u505c\u6b62\u3002\u60a8\u771f\u7684\u9700\u8981\u8fd9\u6837\u505a\u5417\uff1f\u5982\u679c\u60a8\u7f16\u5199\u7684\u503c\u662f\u7531\u7528\u6237\u8f93\u5165\u7684\uff0c\u6216\u8005\u662f\u6839\u636e\u7528\u6237\u63d0\u4f9b\u7684\u503c\u521b\u5efa\u7684\uff0c\u5219\u5b58\u5728\u5728\u60a8\u7684\u7f51\u7ad9\u4e2d\u521b\u5efa\u5b89\u5168\u6f0f\u6d1e\u7684\u4e25\u91cd\u98ce\u9669\u3002<\/p>\n<p>If you really need to write the variable out to the HTML stream, you can do so using the Html property on the view page and calling the Raw method:<br \/>\n\u5982\u679c\u60a8\u786e\u5b9e\u9700\u8981\u5c06\u53d8\u91cf\u5199\u51fa\u5230 HTML \u6d41\u4e2d\uff0c\u5219\u53ef\u4ee5\u4f7f\u7528\u89c6\u56fe\u9875\u9762\u4e0a\u7684 Html \u5c5e\u6027\u5e76\u8c03\u7528 Raw \u65b9\u6cd5\u6765\u5b9e\u73b0\uff1a<\/p>\n<pre><code>&lt;li&gt;@Html.Raw(task)&lt;\/li&gt;<\/code><\/pre>\n<p>With this approach, the string in task is directly written to the output stream, without encoding, producing the HTML you originally wanted, <code>&lt;li&gt;&lt;strong&gt;Check oil&lt;\/strong&gt;&lt;\/li&gt;<\/code>, which renders as shown in figure 17.8.<br \/>\n\u4f7f\u7528\u8fd9\u79cd\u65b9\u6cd5\uff0ctask \u4e2d\u7684\u5b57\u7b26\u4e32\u88ab\u76f4\u63a5\u5199\u5165\u8f93\u51fa\u6d41\uff0c\u65e0\u9700\u7f16\u7801\uff0c\u751f\u6210\u4f60\u6700\u521d\u60f3\u8981\u7684 HTML <code>&lt;li&gt;&lt;strong&gt;Check oil&lt;\/strong&gt;&lt;\/li&gt;<\/code>\uff0c\u5982\u56fe 17.8 \u6240\u793a\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1709.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 17.8 The second item, <code> &quot;&lt;strong&gt;Check oil&lt;strong&gt;&quot; <\/code> has been output using Html.Raw(), so it hasn\u2019t been HTML-encoded. The <code> &lt;strong&gt; <\/code> elements result in the second item being shown in bold instead. Using Html.Raw() in this way should be avoided where possible, as it is a security risk.<br \/>\n\u56fe 17.8 \u7b2c\u4e8c\u9879\u662f\u4f7f\u7528 Html.Raw\uff08\uff09 \u8f93\u51fa\u7684<code> &quot;&lt;strong&gt;Check oil&lt;strong&gt;&quot; <\/code> \uff0c\u56e0\u6b64\u5c1a\u672a\u8fdb\u884c HTML \u7f16\u7801\u3002\u8fd9\u4e9b <code> &lt;strong&gt; <\/code> \u5143\u7d20\u4f1a\u5bfc\u81f4\u7b2c\u4e8c\u4e2a\u9879\u76ee\u4ee5\u7c97\u4f53\u663e\u793a\u3002\u5e94\u5c3d\u53ef\u80fd\u907f\u514d\u4ee5\u8fd9\u79cd\u65b9\u5f0f\u4f7f\u7528 Html.Raw\uff08\uff09\uff0c\u56e0\u4e3a\u8fd9\u4f1a\u5e26\u6765\u5b89\u5168\u98ce\u9669\u3002<\/p>\n<p><b>Warning<\/b> Using Html.Raw on user input creates a security risk that users could use to inject malicious code into your website. Avoid using Html.Raw if possible.<br \/>\n\u8b66\u544a:\u5728\u7528\u6237\u8f93\u5165\u4e0a\u4f7f\u7528 Html.Raw \u4f1a\u5e26\u6765\u5b89\u5168\u98ce\u9669\uff0c\u7528\u6237\u53ef\u80fd\u4f1a\u5229\u7528\u8be5\u98ce\u9669\u5c06\u6076\u610f\u4ee3\u7801\u6ce8\u5165\u60a8\u7684\u7f51\u7ad9\u3002\u5982\u679c\u53ef\u80fd\uff0c\u8bf7\u907f\u514d\u4f7f\u7528 Html.Raw\u3002<\/p>\n<p>The C# constructs shown in this section can be useful, but they can make your templates harder to read. It\u2019s generally easier to understand the intention of Razor templates that are predominantly HTML markup rather than C#.<br \/>\n\u672c\u8282\u4e2d\u6240\u793a\u7684 C# \u6784\u9020\u53ef\u80fd\u5f88\u6709\u7528\uff0c\u4f46\u5b83\u4eec\u53ef\u80fd\u4f1a\u4f7f\u6a21\u677f\u66f4\u96be\u9605\u8bfb\u3002\u901a\u5e38\u66f4\u5bb9\u6613\u7406\u89e3\u4e3b\u8981\u662f HTML \u6807\u8bb0\u800c\u4e0d\u662f C# \u7684 Razor \u6a21\u677f\u7684\u610f\u56fe\u3002<\/p>\n<p>In the previous version of ASP.NET, these constructs, and in particular the Html helper property, were the standard way to generate dynamic markup. You can still use this approach in ASP.NET Core by using the various HtmlHelper methods on the Html property, but these have largely been superseded by a cleaner technique: Tag Helpers.<br \/>\n\u5728\u65e9\u671f\u7248\u672c\u7684 ASP.NET \u4e2d\uff0c\u8fd9\u4e9b\u6784\u9020\uff08\u7279\u522b\u662f Html \u5e2e\u52a9\u7a0b\u5e8f\u5c5e\u6027\uff09\u662f\u751f\u6210\u52a8\u6001\u6807\u8bb0\u7684\u6807\u51c6\u65b9\u6cd5\u3002\u60a8\u4ecd\u7136\u53ef\u4ee5\u5728 ASP.NET Core \u4e2d\u901a\u8fc7\u4f7f\u7528 Html \u5c5e\u6027\u4e0a\u7684\u5404\u79cd HtmlHelper \u65b9\u6cd5\uff0c\u4f46\u8fd9\u4e9b\u65b9\u6cd5\u5728\u5f88\u5927\u7a0b\u5ea6\u4e0a\u5df2\u88ab\u4e00\u79cd\u66f4\u7b80\u6d01\u7684\u6280\u672f\u6240\u53d6\u4ee3\uff1aTag Helpers\u3002<\/p>\n<p><b>NOTE<\/b> I discuss Tag Helpers and how to use them to build HTML forms in chapter 18. HtmlHelper is essentially obsolete, though it\u2019s still available if you prefer to use it.<br \/>\n\u6ce8\u610f:\u6211\u5728\u7b2c 18 \u7ae0\u4e2d\u8ba8\u8bba\u4e86 Tag Helpers \u4ee5\u53ca\u5982\u4f55\u4f7f\u7528\u5b83\u4eec\u6765\u6784\u5efa HTML \u8868\u5355\u3002HtmlHelper \u57fa\u672c\u4e0a\u5df2\u8fc7\u65f6\uff0c\u4f46\u5982\u679c\u60a8\u613f\u610f\u4f7f\u7528\u5b83\uff0c\u5b83\u4ecd\u7136\u53ef\u7528\u3002<\/p>\n<p>Tag Helpers are a useful feature that\u2019s new to Razor in ASP.NET Core, but many other features have been carried through from the legacy (.NET Framework) ASP.NET. In the next section of this chapter, you\u2019ll see how you can create nested Razor templates and use partial views to reduce the amount of duplication in your views.<br \/>\n\u6807\u8bb0\u5e2e\u52a9\u7a0b\u5e8f\u662f ASP.NET Core \u4e2d Razor \u65b0\u589e\u7684\u4e00\u9879\u6709\u7528\u529f\u80fd\uff0c\u4f46\u8bb8\u591a\u5176\u4ed6\u529f\u80fd\u5df2\u4ece\u65e7\u7248 \uff08.NET Framework\uff09 ASP.NET \u4e2d\u7ee7\u627f\u800c\u6765\u3002\u5728\u672c\u7ae0\u7684\u4e0b\u4e00\u90e8\u5206\u4e2d\uff0c\u60a8\u5c06\u4e86\u89e3\u5982\u4f55\u521b\u5efa\u5d4c\u5957\u7684 Razor \u6a21\u677f\u5e76\u4f7f\u7528\u5206\u90e8\u89c6\u56fe\u6765\u51cf\u5c11\u89c6\u56fe\u4e2d\u7684\u91cd\u590d\u6570\u91cf\u3002<\/p>\n<h2>17.4 Layouts, partial views, and _ViewStart<\/h2>\n<p>17.4 \u5e03\u5c40\u3001\u5206\u90e8\u89c6\u56fe\u548c_ViewStart<\/p>\n<p>In this section you\u2019ll learn about layouts and partial views, which allow you to extract common code to reduce duplication. These files make it easier to make changes to your HTML that affect multiple pages at once. You\u2019ll also learn how to run common code for every Razor Page using _ViewStart and _ViewImports, and how to include optional sections in your pages.<br \/>\n\u5728\u672c\u8282\u4e2d\uff0c\u60a8\u5c06\u4e86\u89e3\u5e03\u5c40\u548c\u5206\u90e8\u89c6\u56fe\uff0c\u5b83\u4eec\u5141\u8bb8\u60a8\u63d0\u53d6\u901a\u7528\u4ee3\u7801\u4ee5\u51cf\u5c11\u91cd\u590d\u3002\u901a\u8fc7\u8fd9\u4e9b\u6587\u4ef6\uff0c\u53ef\u4ee5\u66f4\u8f7b\u677e\u5730\u5bf9 HTML \u8fdb\u884c\u4e00\u6b21\u5f71\u54cd\u591a\u4e2a\u9875\u9762\u7684\u66f4\u6539\u3002\u60a8\u8fd8\u5c06\u4e86\u89e3\u5982\u4f55\u4f7f\u7528 _ViewStart \u548c _ViewImports \u4e3a\u6bcf\u4e2a Razor \u9875\u9762\u8fd0\u884c\u901a\u7528\u4ee3\u7801\uff0c\u4ee5\u53ca\u5982\u4f55\u5728\u9875\u9762\u4e2d\u5305\u542b\u53ef\u9009\u90e8\u5206\u3002<\/p>\n<p>Every HTML document has a certain number of elements that are required: <code>&lt;html&gt;<\/code>, <code>&lt;head&gt;<\/code>, and <code>&lt;body&gt;<\/code>. As well, there are often common sections that are repeated on every page of your application, such as the header and footer, as shown in figure 17.9. Also, each page in your application will probably reference the same CSS and JavaScript files.<br \/>\n\u6bcf\u4e2a HTML \u6587\u6863\u90fd\u6709\u4e00\u5b9a\u6570\u91cf\u7684\u5fc5\u9700\u5143\u7d20\uff1a<code>&lt;html&gt;<\/code>, <code>&lt;head&gt;<\/code>\u548c <code>&lt;body&gt;<\/code>.\u6b64\u5916\uff0c\u5728\u5e94\u7528\u7a0b\u5e8f\u7684\u6bcf\u4e2a\u9875\u9762\u4e0a\u901a\u5e38\u90fd\u6709\u91cd\u590d\u7684\u5e38\u89c1\u90e8\u5206\uff0c\u4f8b\u5982 header \u548c footer\uff0c\u5982\u56fe 17.9 \u6240\u793a\u3002\u6b64\u5916\uff0c\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u6bcf\u4e2a\u9875\u9762\u90fd\u53ef\u80fd\u5f15\u7528\u76f8\u540c\u7684 CSS \u548c JavaScript \u6587\u4ef6\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1710.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 17.9 A typical web application has a block-based layout, where some blocks are common to every page of your application. The header block will likely be identical across your whole application, but the sidebar may be identical only for the pages in one section. The body content will differ for every page in your application.<br \/>\n\u56fe 17.9 \u5178\u578b\u7684 Web \u5e94\u7528\u7a0b\u5e8f\u5177\u6709\u57fa\u4e8e\u5757\u7684\u5e03\u5c40\uff0c\u5176\u4e2d\u67d0\u4e9b\u5757\u5bf9\u4e8e\u5e94\u7528\u7a0b\u5e8f\u7684\u6bcf\u4e2a\u9875\u9762\u90fd\u662f\u901a\u7528\u7684\u3002\u6807\u9898\u5757\u5728\u6574\u4e2a\u5e94\u7528\u7a0b\u5e8f\u4e2d\u53ef\u80fd\u76f8\u540c\uff0c\u4f46\u4fa7\u8fb9\u680f\u53ef\u80fd\u4ec5\u5bf9\u4e00\u4e2a\u90e8\u5206\u4e2d\u7684\u9875\u9762\u76f8\u540c\u3002\u5e94\u7528\u7a0b\u5e8f\u4e2d\u6bcf\u4e2a\u9875\u9762\u7684\u6b63\u6587\u5185\u5bb9\u90fd\u4e0d\u540c\u3002<\/p>\n<p>All these different elements add up to a maintenance nightmare. If you had to include these manually in every view, making any changes would be a laborious, error-prone process involving editing every page. Instead, Razor lets you extract these common elements into layouts.<br \/>\n\u6240\u6709\u8fd9\u4e9b\u4e0d\u540c\u7684\u56e0\u7d20\u52a0\u8d77\u6765\u5c31\u662f\u4e00\u573a\u7ef4\u62a4\u5669\u68a6\u3002\u5982\u679c\u60a8\u5fc5\u987b\u5728\u6bcf\u4e2a\u89c6\u56fe\u4e2d\u624b\u52a8\u5305\u542b\u8fd9\u4e9b\u5185\u5bb9\uff0c\u5219\u8fdb\u884c\u4efb\u4f55\u66f4\u6539\u90fd\u5c06\u662f\u4e00\u4e2a\u8d39\u529b\u4e14\u5bb9\u6613\u51fa\u9519\u7684\u8fc7\u7a0b\uff0c\u6d89\u53ca\u7f16\u8f91\u6bcf\u4e2a\u9875\u9762\u3002\u76f8\u53cd\uff0cRazor \u5141\u8bb8\u60a8\u5c06\u8fd9\u4e9b\u5e38\u89c1\u5143\u7d20\u63d0\u53d6\u5230\u5e03\u5c40\u4e2d\u3002<\/p>\n<p><b>DEFINITION<\/b> A layout in Razor is a template that includes common code. It can\u2019t be rendered directly, but it can be rendered in conjunction with normal Razor views.<br \/>\n\u5b9a\u4e49:Razor \u4e2d\u7684\u5e03\u5c40\u662f\u5305\u542b\u901a\u7528\u4ee3\u7801\u7684\u6a21\u677f\u3002\u5b83\u4e0d\u80fd\u76f4\u63a5\u5448\u73b0\uff0c\u4f46\u53ef\u4ee5\u4e0e\u666e\u901a Razor \u89c6\u56fe\u4e00\u8d77\u5448\u73b0\u3002<\/p>\n<p>By extracting your common markup into layouts, you can reduce the duplication in your app. This makes changes easier, makes your views easier to manage and maintain, and is generally good practice!<br \/>\n\u901a\u8fc7\u5c06\u901a\u7528\u6807\u8bb0\u63d0\u53d6\u5230\u5e03\u5c40\u4e2d\uff0c\u60a8\u53ef\u4ee5\u51cf\u5c11\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u91cd\u590d\u3002\u8fd9\u4f7f\u5f97\u66f4\u6539\u66f4\u5bb9\u6613\uff0c\u4f7f\u60a8\u7684\u89c6\u56fe\u66f4\u6613\u4e8e\u7ba1\u7406\u548c\u7ef4\u62a4\uff0c\u5e76\u4e14\u901a\u5e38\u662f\u5f88\u597d\u7684\u505a\u6cd5\uff01<\/p>\n<h3>17.4.1 Using layouts for shared markup<\/h3>\n<p>17.4.1 \u5c06\u5e03\u5c40\u7528\u4e8e\u5171\u4eab\u6807\u8bb0<\/p>\n<p>Layout files are, for the most part, normal Razor templates that contain markup common to more than one page. An ASP.NET Core app can have multiple layouts, and layouts can reference other layouts. A common use for this is to have different layouts for different sections of your application. For example, an e-commerce website might use a three-column view for most pages but a single-column layout when you come to the checkout pages, as shown in figure 17.10.<br \/>\n\u5e03\u5c40\u6587\u4ef6\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\u662f\u666e\u901a\u7684 Razor \u6a21\u677f\uff0c\u5176\u4e2d\u5305\u542b\u591a\u4e2a\u9875\u9762\u901a\u7528\u7684\u6807\u8bb0\u3002ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u53ef\u4ee5\u6709\u591a\u4e2a\u5e03\u5c40\uff0c\u5e76\u4e14\u5e03\u5c40\u53ef\u4ee5\u5f15\u7528\u5176\u4ed6\u5e03\u5c40\u3002\u8fd9\u6837\u505a\u7684\u4e00\u4e2a\u5e38\u89c1\u7528\u9014\u662f\u4e3a\u5e94\u7528\u7a0b\u5e8f\u7684\u4e0d\u540c\u90e8\u5206\u4f7f\u7528\u4e0d\u540c\u7684\u5e03\u5c40\u3002\u4f8b\u5982\uff0c\u7535\u5b50\u5546\u52a1\u7f51\u7ad9\u53ef\u80fd\u5728\u5927\u591a\u6570\u9875\u9762\u4e2d\u4f7f\u7528\u4e09\u5217\u89c6\u56fe\uff0c\u4f46\u5728\u60a8\u8fdb\u5165\u7ed3\u5e10\u9875\u9762\u65f6\u4f7f\u7528\u5355\u5217\u5e03\u5c40\uff0c\u5982\u56fe 17.10 \u6240\u793a\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1711.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 17.10 The <a href=\"https:\/\/manning.com\">https:\/\/manning.com<\/a> website uses different layouts for different parts of the web application. The product pages use a three-column layout, but the cart page uses a single-column layout.<br \/>\n\u56fe 17.10 <a href=\"https:\/\/manning.com\">https:\/\/manning.com<\/a> \u7f51\u7ad9\u5bf9 Web \u5e94\u7528\u7a0b\u5e8f\u7684\u4e0d\u540c\u90e8\u5206\u4f7f\u7528\u4e0d\u540c\u7684\u5e03\u5c40\u3002\u4ea7\u54c1\u9875\u9762\u4f7f\u7528\u4e09\u5217\u5e03\u5c40\uff0c\u4f46\u8d2d\u7269\u8f66\u9875\u9762\u4f7f\u7528\u5355\u5217\u5e03\u5c40\u3002<\/p>\n<p>You\u2019ll often use layouts across many different Razor Pages, so they\u2019re typically placed in the Pages\/Shared folder. You can name them anything you like, but there\u2019s a common convention to use _Layout.cshtml as the filename for the base layout in your application. This is the default name used by the Razor Page templates in Visual Studio and the .NET CLI.<br \/>\n\u60a8\u7ecf\u5e38\u5728\u8bb8\u591a\u4e0d\u540c\u7684 Razor Pages \u4e2d\u4f7f\u7528\u5e03\u5c40\uff0c\u56e0\u6b64\u5b83\u4eec\u901a\u5e38\u4f4d\u4e8e Pages\/Shared \u6587\u4ef6\u5939\u4e2d\u3002\u4f60\u53ef\u4ee5\u4e3a\u5b83\u4eec\u547d\u540d\u4efb\u4f55\u4f60\u559c\u6b22\u7684\u540d\u5b57\uff0c\u4f46\u6709\u4e00\u4e2a\u5e38\u89c1\u7684\u7ea6\u5b9a\uff0c\u5373\u4f7f\u7528 _Layout.cshtml \u4f5c\u4e3a\u5e94\u7528\u7a0b\u5e8f\u4e2d\u57fa\u672c\u5e03\u5c40\u7684\u6587\u4ef6\u540d\u3002\u8fd9\u662f Visual Studio \u548c .NET CLI \u4e2d\u7684 Razor \u9875\u9762\u6a21\u677f\u4f7f\u7528\u7684\u9ed8\u8ba4\u540d\u79f0\u3002<\/p>\n<p><b>Tip<\/b> A common convention is to prefix your layout files with an underscore (_) to distinguish them from standard Razor templates in your Pages folder. Placing them in Pages\/Shared means you can refer to them by the short name, such as &quot;<em>Layout&quot;, without having to specify the full path to the layout file.<br \/>\n\u63d0\u793a:\u4e00\u4e2a\u5e38\u89c1\u7684\u7ea6\u5b9a\u662f\u5728\u5e03\u5c40\u6587\u4ef6\u524d\u9762\u52a0\u4e0a\u4e0b\u5212\u7ebf \uff08<\/em>\uff09\uff0c\u4ee5\u5c06\u5b83\u4eec\u4e0e Pages \u6587\u4ef6\u5939\u4e2d\u7684\u6807\u51c6 Razor \u6a21\u677f\u533a\u5206\u5f00\u6765\u3002\u5c06\u5b83\u4eec\u653e\u5728 Pages\/Shared \u4e2d\u610f\u5473\u7740\u60a8\u53ef\u4ee5\u901a\u8fc7\u77ed\u540d\u79f0\uff08\u5982\u201c_Layout\u201d\uff09\u6765\u5f15\u7528\u5b83\u4eec\uff0c\u800c\u4e0d\u5fc5\u6307\u5b9a\u5e03\u5c40\u6587\u4ef6\u7684\u5b8c\u6574\u8def\u5f84\u3002<\/p>\n<p>A layout file looks similar to a normal Razor template, with one exception: every layout must call the @RenderBody() function. This tells the templating engine where to insert the content from the child views. A simple layout is shown in listing 17.7. Typically, your application references all your CSS and JavaScript files in the layout and includes all the common elements, such as headers and footers, but this example includes pretty much the bare minimum HTML.<br \/>\n\u5e03\u5c40\u6587\u4ef6\u770b\u8d77\u6765\u7c7b\u4f3c\u4e8e\u666e\u901a\u7684 Razor \u6a21\u677f\uff0c\u4f46\u6709\u4e00\u4e2a\u4f8b\u5916\uff1a\u6bcf\u4e2a\u5e03\u5c40\u90fd\u5fc5\u987b\u8c03\u7528 @RenderBody\uff08\uff09 \u51fd\u6570\u3002\u8fd9\u4f1a\u544a\u8bc9\u6a21\u677f\u5f15\u64ce\u5c06\u5b50\u89c6\u56fe\u4e2d\u7684\u5185\u5bb9\u63d2\u5165\u5230\u4f55\u5904\u3002\u4e00\u4e2a\u7b80\u5355\u7684\u5e03\u5c40\u5982\u6e05\u5355 17.7 \u6240\u793a\u3002\u901a\u5e38\uff0c\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u4f1a\u5f15\u7528\u5e03\u5c40\u4e2d\u7684\u6240\u6709 CSS \u548c JavaScript \u6587\u4ef6\uff0c\u5e76\u5305\u542b\u6240\u6709\u5e38\u89c1\u5143\u7d20\uff0c\u4f8b\u5982\u9875\u7709\u548c\u9875\u811a\uff0c\u4f46\u6b64\u793a\u4f8b\u5305\u542b\u7684 HTML \u51e0\u4e4e\u662f\u6700\u4f4e\u9650\u5ea6\u7684\u3002<\/p>\n<p>Listing 17.7 A basic _Layout.cshtml file calling RenderBody<br \/>\n\u6e05\u5355 17.7 \u4e00\u4e2a\u8c03\u7528 RenderBody \u7684\u57fa\u672c _Layout.cshtml \u6587\u4ef6<\/p>\n<pre><code>&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n&lt;meta charset=&quot;utf-8&quot; \/&gt;\n&lt;title&gt;@ViewData[&quot;Title&quot;]&lt;\/title&gt; \u2776\n&lt;link rel=&quot;stylesheet&quot; href=&quot;~\/css\/site.css&quot; \/&gt; \u2777\n&lt;\/head&gt;\n&lt;body&gt;\n@RenderBody() \u2778\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/pre>\n<p>\u2776 ViewData is the standard mechanism for passing data to a layout from a view.<br \/>\nViewData \u662f\u4ece\u89c6\u56fe\u5411\u5e03\u5c40\u4f20\u9012\u6570\u636e\u7684\u6807\u51c6\u673a\u5236\u3002<br \/>\n\u2777 Elements common to every page, such as your CSS, are typically found in the layout.<br \/>\n\u6bcf\u4e2a\u9875\u9762\u901a\u7528\u7684\u5143\u7d20\uff08\u4f8b\u5982 CSS\uff09\u901a\u5e38\u4f4d\u4e8e\u5e03\u5c40\u4e2d\u3002<br \/>\n\u2778 Tells the templating engine where to insert the child view\u2019s content<br \/>\n\u544a\u8bc9\u6a21\u677f\u5f15\u64ce\u5728\u4f55\u5904\u63d2\u5165\u5b50\u89c6\u56fe\u7684\u5185\u5bb9<\/p>\n<p>As you can see, the layout file includes the required elements, such as<code> &lt;html&gt; <\/code>and <code>&lt;head&gt;<\/code>, as well as elements you need on every page, such as<code> &lt;title&gt; <\/code>and <code>&lt;link&gt;<\/code>. This example also shows the benefit of storing the page title in ViewData; the layout can render it in the <code>&lt;title&gt; <\/code>element so that it shows in the browser\u2019s tab, as shown in figure 17.11.<br \/>\n\u5982\u60a8\u6240\u89c1\uff0c\u5e03\u5c40\u6587\u4ef6\u5305\u62ec\u6240\u9700\u7684\u5143\u7d20\uff0c\u5982 <code> &lt;html&gt; <\/code>\u548c <code>&lt;head&gt;<\/code>\uff0c\u4ee5\u53ca\u6bcf\u4e2a\u9875\u9762\u4e0a\u6240\u9700\u7684\u5143\u7d20\uff0c\u5982<code> &lt;title&gt; <\/code>\u548c <code>&lt;link&gt;<\/code>\u3002\u6b64\u793a\u4f8b\u8fd8\u663e\u793a\u4e86\u5728 ViewData \u4e2d\u5b58\u50a8\u9875\u9762\u6807\u9898\u7684\u597d\u5904;\u5e03\u5c40\u53ef\u4ee5\u5728<code>&lt;title&gt; <\/code>\u5143\u7d20\u4e2d\u6e32\u67d3\u5b83\uff0c\u4f7f\u5176\u663e\u793a\u5728\u6d4f\u89c8\u5668\u7684\u9009\u9879\u5361\u4e2d\uff0c\u5982\u56fe 17.11 \u6240\u793a\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1712.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 17.11 The content of the <code>&lt;title&gt;<\/code> element is used to name the tab in the user\u2019s browser, in this case Home Page.<br \/>\n\u56fe 17.11 <code>&lt;title&gt;<\/code>\u5143\u7d20\u7684\u5185\u5bb9\u7528\u4e8e\u547d\u540d\u7528\u6237\u6d4f\u89c8\u5668\u4e2d\u7684\u9009\u9879\u5361\uff0c\u5728\u672c\u4f8b\u4e2d\u4e3a Home Page\u3002<\/p>\n<p><b>NOTE<\/b> Layout files are not standalone Razor Pages and do not take part in routing, so they do not start with the @page directive.<br \/>\n\u6ce8\u610f\uff1a\u5e03\u5c40\u6587\u4ef6\u4e0d\u662f\u72ec\u7acb\u7684 Razor \u9875\u9762\uff0c\u4e0d\u53c2\u4e0e\u8def\u7531\uff0c\u56e0\u6b64\u5b83\u4eec\u4e0d\u4ee5 @page \u6307\u4ee4\u5f00\u5934\u3002<\/p>\n<p>Views can specify a layout file to use by setting the Layout property inside a Razor code block, as shown in the following listing.<br \/>\n\u89c6\u56fe\u53ef\u4ee5\u901a\u8fc7\u5728 Razor \u4ee3\u7801\u5757\u4e2d\u8bbe\u7f6e Layout \u5c5e\u6027\u6765\u6307\u5b9a\u8981\u4f7f\u7528\u7684\u5e03\u5c40\u6587\u4ef6\uff0c\u5982\u4e0b\u9762\u7684\u6e05\u5355\u6240\u793a\u3002<\/p>\n<p>Listing 17.8 Setting the Layout property from a view<br \/>\n\u793a\u4f8b 17.8 \u4ece\u89c6\u56fe\u8bbe\u7f6e Layout \u5c5e\u6027<\/p>\n<pre><code>@{\nLayout = &quot;_Layout&quot;; \u2776\nViewData[&quot;Title&quot;] = &quot;Home Page&quot;; \u2777\n}\n&lt;h1&gt;@ViewData[&quot;Title&quot;]&lt;\/h1&gt; \u2778\n&lt;p&gt;This is the home page&lt;\/p&gt; \u2778<\/code><\/pre>\n<p>\u2776 Sets the layout for the page to _Layout.cshtml<br \/>\n\u5c06\u9875\u9762\u7684\u5e03\u5c40\u8bbe\u7f6e\u4e3a _Layout.cshtml<br \/>\n\u2777 ViewData is a convenient way of passing data from a Razor view to the layout.<br \/>\nViewData \u662f\u5c06\u6570\u636e\u4ece Razor \u89c6\u56fe\u4f20\u9012\u5230\u5e03\u5c40\u7684\u4fbf\u6377\u65b9\u6cd5\u3002<br \/>\n\u2778 The content in the Razor view to render inside the layout<br \/>\n\u8981\u5728\u5e03\u5c40\u5185\u5448\u73b0\u7684 Razor \u89c6\u56fe\u4e2d\u7684\u5185\u5bb9<\/p>\n<p>Any contents in the view are be rendered inside the layout, where the call to @RenderBody() occurs. Combining the two previous listings generates the following HTML.<br \/>\n\u89c6\u56fe\u4e2d\u7684\u4efb\u4f55\u5185\u5bb9\u90fd\u5c06\u5728\u5e03\u5c40\u4e2d\u5448\u73b0\uff0c\u5176\u4e2d\u4f1a\u8c03\u7528 @RenderBody\uff08\uff09\u3002\u5c06\u524d\u9762\u7684\u4e24\u4e2a\u5217\u8868\u7ec4\u5408\u5728\u4e00\u8d77\u5c06\u751f\u6210\u4ee5\u4e0b HTML\u3002<\/p>\n<p>Listing 17.9 Rendered output from combining a view with its layout<br \/>\n\u5217\u8868 17.9 \u5c06\u89c6\u56fe\u4e0e\u5176\u5e03\u5c40\u7ec4\u5408\u5728\u4e00\u8d77\u7684\u6e32\u67d3\u8f93\u51fa<\/p>\n<pre><code>&lt;!DOCTYPE html&gt;\n&lt;html&gt;\n&lt;head&gt;\n&lt;meta charset=&quot;utf-8&quot; \/&gt;\n&lt;title&gt;Home Page&lt;\/title&gt; \u2776\n&lt;link rel=&quot;stylesheet&quot; href=&quot;\/css\/site.css&quot; \/&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n&lt;h1&gt;Home Page&lt;\/h1&gt; \u2777\n&lt;p&gt;This is the home page&lt;\/p&gt; \u2777\n&lt;\/body&gt;\n&lt;html&gt;<\/code><\/pre>\n<p>\u2776 ViewData set in the view is used to render the layout.<br \/>\nViewData \u4e2d\u8bbe\u7f6e\u7684view \u7528\u4e8e\u6e32\u67d3\u5e03\u5c40\u3002<br \/>\n\u2777 The RenderBody call renders the contents of the view.<br \/>\nRenderBody \u8c03\u7528\u6e32\u67d3\u89c6\u56fe\u7684\u5185\u5bb9\u3002<\/p>\n<p>Judicious use of layouts can be extremely useful in reducing the duplication between pages. By default, layouts provide only a single location where you can render content from the view, at the call to @RenderBody. In cases where this is too restrictive, you can render content using sections.<br \/>\n\u660e\u667a\u5730\u4f7f\u7528\u5e03\u5c40\u5bf9\u4e8e\u51cf\u5c11\u9875\u9762\u4e4b\u95f4\u7684\u91cd\u590d\u975e\u5e38\u6709\u7528\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5e03\u5c40\u4ec5\u63d0\u4f9b\u4e00\u4e2a\u4f4d\u7f6e\uff0c\u60a8\u53ef\u4ee5\u5728\u8c03\u7528 @RenderBody\u65f6\u4ece\u89c6\u56fe\u4e2d\u5448\u73b0\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u8fc7\u4e8e\u4e25\u683c\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528\u90e8\u5206\u6765\u5448\u73b0\u5185\u5bb9\u3002<\/p>\n<h3>17.4.2 Overriding parent layouts using sections<\/h3>\n<p>\u4f7f\u7528\u90e8\u5206\u8986\u76d6\u7236\u5e03\u5c40<\/p>\n<p>A common requirement when you start using multiple layouts in your application is to be able to render content from child views in more than one place in your layout. Consider the case of a layout that uses two columns. The view needs a mechanism for saying \u201crender this content in the left column\u201d and \u201crender this other content in the right column.\u201d This is achieved using sections.<br \/>\n\u5f53\u60a8\u5728\u5e94\u7528\u7a0b\u5e8f\u4e2d\u5f00\u59cb\u4f7f\u7528\u591a\u4e2a\u5e03\u5c40\u65f6\uff0c\u4e00\u4e2a\u5e38\u89c1\u7684\u8981\u6c42\u662f\u80fd\u591f\u5728\u5e03\u5c40\u4e2d\u7684\u591a\u4e2a\u4f4d\u7f6e\u5448\u73b0\u5b50\u89c6\u56fe\u4e2d\u7684\u5185\u5bb9\u3002\u8003\u8651\u4f7f\u7528\u4e24\u5217\u7684\u5e03\u5c40\u7684\u60c5\u51b5\u3002\u89c6\u56fe\u9700\u8981\u4e00\u79cd\u673a\u5236\u6765\u8868\u793a \u201crender this content in the left column\u201d \u548c \u201crender this other content in the right column\u201d\u8fd9\u662f\u4f7f\u7528\u90e8\u5206\u5b9e\u73b0\u7684\u3002<\/p>\n<p><b>NOTE<\/b> Remember, all the features outlined in this chapter are specific to Razor, which is a server-side rendering engine. If you\u2019re using a client-side single-page application (SPA) framework to build your application, you\u2019ll likely handle these requirements in other ways, within the client.<br \/>\n\u6ce8\u610f\uff1a\u8bf7\u8bb0\u4f4f\uff0c\u672c\u7ae0\u4e2d\u6982\u8ff0\u7684\u6240\u6709\u529f\u80fd\u90fd\u662f\u7279\u5b9a\u4e8e Razor \u7684\uff0cRazor \u662f\u4e00\u4e2a\u670d\u52a1\u5668\u7aef\u6e32\u67d3\u5f15\u64ce\u3002\u5982\u679c\u60a8\u4f7f\u7528\u5ba2\u6237\u7aef\u5355\u9875\u5e94\u7528\u7a0b\u5e8f \uff08SPA\uff09 \u6846\u67b6\u6765\u6784\u5efa\u5e94\u7528\u7a0b\u5e8f\uff0c\u5219\u53ef\u80fd\u4f1a\u5728\u5ba2\u6237\u7aef\u5185\u4ee5\u5176\u4ed6\u65b9\u5f0f\u5904\u7406\u8fd9\u4e9b\u8981\u6c42\u3002<\/p>\n<p>Sections provide a way of organizing where view elements should be placed within a layout. They\u2019re defined in the view using an @section definition, as shown in the following listing, which defines the HTML content for a sidebar separate from the main content, in a section called Sidebar. The @section can be placed anywhere in the file, top or bottom, wherever is convenient.<br \/>\nSections \u63d0\u4f9b\u4e86\u4e00\u79cd\u7ec4\u7ec7\u89c6\u56fe\u5143\u7d20\u5728\u5e03\u5c40\u4e2d\u5e94\u653e\u7f6e\u7684\u4f4d\u7f6e\u7684\u65b9\u6cd5\u3002\u5b83\u4eec\u662f\u5728\u89c6\u56fe\u4e2d\u4f7f\u7528 @section \u5b9a\u4e49\u5b9a\u4e49\u7684\uff0c\u5982\u4e0b\u9762\u7684\u6e05\u5355\u6240\u793a\uff0c\u8be5\u6e05\u5355\u5728\u540d\u4e3a Sidebar \u7684\u90e8\u5206\u4e2d\u5b9a\u4e49\u4e0e\u4e3b\u8981\u5185\u5bb9\u5206\u5f00\u7684\u4fa7\u8fb9\u680f\u7684 HTML \u5185\u5bb9\u3002@section\u53ef\u4ee5\u653e\u7f6e\u5728\u6587\u4ef6\u4e2d\u7684\u4efb\u4f55\u4f4d\u7f6e\uff0c\u9876\u90e8\u6216\u5e95\u90e8\uff0c\u53ea\u8981\u65b9\u4fbf\u5373\u53ef\u3002<\/p>\n<p>Listing 17.10 Defining a section in a view template<br \/>\n\u6e05\u5355 17.10 \u5728\u89c6\u56fe\u6a21\u677f\u4e2d\u5b9a\u4e49\u90e8\u5206<\/p>\n<pre><code>@{\n    Layout = &quot;_TwoColumn&quot;;\n}\n@section Sidebar {                         #A\n    &lt;p&gt;This is the sidebar content&lt;\/p&gt;     #A\n}                                          #A\n&lt;p&gt;This is the main content &lt;\/p&gt;     #B<\/code><\/pre>\n<p>\u2776 All content inside the braces is part of the Sidebar section, not the main body content.<br \/>\n\u5927\u62ec\u53f7\u5185\u7684\u6240\u6709\u5185\u5bb9\u90fd\u662f Sidebar \u90e8\u5206\u7684\u4e00\u90e8\u5206\uff0c\u800c\u4e0d\u662f\u4e3b\u4f53\u5185\u5bb9\u3002<br \/>\n\u2777 Any content not inside an @section will be rendered by the @RenderBody call.<br \/>\n\u4e0d\u5728 @section \u4e2d\u7684\u4efb\u4f55\u5185\u5bb9\u90fd\u5c06\u7531 @RenderBody \u8c03\u7528\u5448\u73b0\u3002<\/p>\n<p>The section is rendered in the parent layout with a call to @RenderSection(). This renders the content contained in the child section into the layout. Sections can be either required or optional. If they\u2019re required, a view must declare the given @section; if they\u2019re optional, they can be omitted, and the layout will skip them. Skipped sections won\u2019t appear in the rendered HTML. The following listing shows a layout that has a required section called Sidebar and an optional section called Scripts.<br \/>\n\u8be5\u90e8\u5206\u901a\u8fc7\u8c03\u7528 @RenderSection\uff08\uff09 \u5728\u7236\u5e03\u5c40\u4e2d\u5448\u73b0\u3002\u8fd9\u4f1a\u5c06\u5b50\u90e8\u5206\u4e2d\u5305\u542b\u7684\u5185\u5bb9\u5448\u73b0\u5230\u5e03\u5c40\u4e2d\u3002\u90e8\u5206\u53ef\u4ee5\u662f\u5fc5\u9700\u7684\uff0c\u4e5f\u53ef\u4ee5\u662f\u53ef\u9009\u7684\u3002\u5982\u679c\u9700\u8981\uff0c\u89c6\u56fe\u5fc5\u987b\u58f0\u660e\u7ed9\u5b9a\u7684@section;\u5982\u679c\u5b83\u4eec\u662f\u53ef\u9009\u7684\uff0c\u5219\u53ef\u4ee5\u7701\u7565\u5b83\u4eec\uff0c\u5e03\u5c40\u5c06\u8df3\u8fc7\u5b83\u4eec\u3002\u8df3\u8fc7\u7684\u90e8\u5206\u4e0d\u4f1a\u663e\u793a\u5728\u5448\u73b0\u7684 HTML \u4e2d\u3002\u4e0b\u9762\u7684\u6e05\u5355\u663e\u793a\u4e86\u4e00\u4e2a\u5e03\u5c40\uff0c\u8be5\u5e03\u5c40\u5177\u6709\u4e00\u4e2a\u540d\u4e3a Sidebar \u7684\u5fc5\u9700\u90e8\u5206\u548c\u4e00\u4e2a\u540d\u4e3a Scripts \u7684\u53ef\u9009\u90e8\u5206\u3002<\/p>\n<p>Listing 17.11 Rendering a section in a layout file, _TwoColumn.cshtml<br \/>\n\u6e05\u5355 17.11 \u5728\u5e03\u5c40\u6587\u4ef6\u4e2d\u6e32\u67d3\u90e8\u5206 _TwoColumn.cshtml<\/p>\n<pre><code>@{\n    Layout = &quot;_Layout&quot;;     #A\n}\n&lt;div class=&quot;main-content&quot;&gt;\n    @RenderBody()          #B\n&lt;\/div&gt;\n&lt;div class=&quot;side-bar&quot;&gt;\n    @RenderSection(&quot;Sidebar&quot;, required: true)     #C\n&lt;\/div&gt;\n@RenderSection(&quot;Scripts&quot;, required: false)    #D<\/code><\/pre>\n<p>\u2776 This layout is nested inside a layout itself.<br \/>\n\u6b64\u5e03\u5c40\u5d4c\u5957\u5728\u5e03\u5c40\u672c\u8eab\u5185\u3002<br \/>\n\u2777 Renders all the content from a view that isn\u2019t part of a section<br \/>\n\u4ece\u4e0d\u5c5e\u4e8e\u67d0\u4e2a\u90e8\u5206\u7684\u89c6\u56fe\u4e2d\u5448\u73b0\u6240\u6709\u5185\u5bb9<br \/>\n\u2778 Renders the Sidebar section; if the Sidebar section isn\u2019t defined in the view, throws an error<br \/>\n\u5448\u73b0\u4fa7\u8fb9\u680f\u90e8\u5206;\u5982\u679c\u89c6\u56fe\u4e2d\u672a\u5b9a\u4e49 Sidebar \u90e8\u5206\uff0c\u5219\u629b\u51fa\u9519\u8bef<br \/>\n\u2779 Renders the Scripts section; if the Scripts section isn\u2019t defined in the view, ignores it<br \/>\n\u5448\u73b0 Scripts \u90e8\u5206;\u5982\u679c Scripts \u90e8\u5206\u672a\u5728\u89c6\u56fe\u4e2d\u5b9a\u4e49\uff0c\u5219\u5ffd\u7565\u5b83<\/p>\n<p><b>Tip<\/b> It\u2019s common to have an optional section called Scripts in your layout pages. This can be used to render additional JavaScript that\u2019s required by some views but isn\u2019t needed on every view. A common example is the jQuery Unobtrusive Validation scripts for client-side validation. If a view requires the scripts, it adds the appropriate @section Scripts to the Razor markup.<br \/>\n\u63d0\u793a\uff1a\u5e03\u5c40\u9875\u9762\u4e2d\u901a\u5e38\u6709\u4e00\u4e2a\u540d\u4e3a Scripts \u7684\u53ef\u9009\u90e8\u5206\u3002\u8fd9\u53ef\u7528\u4e8e\u5448\u73b0\u67d0\u4e9b\u89c6\u56fe\u9700\u8981\u4f46\u5e76\u975e\u6bcf\u4e2a\u89c6\u56fe\u90fd\u9700\u8981\u7684\u5176\u4ed6 JavaScript\u3002\u4e00\u4e2a\u5e38\u89c1\u7684\u793a\u4f8b\u662f\u7528\u4e8e\u5ba2\u6237\u7aef\u9a8c\u8bc1\u7684 jQuery Unobtrusive Validation \u811a\u672c\u3002\u5982\u679c\u89c6\u56fe\u9700\u8981\u811a\u672c\uff0c\u5b83\u4f1a\u5c06\u76f8\u5e94\u7684 @section \u811a\u672c\u6dfb\u52a0\u5230 Razor \u6807\u8bb0\u3002<\/p>\n<p>You may notice that the previous listing defines a Layout property, even though it\u2019s a layout itself, not a view. This is perfectly acceptable and lets you create nested hierarchies of layouts, as shown in figure 17.12.<br \/>\n\u60a8\u53ef\u80fd\u4f1a\u6ce8\u610f\u5230\uff0c\u524d\u9762\u7684\u6e05\u5355\u5b9a\u4e49\u4e86\u4e00\u4e2a Layout \u5c5e\u6027\uff0c\u5373\u4f7f\u5b83\u672c\u8eab\u662f\u4e00\u4e2a\u5e03\u5c40\uff0c\u800c\u4e0d\u662f\u4e00\u4e2a\u89c6\u56fe\u3002\u8fd9\u662f\u5b8c\u5168\u53ef\u4ee5\u63a5\u53d7\u7684\uff0c\u5e76\u4e14\u5141\u8bb8\u60a8\u521b\u5efa\u5e03\u5c40\u7684\u5d4c\u5957\u5c42\u6b21\u7ed3\u6784\uff0c\u5982\u56fe 17.12 \u6240\u793a\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/1713.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 17.12 Multiple layouts can be nested to create complex hierarchies. This allows you to keep the elements common to all views in your base layout and extract layout common to multiple views into sub-layouts.<br \/>\n\u56fe 17.12 \u53ef\u4ee5\u5d4c\u5957\u591a\u4e2a\u5e03\u5c40\u4ee5\u521b\u5efa\u590d\u6742\u7684\u5c42\u6b21\u7ed3\u6784\u3002\u8fd9\u6837\uff0c\u60a8\u5c31\u53ef\u4ee5\u4fdd\u6301\u57fa\u672c\u5e03\u5c40\u4e2d\u6240\u6709\u89c6\u56fe\u901a\u7528\u7684\u5143\u7d20\uff0c\u5e76\u5c06\u591a\u4e2a\u89c6\u56fe\u901a\u7528\u7684\u5e03\u5c40\u63d0\u53d6\u5230\u5b50\u5e03\u5c40\u4e2d\u3002<\/p>\n<p><b>Tip<\/b> Most websites these days need to be responsive, so they work on a wide variety of devices. You generally shouldn\u2019t use layouts for this. Don\u2019t serve different layouts for a single page based on the device making the request. Instead, serve the same HTML to all devices, and use CSS on the client side to adapt the display of your web page as required.<br \/>\n\u63d0\u793a\uff1a\u5982\u4eca\uff0c\u5927\u591a\u6570\u7f51\u7ad9\u90fd\u9700\u8981\u54cd\u5e94\u5f0f\uff0c\u56e0\u6b64\u5b83\u4eec\u53ef\u4ee5\u5728\u5404\u79cd\u8bbe\u5907\u4e0a\u8fd0\u884c\u3002\u901a\u5e38\uff0c\u60a8\u4e0d\u5e94\u8be5\u4e3a\u6b64\u4f7f\u7528\u5e03\u5c40\u3002\u4e0d\u8981\u6839\u636e\u53d1\u51fa\u8bf7\u6c42\u7684\u8bbe\u5907\u4e3a\u5355\u4e2a\u9875\u9762\u63d0\u4f9b\u4e0d\u540c\u7684\u5e03\u5c40\u3002\u76f8\u53cd\uff0c\u5e94\u5411\u6240\u6709\u8bbe\u5907\u63d0\u4f9b\u76f8\u540c\u7684 HTML\uff0c\u5e76\u5728\u5ba2\u6237\u7aef\u4f7f\u7528 CSS \u6765\u6839\u636e\u9700\u8981\u8c03\u6574\u7f51\u9875\u7684\u663e\u793a\u3002<\/p>\n<p>As well as the simple optional\/required flags for sections, Razor Pages have several other messages that you can use for flow control in your layout pages:<br \/>\n\u9664\u4e86\u90e8\u5206\u7684\u7b80\u5355\u53ef\u9009\/\u5fc5\u9700\u6807\u5fd7\u5916\uff0cRazor Pages \u8fd8\u6709\u5176\u4ed6\u51e0\u6761\u6d88\u606f\u53ef\u7528\u4e8e\u5e03\u5c40\u9875\u9762\u4e2d\u7684\u6d41\u63a7\u5236\uff1a<\/p>\n<p>\u2022  IsSectionDefined(string section)\u2014Returns true if a Razor Page has defined the named section.<br \/>\nIsSectionDefined\uff08string section\uff09 - \u5982\u679c Razor \u9875\u9762\u5df2\u5b9a\u4e49\u547d\u540d\u90e8\u5206\uff0c\u5219\u8fd4\u56de true\u3002<\/p>\n<p>\u2022  IgnoreSection(string section)\u2014Ignores an unrendered section. If a section is defined in a page but not rendered, the Razor Page throws an exception unless the section is ignored.<br \/>\nIgnoreSection\uff08string section\uff09 - \u5ffd\u7565\u672a\u6e32\u67d3\u7684\u90e8\u5206\u3002\u5982\u679c\u5728\u9875\u9762\u4e2d\u5b9a\u4e49\u4e86\u67d0\u4e2a\u90e8\u5206\u4f46\u672a\u5448\u73b0\uff0c\u5219 Razor Page \u4f1a\u5f15\u53d1\u5f02\u5e38\uff0c\u9664\u975e\u5ffd\u7565\u8be5\u90e8\u5206\u3002<\/p>\n<p>\u2022  IgnoreBody()\u2014Ignores the unrendered body of the Razor Page. Layouts must call either RenderBody() or IgnoreBody(); otherwise, they will throw an InvalidOperationException.<br \/>\nIgnoreBody\uff08\uff09 - \u5ffd\u7565 Razor Page \u7684\u672a\u6e32\u67d3\u4e3b\u4f53\u3002\u5e03\u5c40\u5fc5\u987b\u8c03\u7528 RenderBody\uff08\uff09 \u6216 IgnoreBody\uff08\uff09;\u5426\u5219\uff0c\u5b83\u4eec\u5c06\u5f15\u53d1 InvalidOperationException\u3002<\/p>\n<p>Layout files and sections provide a lot of flexibility for building sophisticated UIs, but one of their most important uses is in reducing the duplication of code in your application. They\u2019re perfect for avoiding duplication of content that you\u2019d need to write for every view. But what about those times when you find you want to reuse part of a view somewhere else? For those cases, you have partial views.<br \/>\n\u5e03\u5c40\u6587\u4ef6\u548c\u90e8\u5206\u4e3a\u6784\u5efa\u590d\u6742\u7684 UI \u63d0\u4f9b\u4e86\u5f88\u5927\u7684\u7075\u6d3b\u6027\uff0c\u4f46\u5b83\u4eec\u6700\u91cd\u8981\u7684\u7528\u9014\u4e4b\u4e00\u662f\u51cf\u5c11\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u4ee3\u7801\u91cd\u590d\u3002\u5b83\u4eec\u975e\u5e38\u9002\u5408\u907f\u514d\u60a8\u9700\u8981\u4e3a\u6bcf\u4e2a\u89c6\u56fe\u7f16\u5199\u7684\u5185\u5bb9\u91cd\u590d\u3002\u4f46\u662f\uff0c\u5f53\u60a8\u53d1\u73b0\u60f3\u8981\u5728\u5176\u4ed6\u5730\u65b9\u91cd\u7528\u89c6\u56fe\u7684\u4e00\u90e8\u5206\u65f6\uff0c\u8be5\u600e\u4e48\u529e\uff1f\u5bf9\u4e8e\u8fd9\u4e9b\u60c5\u51b5\uff0c\u60a8\u6709 partial views\u3002<\/p>\n<h3>17.4.3 Using partial views to encapsulate markup<\/h3>\n<p>17.4.3 \u4f7f\u7528\u5206\u90e8\u89c6\u56fe\u5c01\u88c5\u6807\u8bb0<\/p>\n<p>Partial views are exactly what they sound like: part of a view. They provide a means of breaking up a larger view into smaller, reusable chunks. This can be useful for both reducing the complexity in a large view by splitting it into multiple partial views or for allowing you to reuse part of a view inside another.<br \/>\n\u90e8\u5206\u89c6\u56fe\u6b63\u662f\u5b83\u4eec\u542c\u8d77\u6765\u7684\u6837\u5b50\uff1a\u89c6\u56fe\u7684\u4e00\u90e8\u5206\u3002\u5b83\u4eec\u63d0\u4f9b\u4e86\u4e00\u79cd\u5c06\u8f83\u5927\u7684\u89c6\u56fe\u5206\u89e3\u4e3a\u66f4\u5c0f\u7684\u3001\u53ef\u91cd\u7528\u7684\u5757\u7684\u65b9\u6cd5\u3002\u8fd9\u65e2\u53ef\u4ee5\u901a\u8fc7\u5c06\u5927\u578b\u89c6\u56fe\u62c6\u5206\u4e3a\u591a\u4e2a\u90e8\u5206\u89c6\u56fe\u6765\u964d\u4f4e\u5927\u578b\u89c6\u56fe\u7684\u590d\u6742\u6027\uff0c\u4e5f\u53ef\u4ee5\u5141\u8bb8\u60a8\u5728\u53e6\u4e00\u4e2a\u89c6\u56fe\u4e2d\u91cd\u7528\u67d0\u4e2a\u89c6\u56fe\u7684\u4e00\u90e8\u5206\u3002<\/p>\n<p>Most web frameworks that use server-side rendering have this capability. Ruby on Rails has partial views, Django has inclusion tags, and Zend has partials. These all work in the same way, extracting common code into small, reusable templates. Even client-side templating engines such as Mustache and Handlebars, used by client-side frameworks like Angular and Ember, have similar \u201cpartial view\u201d concepts.<br \/>\n\u5927\u591a\u6570\u4f7f\u7528\u670d\u52a1\u5668\u7aef\u6e32\u67d3\u7684 Web \u6846\u67b6\u90fd\u5177\u6709\u6b64\u529f\u80fd\u3002Ruby on Rails \u6709 partial \u89c6\u56fe\uff0cDjango \u6709 inclusion \u6807\u7b7e\uff0c\u800c Zend \u6709 partials\u3002\u8fd9\u4e9b\u90fd\u4ee5\u76f8\u540c\u7684\u65b9\u5f0f\u5de5\u4f5c\uff0c\u5c06\u901a\u7528\u4ee3\u7801\u63d0\u53d6\u5230\u5c0f\u578b\u3001\u53ef\u91cd\u7528\u7684\u6a21\u677f\u4e2d\u3002\u5373\u4f7f\u662f Angular \u548c Ember \u7b49\u5ba2\u6237\u7aef\u6846\u67b6\u4f7f\u7528\u7684\u5ba2\u6237\u7aef\u6a21\u677f\u5f15\u64ce\uff08\u5982 Mustache \u548c Handlebars\uff09\u4e5f\u5177\u6709\u7c7b\u4f3c\u7684\u201c\u90e8\u5206\u89c6\u56fe\u201d\u6982\u5ff5\u3002<\/p>\n<p>Consider a to-do list application again. You might find you have a Razor Page called ViewToDo.cshtml that displays a single to-do with a given id. Later, you create a new Razor Page, RecentToDos.cshtml, that displays the five most recent to-do items. Instead of copying and pasting the code from one page to the other, you could create a partial view, called _ToDo.cshtml, as in the following listing.<br \/>\n\u518d\u6b21\u8003\u8651\u4e00\u4e2a\u5f85\u529e\u4e8b\u9879\u5217\u8868\u5e94\u7528\u7a0b\u5e8f\u3002\u4f60\u53ef\u80fd\u4f1a\u53d1\u73b0\u4f60\u6709\u4e00\u4e2a\u540d\u4e3a ViewToDo.cshtml \u7684 Razor \u9875\u9762\uff0c\u5b83\u663e\u793a\u5177\u6709\u7ed9\u5b9a ID \u7684\u5355\u4e2a\u5f85\u529e\u4e8b\u9879\u3002\u7a0d\u540e\uff0c\u60a8\u5c06\u521b\u5efa\u4e00\u4e2a\u65b0\u7684 Razor \u9875\u9762 RecentToDos.cshtml\uff0c\u8be5\u9875\u9762\u663e\u793a\u4e94\u4e2a\u6700\u65b0\u7684\u5f85\u529e\u4e8b\u9879\u3002\u60a8\u53ef\u4ee5\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a _ToDo.cshtml \u7684\u5206\u90e8\u89c6\u56fe\uff0c\u800c\u4e0d\u662f\u5c06\u4ee3\u7801\u4ece\u4e00\u4e2a\u9875\u9762\u590d\u5236\u5e76\u7c98\u8d34\u5230\u53e6\u4e00\u4e2a\u9875\u9762\uff0c\u5982\u4e0b\u9762\u7684\u6e05\u5355\u6240\u793a\u3002<\/p>\n<p>Listing 17.12 Partial view _ToDo.cshtml for displaying a ToDoItemViewModel<br \/>\n\u5217\u8868 17.12 \u7528\u4e8e\u663e\u793a ToDoItemViewModel \u7684\u5206\u90e8\u89c6\u56fe _ToDo.cshtml<\/p>\n<pre><code>@model ToDoItemViewModel                                  #A\n&lt;h2&gt;@Model.Title&lt;\/h2&gt;                   #B\n&lt;ul&gt;                                    #B\n    @foreach (var task in Model.Tasks)  #B\n    {                                   #B\n        &lt;li&gt;@task&lt;\/li&gt;                  #B\n    }                                   #B\n&lt;\/ul&gt;                                   #B<\/code><\/pre>\n<p>\u2776 Partial views can bind to data in the Model property, like a normal Razor Page uses a PageModel.<br \/>\n\u5206\u90e8\u89c6\u56fe\u53ef\u4ee5\u7ed1\u5b9a\u5230 Model \u5c5e\u6027\u4e2d\u7684\u6570\u636e\uff0c\u5c31\u50cf\u666e\u901a\u7684 Razor Page \u4f7f\u7528 PageModel \u4e00\u6837\u3002<br \/>\n\u2777 The content of the partial view, which previously existed in the ViewToDo.cshtml file<br \/>\n\u5206\u90e8\u89c6\u56fe\u7684\u5185\u5bb9\uff0c\u4ee5\u524d\u5b58\u5728\u4e8e ViewToDo.cshtml \u6587\u4ef6\u4e2d<\/p>\n<p>Partial views are a bit like Razor Pages without the PageModel and handlers. Partial views are purely about rendering small sections of HTML rather than handling requests, model binding, and validation, and calling the application model. They are great for encapsulating small usable bits of HTML that you need to generate on multiple Razor Pages.<br \/>\n\u5206\u90e8\u89c6\u56fe\u6709\u70b9\u50cf\u6ca1\u6709 PageModel \u548c\u5904\u7406\u7a0b\u5e8f\u7684 Razor Pages\u3002\u5206\u90e8\u89c6\u56fe\u7eaf\u7cb9\u662f\u5173\u4e8e\u5448\u73b0 HTML \u7684\u4e00\u5c0f\u90e8\u5206\uff0c\u800c\u4e0d\u662f\u5904\u7406\u8bf7\u6c42\u3001\u6a21\u578b\u7ed1\u5b9a\u548c\u9a8c\u8bc1\u4ee5\u53ca\u8c03\u7528\u5e94\u7528\u7a0b\u5e8f\u6a21\u578b\u3002\u5b83\u4eec\u975e\u5e38\u9002\u5408\u5c01\u88c5\u60a8\u9700\u8981\u5728\u591a\u4e2a Razor \u9875\u9762\u4e0a\u751f\u6210\u7684\u5c11\u91cf\u53ef\u7528 HTML\u3002<\/p>\n<p>Both the ViewToDo.cshtml and RecentToDos.cshtml Razor Pages can render the _ToDo.cshtml partial view, which handles generating the HTML for a single class. Partial views are rendered using the <code>&lt;partial \/&gt;<\/code> Tag Helper, providing the name of the partial view to render and the data (the model) to render. For example, the RecentToDos.cshtml view could achieve this as shown in the following listing.<br \/>\nViewToDo.cshtml \u548c RecentToDos.cshtml Razor \u9875\u9762\u90fd\u53ef\u4ee5\u5448\u73b0 _ToDo.cshtml \u5206\u90e8\u89c6\u56fe\uff0c\u8be5\u89c6\u56fe\u5904\u7406\u4e3a\u5355\u4e2a\u7c7b\u751f\u6210 HTML\u3002\u90e8\u5206\u89c6\u56fe\u4f7f\u7528<code>&lt;partial \/&gt;<\/code> Tag Helper \u8fdb\u884c\u6e32\u67d3\uff0c\u63d0\u4f9b\u8981\u6e32\u67d3\u7684\u5206\u90e8\u89c6\u56fe\u7684\u540d\u79f0\u548c\u8981\u6e32\u67d3\u7684\u6570\u636e\uff08\u6a21\u578b\uff09\u3002\u4f8b\u5982\uff0cRecentToDos.cshtml \u89c6\u56fe\u53ef\u4ee5\u5b9e\u73b0\u6b64\u76ee\u7684\uff0c\u5982\u4e0b\u9762\u7684\u6e05\u5355\u6240\u793a\u3002<\/p>\n<p>Listing 17.13 Rendering a partial view from a Razor Page<br \/>\n\u6e05\u5355 17.13 \u4ece Razor \u9875\u9762\u6e32\u67d3\u90e8\u5206\u89c6\u56fe<\/p>\n<pre><code>@page                    #A\n@model RecentToDoListModel                   #B\n\n@foreach(var todo in Model.RecentItems)     #C\n{\n    &lt;partial name=&quot;_ToDo&quot; model=&quot;todo&quot; \/&gt;   #D\n}<\/code><\/pre>\n<p>\u2776 This is a Razor Page, so it uses the @page directive. Partial views do not use @page.<br \/>\n\u8fd9\u662f\u4e00\u4e2a Razor \u9875\u9762\uff0c\u56e0\u6b64\u5b83\u4f7f\u7528 @page \u6307\u4ee4\u3002\u5206\u90e8\u89c6\u56fe\u4e0d\u4f7f\u7528@page\u3002<br \/>\n\u2777 The PageModel contains the list of recent items to render.<br \/>\nPageModel \u5305\u542b\u8981\u6e32\u67d3\u7684\u6700\u8fd1\u9879\u76ee\u7684\u5217\u8868\u3002<br \/>\n\u2778 Loops through the recent items. todo is a ToDoItemViewModel, as required by the partial view.<br \/>\n\u5faa\u73af\u6d4f\u89c8\u6700\u8fd1\u7684\u9879\u76ee\u3002todo \u662f ToDoItemViewModel\uff0c\u8fd9\u662f\u5206\u90e8\u89c6\u56fe\u6240\u9700\u7684\u3002<br \/>\n\u2779 Uses the partial tag helper to render the _ToDo partial view, passing in the model to render<br \/>\n\u4f7f\u7528 partial \u6807\u7b7e\u8f85\u52a9\u51fd\u6570\u6e32\u67d3_ToDo \u90e8\u5206\u89c6\u56fe\uff0c\u4f20\u5165\u6a21\u578b\u4ee5\u6e32\u67d3<\/p>\n<p>When you render a partial view without providing an absolute path or file extension, such as _ToDo in listing 17.13, the framework tries to locate the view by searching the Pages folder, starting from the Razor Page that invoked it. For example, if your Razor Page is located at Pages\/Agenda\/ToDos\/RecentToDos.chstml, the framework would look in the following places for a file called _ToDo.chstml:<br \/>\n\u5f53\u60a8\u5728\u4e0d\u63d0\u4f9b\u7edd\u5bf9\u8def\u5f84\u6216\u6587\u4ef6\u6269\u5c55\u540d\u7684\u60c5\u51b5\u4e0b\u5448\u73b0\u90e8\u5206\u89c6\u56fe\u65f6\uff08\u5982\u6e05\u5355 17.13 \u4e2d\u7684 _ToDo\uff09\uff0c\u6846\u67b6\u4f1a\u5c1d\u8bd5\u901a\u8fc7\u641c\u7d22 Pages \u6587\u4ef6\u5939\u6765\u67e5\u627e\u89c6\u56fe\uff0c\u4ece\u8c03\u7528\u5b83\u7684 Razor Page \u5f00\u59cb\u3002\u4f8b\u5982\uff0c\u5982\u679c\u60a8\u7684 Razor \u9875\u9762\u4f4d\u4e8e Pages\/Agenda\/ToDos\/RecentToDos.chstml\uff0c\u5219\u6846\u67b6\u5c06\u5728\u4ee5\u4e0b\u4f4d\u7f6e\u67e5\u627e\u540d\u4e3a _ToDo.chstml \u7684\u6587\u4ef6\uff1a<\/p>\n<p>\u2022  Pages\/Agenda\/ToDos\/ (the current Razor Page\u2019s folder)<br \/>\n\u2022  Pages\/Agenda\/<br \/>\n\u2022  Pages\/<br \/>\n\u2022  Pages\/Shared\/<br \/>\n\u2022  Views\/Shared\/<\/p>\n<p>The first location that contains a file called _ToDo.cshtml will be selected. If you include the .cshtml file extension when you reference the partial view, the framework will look only in the current Razor Page\u2019s folder. Also, if you provide an absolute path to the partial, such as \/Pages\/Agenda\/ToDo.cshtml, that\u2019s the only place the framework will look.<br \/>\n\u5c06\u9009\u62e9\u5305\u542b\u540d\u4e3a _ToDo.cshtml \u7684\u6587\u4ef6\u7684\u7b2c\u4e00\u4e2a\u4f4d\u7f6e\u3002\u5982\u679c\u5728\u5f15\u7528\u5206\u90e8\u89c6\u56fe\u65f6\u5305\u542b .cshtml \u6587\u4ef6\u6269\u5c55\u540d\uff0c\u5219\u6846\u67b6\u5c06\u4ec5\u5728\u5f53\u524d Razor Page \u7684\u6587\u4ef6\u5939\u4e2d\u67e5\u627e\u3002\u6b64\u5916\uff0c\u5982\u679c\u63d0\u4f9b\u90e8\u5206\u7684\u7edd\u5bf9\u8def\u5f84\uff08\u5982 \/Pages\/Agenda\/ToDo.cshtml\uff09\uff0c\u5219\u8fd9\u662f\u6846\u67b6\u5c06\u67e5\u770b\u7684\u552f\u4e00\u4f4d\u7f6e\u3002<\/p>\n<p><b>Tip<\/b> As with most of Razor Pages, the search locations are conventions that you can customize. If you find the need, you can customize the paths as shown here: <a href=\"http:\/\/mng.bz\/nM9e\">http:\/\/mng.bz\/nM9e<\/a>.<br \/>\n\u63d0\u793a:\u4e0e\u5927\u591a\u6570 Razor Pages \u4e00\u6837\uff0c\u641c\u7d22\u4f4d\u7f6e\u662f\u53ef\u4ee5\u81ea\u5b9a\u4e49\u7684\u7ea6\u5b9a\u3002\u5982\u679c\u627e\u5230\u9700\u6c42\uff0c\u53ef\u4ee5\u81ea\u5b9a\u4e49\u8def\u5f84\uff0c\u5982\u4e0b\u6240\u793a\uff1a<a href=\"http:\/\/mng.bz\/nM9e\">http:\/\/mng.bz\/nM9e<\/a>\u3002<\/p>\n<p>The Razor code contained in a partial view is almost identical to a standard view. The main difference is the fact that partial views are called only from other views. The other difference is that partial views don\u2019t run _ViewStart.cshtml when they execute. You\u2019ll learn about _ViewStart.cshtml shortly in section 17.4.4.<br \/>\n\u5206\u90e8\u89c6\u56fe\u4e2d\u5305\u542b\u7684 Razor \u4ee3\u7801\u4e0e\u6807\u51c6\u89c6\u56fe\u51e0\u4e4e\u76f8\u540c\u3002\u4e3b\u8981\u533a\u522b\u5728\u4e8e\u5206\u90e8\u89c6\u56fe\u4ec5\u4ece\u5176\u4ed6\u89c6\u56fe\u8c03\u7528\u3002\u53e6\u4e00\u4e2a\u533a\u522b\u662f\uff0c\u5206\u90e8\u89c6\u56fe\u5728\u6267\u884c\u65f6\u4e0d\u4f1a\u8fd0\u884c _ViewStart.cshtml\u3002\u60a8\u5f88\u5feb\u5c31\u4f1a\u5728\u7b2c 17.4.4 \u8282\u4e2d\u4e86\u89e3 _ViewStart.cshtml\u3002<\/p>\n<p><b>NOTE<\/b> Like layouts, partial views are typically named with a leading underscore.<br \/>\n\u6ce8\u610f:\u4e0e\u5e03\u5c40\u4e00\u6837\uff0c\u5206\u90e8\u89c6\u56fe\u901a\u5e38\u4f7f\u7528\u524d\u5bfc\u4e0b\u5212\u7ebf\u547d\u540d\u3002<\/p>\n<blockquote>\n<p>Child actions in ASP.NET Core<\/p>\n<p>In the legacy .NET Framework version of ASP.NET, there was the concept of a child action. This was an MVC controller action method that could be invoked from inside a view. This was the main mechanism for rendering discrete sections of a complex layout that had nothing to do with the main action method. For example, a child action method might render the shopping cart in the corner of every page on an e-commerce site.<br \/>\n\u5728 ASP.NET \u7684\u65e7\u7248 .NET Framework \u4e2d\uff0c\u5b58\u5728\u5b50\u4f5c\u7684\u6982\u5ff5\u3002\u8fd9\u662f\u4e00\u4e2a\u53ef\u4ee5\u4ece\u89c6\u56fe\u5185\u90e8\u8c03\u7528\u7684 MVC \u63a7\u5236\u5668\u4f5c\u65b9\u6cd5\u3002\u8fd9\u662f\u6e32\u67d3\u590d\u6742\u5e03\u5c40\u7684\u79bb\u6563\u90e8\u5206\u7684\u4e3b\u8981\u673a\u5236\uff0c\u4e0e\u4e3b\u4f5c\u65b9\u6cd5\u65e0\u5173\u3002\u4f8b\u5982\uff0c\u5b50\u4f5c\u65b9\u6cd5\u53ef\u80fd\u4f1a\u5728\u7535\u5b50\u5546\u52a1\u7f51\u7ad9\u4e0a\u6bcf\u4e2a\u9875\u9762\u7684\u4e00\u89d2\u5448\u73b0\u8d2d\u7269\u8f66\u3002<\/p>\n<p>This approach meant you didn\u2019t have to pollute every page\u2019s view model with the view model items required to render the shopping cart, but it fundamentally broke the MVC design pattern by referencing controllers from a view.<br \/>\n\u8fd9\u79cd\u65b9\u6cd5\u610f\u5473\u7740\u4f60\u4e0d\u5fc5\u7528\u6e32\u67d3\u8d2d\u7269\u8f66\u6240\u9700\u7684\u89c6\u56fe\u6a21\u578b\u9879\u6765\u6c61\u67d3\u6bcf\u4e2a\u9875\u9762\u7684\u89c6\u56fe\u6a21\u578b\uff0c\u4f46\u5b83\u901a\u8fc7\u4ece\u89c6\u56fe\u4e2d\u5f15\u7528\u63a7\u5236\u5668\uff0c\u4ece\u6839\u672c\u4e0a\u6253\u7834\u4e86 MVC \u8bbe\u8ba1\u6a21\u5f0f\u3002<\/p>\n<p>In ASP.NET Core, child actions are no more. View components have replaced them. These are conceptually quite similar in that they allow both the execution of arbitrary code and the rendering of HTML, but they don\u2019t directly invoke controller actions. You can think of them as a more powerful partial view that you should use anywhere a partial view needs to contain significant code or business logic. You\u2019ll see how to build a small view component in chapter 32.<br \/>\n\u5728 ASP.NET Core \u4e2d\uff0c\u5b50\u4f5c\u4e0d\u518d\u5b58\u5728\u3002\u89c6\u56fe\u7ec4\u4ef6\u5df2\u53d6\u4ee3\u5b83\u4eec\u3002\u5b83\u4eec\u5728\u6982\u5ff5\u4e0a\u975e\u5e38\u76f8\u4f3c\uff0c\u56e0\u4e3a\u5b83\u4eec\u90fd\u5141\u8bb8\u6267\u884c\u4efb\u610f\u4ee3\u7801\u548c\u5448\u73b0 HTML\uff0c\u4f46\u5b83\u4eec\u4e0d\u76f4\u63a5\u8c03\u7528\u63a7\u5236\u5668\u4f5c\u3002\u60a8\u53ef\u4ee5\u5c06\u5b83\u4eec\u89c6\u4e3a\u4e00\u4e2a\u529f\u80fd\u66f4\u5f3a\u5927\u7684\u5206\u90e8\u89c6\u56fe\uff0c\u60a8\u5e94\u8be5\u5728\u5206\u90e8\u89c6\u56fe\u9700\u8981\u5305\u542b\u91cd\u8981\u4ee3\u7801\u6216\u4e1a\u52a1\u903b\u8f91\u7684\u4efb\u4f55\u4f4d\u7f6e\u4f7f\u7528\u5b83\u3002\u60a8\u5c06\u5728\u7b2c 32 \u7ae0\u4e2d\u770b\u5230\u5982\u4f55\u6784\u5efa\u4e00\u4e2a\u5c0f\u7684\u89c6\u56fe\u7ec4\u4ef6\u3002<\/p>\n<\/blockquote>\n<p>Partial views aren\u2019t the only way to reduce duplication in your view templates. Razor also allows you to put common elements such as namespace declarations and layout configuration in centralized files. In the next section you\u2019ll see how to wield these files to clean up your templates.<br \/>\n\u5206\u90e8\u89c6\u56fe\u5e76\u4e0d\u662f\u51cf\u5c11\u89c6\u56fe\u6837\u677f\u4e2d\u91cd\u590d\u7684\u552f\u4e00\u65b9\u6cd5\u3002Razor \u8fd8\u5141\u8bb8\u5c06\u547d\u540d\u7a7a\u95f4\u58f0\u660e\u548c\u5e03\u5c40\u914d\u7f6e\u7b49\u5e38\u89c1\u5143\u7d20\u653e\u5728\u96c6\u4e2d\u5f0f\u6587\u4ef6\u4e2d\u3002\u5728\u4e0b\u4e00\u8282\u4e2d\uff0c\u60a8\u5c06\u770b\u5230\u5982\u4f55\u4f7f\u7528\u8fd9\u4e9b\u6587\u4ef6\u6765\u6e05\u7406\u6a21\u677f\u3002<\/p>\n<h3>17.4.4 Running code on every view with _ViewStart and _ViewImports<\/h3>\n<p>17.4.4 \u4f7f\u7528 _ViewStart \u548c _ViewImports \u5728\u6bcf\u4e2a\u89c6\u56fe\u4e0a\u8fd0\u884c\u4ee3\u7801<\/p>\n<p>Due to the nature of views, you\u2019ll inevitably find yourself writing certain things repeatedly. If all your views use the same layout, adding the following code to the top of every page feels a little redundant:<br \/>\n\u7531\u4e8e\u89c6\u56fe\u7684\u6027\u8d28\uff0c\u60a8\u4e0d\u53ef\u907f\u514d\u5730\u4f1a\u53d1\u73b0\u81ea\u5df1\u91cd\u590d\u7f16\u5199\u67d0\u4e9b\u5185\u5bb9\u3002\u5982\u679c\u6240\u6709\u89c6\u56fe\u90fd\u4f7f\u7528\u76f8\u540c\u7684\u5e03\u5c40\uff0c\u5219\u5c06\u4ee5\u4e0b\u4ee3\u7801\u6dfb\u52a0\u5230\u6bcf\u4e2a\u9875\u9762\u7684\u9876\u90e8\u611f\u89c9\u6709\u70b9\u591a\u4f59\uff1a<\/p>\n<pre><code>@{\n    Layout = &quot;_Layout&quot;;\n}<\/code><\/pre>\n<p>Similarly, if you find you need to reference objects from a different namespace in your Razor views, then having to add @using WebApplication1.Models to the top of every page can get to be a chore. Fortunately, ASP.NET Core includes two mechanisms for handling these common tasks: _ViewImports.cshtml and _ViewStart.cshtml.<br \/>\n\u540c\u6837\uff0c\u5982\u679c\u4f60\u53d1\u73b0\u9700\u8981\u5728 Razor \u89c6\u56fe\u4e2d\u5f15\u7528\u6765\u81ea\u4e0d\u540c\u547d\u540d\u7a7a\u95f4\u7684\u5bf9\u8c61\uff0c\u5219\u5fc5\u987b\u5c06 WebApplication1.Models \u6dfb\u52a0\u5230\u6bcf\u4e2a\u9875\u9762\u7684\u9876\u90e8@using\u8fd9\u53ef\u80fd\u662f\u4e00\u4ef6\u82e6\u5dee\u4e8b\u3002\u5e78\u8fd0\u7684\u662f\uff0cASP.NET Core \u5305\u542b\u4e24\u79cd\u7528\u4e8e\u5904\u7406\u8fd9\u4e9b\u5e38\u89c1\u4efb\u52a1\u7684\u673a\u5236\uff1a_ViewImports.cshtml \u548c _ViewStart.cshtml\u3002<\/p>\n<blockquote>\n<p>Importing common directives with _ViewImports<br \/>\n\u4f7f\u7528 _ViewImports \u5bfc\u5165\u901a\u7528\u6307\u4ee4<\/p>\n<p>The _ViewImports.cshtml file contains directives that are inserted at the top of every Razor view. This can include things like the @using and @model statements that you\u2019ve already seen\u2014basically any Razor directive. For example, to avoid adding a using statement to every view, you can include it in _ViewImports.cshtml instead of in your Razor Pages, as shown in the following listing.<br \/>\n_ViewImports.cshtml \u6587\u4ef6\u5305\u542b\u63d2\u5165\u5230\u6bcf\u4e2a Razor \u89c6\u56fe\u9876\u90e8\u7684\u6307\u4ee4\u3002\u8fd9\u53ef\u4ee5\u5305\u62ec\u60a8\u5df2\u7ecf\u770b\u5230\u7684 @using \u548c @model \u8bed\u53e5\u7b49\u5185\u5bb9\uff0c\u57fa\u672c\u4e0a\u662f\u4efb\u4f55 Razor \u6307\u4ee4\u3002\u4f8b\u5982\uff0c\u82e5\u8981\u907f\u514d\u5c06 using \u8bed\u53e5\u6dfb\u52a0\u5230\u6bcf\u4e2a\u89c6\u56fe\uff0c\u53ef\u4ee5\u5c06\u5176\u5305\u542b\u5728 _ViewImports.cshtml \u4e2d\uff0c\u800c\u4e0d\u662f\u5305\u542b\u5728 Razor Pages \u4e2d\uff0c\u5982\u4e0b\u9762\u7684\u6e05\u5355\u6240\u793a\u3002<\/p>\n<\/blockquote>\n<p>Listing 17.14 A typical _ViewImports.cshtml file importing additional namespaces<br \/>\n\u5217\u8868 17.14 \u4e00\u4e2a\u5178\u578b\u7684 _ViewImports.cshtml \u6587\u4ef6\u5bfc\u5165\u989d\u5916\u7684\u547d\u540d\u7a7a\u95f4<\/p>\n<pre><code>@using WebApplication1            #A\n@using WebApplication1.Pages      #A\n@using WebApplication1.Models                            #B\n@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers    #C<\/code><\/pre>\n<p>\u2776 The default namespace of your application and the Pages folder<br \/>\n\u5e94\u7528\u7a0b\u5e8f\u7684\u9ed8\u8ba4\u547d\u540d\u7a7a\u95f4\u548c Pages \u6587\u4ef6\u5939<br \/>\n\u2777 Adds this directive to avoid placing it in every view<br \/>\n\u6dfb\u52a0\u6b64\u6307\u4ee4\u4ee5\u907f\u514d\u5c06\u5176\u653e\u7f6e\u5728\u6bcf\u4e2a\u89c6\u56fe\u4e2d<br \/>\n\u2778 Makes Tag Helpers available in your views, added by default<br \/>\n\u4f7f\u6807\u7b7e\u5e2e\u52a9\u7a0b\u5e8f\u5728\u60a8\u7684\u89c6\u56fe\u4e2d\u53ef\u7528\uff0c\u9ed8\u8ba4\u6dfb\u52a0<\/p>\n<p>The _ViewImports.cshtml file can be placed in any folder, and it will apply to all views and subfolders in that folder. Typically, it\u2019s placed in the root Pages folder so that it applies to every Razor Page and partial view in your app.<br \/>\n_ViewImports.cshtml \u6587\u4ef6\u53ef\u4ee5\u653e\u7f6e\u5728\u4efb\u4f55\u6587\u4ef6\u5939\u4e2d\uff0c\u5e76\u4e14\u5b83\u5c06\u5e94\u7528\u4e8e\u8be5\u6587\u4ef6\u5939\u4e2d\u7684\u6240\u6709\u89c6\u56fe\u548c\u5b50\u6587\u4ef6\u5939\u3002\u901a\u5e38\uff0c\u5b83\u4f4d\u4e8e\u6839 Pages \u6587\u4ef6\u5939\u4e2d\uff0c\u4ee5\u4fbf\u5e94\u7528\u4e8e\u5e94\u7528\u4e2d\u7684\u6bcf\u4e2a Razor \u9875\u9762\u548c\u90e8\u5206\u89c6\u56fe\u3002<\/p>\n<p>It\u2019s important to note that you should put Razor directives only in _ViewImports.cshtml; you can\u2019t put any old C# in there. As you can see in the previous listing, this is limited to things like @using or the @addTagHelper directive that you\u2019ll learn about in chapter 18. If you want to run some arbitrary C# at the start of every view in your application, such as to set the Layout property, you should use the _ViewStart.cshtml file instead.<br \/>\n\u8bf7\u52a1\u5fc5\u6ce8\u610f\uff0c\u5e94\u4ec5\u5c06 Razor \u6307\u4ee4\u653e\u5728 _ViewImports.cshtml \u4e2d;\u4f60\u4e0d\u80fd\u628a\u4efb\u4f55\u65e7\u7684 C# \u653e\u8fdb\u53bb\u3002\u6b63\u5982\u60a8\u5728\u524d\u9762\u7684\u6e05\u5355\u4e2d\u6240\u770b\u5230\u7684\uff0c\u8fd9\u4ec5\u9650\u4e8e @using \u6216 @addTagHelper \u6307\u4ee4\u4e4b\u7c7b\u7684\u5185\u5bb9\uff0c\u60a8\u5c06\u5728\u7b2c 18 \u7ae0\u4e2d\u5b66\u4e60\u8fd9\u4e9b\u5185\u5bb9\u3002\u5982\u679c\u8981\u5728\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u6bcf\u4e2a\u89c6\u56fe\u7684\u5f00\u5934\u8fd0\u884c\u4e00\u4e9b\u4efb\u610f C#\uff0c\u4f8b\u5982\u8bbe\u7f6e Layout \u5c5e\u6027\uff0c\u5219\u5e94\u6539\u7528 _ViewStart.cshtml \u6587\u4ef6\u3002<\/p>\n<blockquote>\n<p>Running code for every view with _ViewStart<br \/>\n\u4f7f\u7528 _ViewStart \u4e3a\u6bcf\u4e2a\u89c6\u56fe\u8fd0\u884c\u4ee3\u7801<\/p>\n<p>You can easily run common code at the start of every Razor Page by adding a _ViewStart.cshtml file to the Pages folder in your application. This file can contain any Razor code, but it\u2019s typically used to set the Layout for all the pages in your application, as shown in the following listing. Then you can omit the Layout statement from all pages that use the default layout. If a view needs to use a nondefault layout, you can override it by setting the value in the Razor Page itself.<br \/>\n\u901a\u8fc7\u5c06 _ViewStart.cshtml \u6587\u4ef6\u6dfb\u52a0\u5230\u5e94\u7528\u7a0b\u5e8f\u7684 Pages \u6587\u4ef6\u5939\uff0c\u53ef\u4ee5\u8f7b\u677e\u5730\u5728\u6bcf\u4e2a Razor \u9875\u9762\u7684\u5f00\u5934\u8fd0\u884c\u901a\u7528\u4ee3\u7801\u3002\u6b64\u6587\u4ef6\u53ef\u4ee5\u5305\u542b\u4efb\u4f55 Razor \u4ee3\u7801\uff0c\u4f46\u5b83\u901a\u5e38\u7528\u4e8e\u4e3a\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u6240\u6709\u9875\u9762\u8bbe\u7f6e Layout\uff0c\u5982\u4e0b\u9762\u7684\u6e05\u5355\u6240\u793a\u3002\u7136\u540e\uff0c\u60a8\u53ef\u4ee5\u4ece\u4f7f\u7528\u9ed8\u8ba4\u5e03\u5c40\u7684\u6240\u6709\u9875\u9762\u4e2d\u7701\u7565 Layout \u8bed\u53e5\u3002\u5982\u679c\u89c6\u56fe\u9700\u8981\u4f7f\u7528\u975e\u9ed8\u8ba4\u5e03\u5c40\uff0c\u60a8\u53ef\u4ee5\u901a\u8fc7\u5728 Razor \u9875\u9762\u672c\u8eab\u4e2d\u8bbe\u7f6e\u503c\u6765\u8986\u76d6\u5b83\u3002<\/p>\n<\/blockquote>\n<p>Listing 17.15 A typical _ViewStart.cshtml file setting the default layout<br \/>\n\u5217\u8868 17.15 \u8bbe\u7f6e\u9ed8\u8ba4\u5e03\u5c40\u7684\u5178\u578b _ViewStart.cshtml \u6587\u4ef6<\/p>\n<pre><code>@{\n    Layout = &quot;_Layout&quot;;\n}<\/code><\/pre>\n<p>Any code in the _ViewStart.cshtml file runs before the view executes. Note that _ViewStart.cshtml runs only for Razor Page views; it doesn\u2019t run for layouts or partial views. Also note that the names for these special Razor files are enforced and can\u2019t be changed by conventions.<br \/>\n_ViewStart.cshtml \u6587\u4ef6\u4e2d\u7684\u4efb\u4f55\u4ee3\u7801\u5728\u89c6\u56fe\u6267\u884c\u4e4b\u524d\u8fd0\u884c\u3002\u8bf7\u6ce8\u610f\uff0c_ViewStart.cshtml \u4ec5\u9488\u5bf9 Razor \u9875\u9762\u89c6\u56fe\u8fd0\u884c;\u5b83\u4e0d\u9488\u5bf9\u5e03\u5c40\u6216\u5206\u90e8\u89c6\u56fe\u8fd0\u884c\u3002\u53e6\u8bf7\u6ce8\u610f\uff0c\u8fd9\u4e9b\u7279\u6b8a Razor \u6587\u4ef6\u7684\u540d\u79f0\u662f\u5f3a\u5236\u6027\u7684\uff0c\u4e0d\u80fd\u901a\u8fc7\u7ea6\u5b9a\u8fdb\u884c\u66f4\u6539\u3002<\/p>\n<p><b>Warning<\/b> You must use the names _ViewStart.cshtml and _ViewImports.cshtml for the Razor engine to locate and execute them correctly. To apply them to all your app\u2019s pages, add them to the root of the Pages folder, not to the Shared subfolder.<br \/>\n\u8b66\u544a:\u5fc5\u987b\u4f7f\u7528\u540d\u79f0 _ViewStart.cshtml \u548c _ViewImports.cshtml \u4ee5\u4fbf Razor \u5f15\u64ce\u6b63\u786e\u67e5\u627e\u548c\u6267\u884c\u5b83\u4eec\u3002\u8981\u5c06\u5b83\u4eec\u5e94\u7528\u4e8e\u5e94\u7528\u7a0b\u5e8f\u7684\u6240\u6709\u9875\u9762\uff0c\u8bf7\u5c06\u5b83\u4eec\u6dfb\u52a0\u5230 Pages \u6587\u4ef6\u5939\u7684\u6839\u76ee\u5f55\uff0c\u800c\u4e0d\u662f Shared \u5b50\u6587\u4ef6\u5939\u3002<\/p>\n<p>You can specify additional _ViewStart.cshtml or _ViewImports.cshtml files to run for a subset of your views by including them in a subfolder in Pages. The files in the subfolders run after the files in the root Pages folder.<br \/>\n\u60a8\u53ef\u4ee5\u901a\u8fc7\u5c06\u89c6\u56fe\u5b50\u96c6\u5305\u542b\u5728 Pages \u7684\u5b50\u6587\u4ef6\u5939\u4e2d\u6765\u6307\u5b9a\u8981\u4e3a\u89c6\u56fe\u5b50\u96c6\u8fd0\u884c\u7684\u5176\u4ed6 _ViewStart.cs_ViewImports html \u6587\u4ef6\u3002\u5b50\u6587\u4ef6\u5939\u4e2d\u7684\u6587\u4ef6\u5728\u6839 Pages \u6587\u4ef6\u5939\u4e2d\u7684\u6587\u4ef6\u4e4b\u540e\u8fd0\u884c\u3002<\/p>\n<blockquote>\n<p>Partial views, layouts, and AJAX<br \/>\n\u5206\u90e8\u89c6\u56fe\u3001\u5e03\u5c40\u548c AJAX<\/p>\n<p>This chapter describes using Razor to render full HTML pages server-side, which are then sent to the user\u2019s browser in traditional web apps. A common alternative approach when building web apps is to use a JavaScript client-side framework to build an SPA, which renders the HTML client-side in the browser.<br \/>\n\u672c\u7ae0\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528 Razor \u5728\u670d\u52a1\u5668\u7aef\u5448\u73b0\u5b8c\u6574\u7684 HTML \u9875\u9762\uff0c\u7136\u540e\u5c06\u5176\u53d1\u9001\u5230\u4f20\u7edf Web \u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u7528\u6237\u6d4f\u89c8\u5668\u3002\u6784\u5efa Web \u5e94\u7528\u7a0b\u5e8f\u65f6\uff0c\u4e00\u79cd\u5e38\u89c1\u7684\u66ff\u4ee3\u65b9\u6cd5\u662f\u4f7f\u7528 JavaScript \u5ba2\u6237\u7aef\u6846\u67b6\u6784\u5efa SPA\uff0c\u8be5 SPA \u5728\u6d4f\u89c8\u5668\u4e2d\u5448\u73b0 HTML \u5ba2\u6237\u7aef\u3002<\/p>\n<p>One of the technologies SPAs typically use is AJAX (Asynchronous JavaScript and XML), in which the browser sends requests to your ASP.NET Core app without reloading a whole new page. It\u2019s also possible to use AJAX requests with apps that use server-side rendering. To do so, you\u2019d use JavaScript to request an update for part of a page.<br \/>\nSPA \u901a\u5e38\u4f7f\u7528\u7684\u6280\u672f\u4e4b\u4e00\u662f AJAX\uff08\u5f02\u6b65 JavaScript \u548c XML\uff09\uff0c\u5728\u8fd9\u79cd\u6280\u672f\u4e2d\uff0c\u6d4f\u89c8\u5668\u5c06\u8bf7\u6c42\u53d1\u9001\u5230\u60a8\u7684 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\uff0c\u800c\u65e0\u9700\u91cd\u65b0\u52a0\u8f7d\u5168\u65b0\u7684\u9875\u9762\u3002\u8fd8\u53ef\u4ee5\u5c06 AJAX \u8bf7\u6c42\u4e0e\u4f7f\u7528\u670d\u52a1\u5668\u7aef\u6e32\u67d3\u7684\u5e94\u7528\u7a0b\u5e8f\u4e00\u8d77\u4f7f\u7528\u3002\u4e3a\u6b64\uff0c\u60a8\u9700\u8981\u4f7f\u7528 JavaScript \u8bf7\u6c42\u66f4\u65b0\u9875\u9762\u7684\u4e00\u90e8\u5206\u3002<\/p>\n<p>If you want to use AJAX with an app that uses Razor, you should consider making extensive use of partial views. Then you can expose these via additional Razor Page handlers, as shown in this article: <a href=\"http:\/\/mng.bz\/vzB1\">http:\/\/mng.bz\/vzB1<\/a>. Using AJAX can reduce the overall amount of data that needs to be sent back and forth between the browser and your app, and it can make your app feel smoother and more responsive, as it requires fewer full-page loads. But using AJAX with Razor can add complexity, especially for larger apps. If you foresee yourself making extensive use of AJAX to build a highly dynamic web app, you might want to consider using minimal APIs or web API controllers with a client-side framework, or consider using Blazor instead.<br \/>\n\u5982\u679c\u8981\u5c06 AJAX \u4e0e\u4f7f\u7528 Razor \u7684\u5e94\u7528\u7a0b\u5e8f\u4e00\u8d77\u4f7f\u7528\uff0c\u5219\u5e94\u8003\u8651\u5e7f\u6cdb\u4f7f\u7528\u5206\u90e8\u89c6\u56fe\u3002\u7136\u540e\uff0c\u60a8\u53ef\u4ee5\u901a\u8fc7\u5176\u4ed6 Razor Page \u5904\u7406\u7a0b\u5e8f\u516c\u5f00\u8fd9\u4e9b\u5185\u5bb9\uff0c\u5982\u672c\u6587\u6240\u793a\uff1a<a href=\"http:\/\/mng.bz\/vzB1\u3002\u4f7f\u7528\">http:\/\/mng.bz\/vzB1\u3002\u4f7f\u7528<\/a> AJAX \u53ef\u4ee5\u51cf\u5c11\u9700\u8981\u5728\u6d4f\u89c8\u5668\u548c\u5e94\u7528\u7a0b\u5e8f\u4e4b\u95f4\u6765\u56de\u53d1\u9001\u7684\u6570\u636e\u603b\u91cf\uff0c\u5e76\u4e14\u53ef\u4ee5\u4f7f\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u611f\u89c9\u66f4\u6d41\u7545\u3001\u54cd\u5e94\u66f4\u5feb\uff0c\u56e0\u4e3a\u5b83\u9700\u8981\u7684\u6574\u9875\u52a0\u8f7d\u66f4\u5c11\u3002\u4f46\u662f\uff0c\u5c06 AJAX \u4e0e Razor \u7ed3\u5408\u4f7f\u7528\u53ef\u80fd\u4f1a\u589e\u52a0\u590d\u6742\u6027\uff0c\u5c24\u5176\u662f\u5bf9\u4e8e\u8f83\u5927\u7684\u5e94\u7528\u7a0b\u5e8f\u3002\u5982\u679c\u4f60\u9884\u89c1\u5230\u81ea\u5df1\u4f1a\u5e7f\u6cdb\u4f7f\u7528 AJAX \u6765\u6784\u5efa\u9ad8\u5ea6\u52a8\u6001\u7684 Web \u5e94\u7528\uff0c\u5219\u53ef\u80fd\u9700\u8981\u8003\u8651\u5c06\u6700\u5c11\u7684 API \u6216 Web API \u63a7\u5236\u5668\u4e0e\u5ba2\u6237\u7aef\u6846\u67b6\u7ed3\u5408\u4f7f\u7528\uff0c\u6216\u8005\u8003\u8651\u6539\u7528 Blazor\u3002<\/p>\n<\/blockquote>\n<p>That concludes our first look at rendering HTML using the Razor templating engine. In the next chapter you\u2019ll learn about Tag Helpers and how to use them to build HTML forms, a staple of modern web applications. Tag Helpers are one of the biggest improvements to Razor in ASP.NET Core over legacy ASP.NET, so getting to grips with them will make editing your views an overall more pleasant experience!<br \/>\n\u6211\u4eec\u7b2c\u4e00\u6b21\u4f7f\u7528 Razor \u6a21\u677f\u5f15\u64ce\u6e32\u67d3 HTML \u5230\u6b64\u7ed3\u675f\u3002\u5728\u4e0b\u4e00\u7ae0\u4e2d\uff0c\u60a8\u5c06\u4e86\u89e3\u6807\u8bb0\u5e2e\u52a9\u7a0b\u5e8f\u4ee5\u53ca\u5982\u4f55\u4f7f\u7528\u5b83\u4eec\u6765\u6784\u5efa HTML \u8868\u5355\uff0c\u8fd9\u662f\u73b0\u4ee3 Web \u5e94\u7528\u7a0b\u5e8f\u7684\u4e3b\u8981\u5185\u5bb9\u3002\u6807\u7b7e\u5e2e\u52a9\u7a0b\u5e8f\u662f ASP.NET Core \u4e2d Razor \u76f8\u5bf9\u4e8e\u65e7\u7248 ASP.NET \u7684\u6700\u5927\u6539\u8fdb\u4e4b\u4e00\uff0c\u56e0\u6b64\u638c\u63e1\u5b83\u4eec\u5c06\u4f7f\u7f16\u8f91\u89c6\u56fe\u7684\u6574\u4f53\u4f53\u9a8c\u66f4\u52a0\u6109\u5feb\uff01<\/p>\n<h2>17.5 Summary<\/h2>\n<p>17.5 \u603b\u7ed3<\/p>\n<p>Razor is a templating language that allows you to generate dynamic HTML using a mixture of HTML and C#. This provides the power of C# without your having to build up an HTML response manually using strings.<br \/>\nRazor \u662f\u4e00\u79cd\u6a21\u677f\u8bed\u8a00\uff0c\u5141\u8bb8\u60a8\u4f7f\u7528 HTML \u548c C# \u7684\u6df7\u5408\u751f\u6210\u52a8\u6001 HTML\u3002\u8fd9\u63d0\u4f9b\u4e86 C# \u7684\u5f3a\u5927\u529f\u80fd\uff0c\u800c\u65e0\u9700\u4f7f\u7528\u5b57\u7b26\u4e32\u624b\u52a8\u6784\u5efa HTML \u54cd\u5e94\u3002<\/p>\n<p>Razor Pages can pass strongly typed data to a Razor view by setting public properties on the PageModel. To access the properties on the view model, the view should declare the model type using the @model directive.<br \/>\nRazor Pages \u53ef\u4ee5\u901a\u8fc7\u5728 PageModel \u4e0a\u8bbe\u7f6e\u516c\u5171\u5c5e\u6027\uff0c\u5c06\u5f3a\u7c7b\u578b\u6570\u636e\u4f20\u9012\u7ed9 Razor \u89c6\u56fe\u3002\u8981\u8bbf\u95ee\u89c6\u56fe\u6a21\u578b\u4e0a\u7684\u5c5e\u6027\uff0c\u89c6\u56fe\u5e94\u4f7f\u7528 @model \u6307\u4ee4\u58f0\u660e\u6a21\u578b\u7c7b\u578b\u3002<\/p>\n<p>Page handlers can pass key-value pairs to the view using the ViewData dictionary. This is useful for implicitly passing shared data to layouts and partial views.<br \/>\n\u9875\u9762\u5904\u7406\u7a0b\u5e8f\u53ef\u4ee5\u4f7f\u7528 ViewData \u5b57\u5178\u5c06\u952e\u503c\u5bf9\u4f20\u9012\u7ed9\u89c6\u56fe\u3002\u8fd9\u5bf9\u4e8e\u5c06\u5171\u4eab\u6570\u636e\u9690\u5f0f\u4f20\u9012\u7ed9\u5e03\u5c40\u548c\u5206\u90e8\u89c6\u56fe\u975e\u5e38\u6709\u7528\u3002<\/p>\n<p>Razor expressions render C# values to the HTML output using @ or @(). You don\u2019t need to include a semicolon after the statement when using Razor expressions.<br \/>\nRazor \u8868\u8fbe\u5f0f\u4f7f\u7528 @ \u6216 @\uff08\uff09 \u5c06 C# \u503c\u5448\u73b0\u5230 HTML \u8f93\u51fa\u3002\u4f7f\u7528 Razor \u8868\u8fbe\u5f0f\u65f6\uff0c\u65e0\u9700\u5728\u8bed\u53e5\u540e\u5305\u542b\u5206\u53f7\u3002<\/p>\n<p>Razor code blocks, defined using @{}, execute C# without outputting HTML. The C# in Razor code blocks must be complete statements, so it must include semicolons.<br \/>\n\u4f7f\u7528 @{} \u5b9a\u4e49\u7684 Razor \u4ee3\u7801\u5757\u6267\u884c C# \u800c\u4e0d\u8f93\u51fa HTML\u3002Razor \u4ee3\u7801\u5757\u4e2d\u7684 C# \u5fc5\u987b\u662f\u5b8c\u6574\u8bed\u53e5\uff0c\u56e0\u6b64\u5b83\u5fc5\u987b\u5305\u542b\u5206\u53f7\u3002<\/p>\n<p>Loops and conditionals can be used to easily generate dynamic HTML in templates, but it\u2019s a good idea to limit the number of if statements in particular, to keep your views easy to read.<br \/>\n\u5faa\u73af\u548c\u6761\u4ef6\u53ef\u7528\u4e8e\u5728\u6a21\u677f\u4e2d\u8f7b\u677e\u751f\u6210\u52a8\u6001 HTML\uff0c\u4f46\u6700\u597d\u7279\u522b\u9650\u5236 if \u8bed\u53e5\u7684\u6570\u91cf\uff0c\u4ee5\u4fdd\u6301\u89c6\u56fe\u6613\u4e8e\u9605\u8bfb\u3002<\/p>\n<p>If you need to render a string as raw HTML you can use Html.Raw, but do so sparingly; rendering raw user input can create a security vulnerability in your application.<br \/>\n\u5982\u679c\u9700\u8981\u5c06\u5b57\u7b26\u4e32\u5448\u73b0\u4e3a\u539f\u59cb HTML\uff0c\u5219\u53ef\u4ee5\u4f7f\u7528 Html.Raw\uff0c\u4f46\u8981\u8c28\u614e\u4f7f\u7528;\u5448\u73b0\u539f\u59cb\u7528\u6237\u8f93\u5165\u53ef\u80fd\u4f1a\u5728\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u4e2d\u521b\u5efa\u5b89\u5168\u6f0f\u6d1e\u3002<\/p>\n<p>Tag Helpers allow you to bind your data model to HTML elements, making it easier to generate dynamic HTML while staying editor-friendly.<br \/>\n\u6807\u7b7e\u5e2e\u52a9\u7a0b\u5e8f\u5141\u8bb8\u60a8\u5c06\u6570\u636e\u6a21\u578b\u7ed1\u5b9a\u5230 HTML \u5143\u7d20\uff0c\u4ece\u800c\u66f4\u8f7b\u677e\u5730\u751f\u6210\u52a8\u6001 HTML\uff0c\u540c\u65f6\u4fdd\u6301\u7f16\u8f91\u5668\u53cb\u597d\u6027\u3002<\/p>\n<p>You can place HTML common to multiple views in a layout to reduce duplication. The layout will render any content from the child view at the location @RenderBody is called.<br \/>\n\u60a8\u53ef\u4ee5\u5c06\u591a\u4e2a\u89c6\u56fe\u901a\u7528\u7684 HTML \u653e\u7f6e\u5728\u5e03\u5c40\u4e2d\uff0c\u4ee5\u51cf\u5c11\u91cd\u590d\u3002\u5e03\u5c40\u5c06\u5728\u8c03\u7528\u5b50\u89c6\u56fe\u7684\u4f4d\u7f6e\u5448\u73b0\u5b50\u89c6\u56fe\u4e2d\u7684\u4efb\u4f55\u5185\u5bb9@RenderBody\u3002<\/p>\n<p>Encapsulate commonly used snippets of Razor code in a partial view. A partial view can be rendered using the <partial \/> tag.<br \/>\n\u5728\u5206\u90e8\u89c6\u56fe\u4e2d\u5c01\u88c5 Razor \u4ee3\u7801\u7684\u5e38\u7528\u4ee3\u7801\u7247\u6bb5\u3002\u53ef\u4ee5\u4f7f\u7528 tag \u5448\u73b0\u90e8\u5206\u89c6\u56fe\u3002<\/p>\n<p>_ViewImports.cshtml can be used to include common directives, such as @using statements, in every view.<br \/>\n_ViewImports.cshtml \u53ef\u7528\u4e8e\u5728\u6bcf\u4e2a\u89c6\u56fe\u4e2d\u5305\u542b\u5e38\u89c1\u6307\u4ee4\uff0c\u4f8b\u5982 @using \u8bed\u53e5\u3002<\/p>\n<p>_ViewStart.cshtml is called before the execution of each Razor Page and can be used to execute code common to all Razor Pages, such as setting a default layout page. It doesn\u2019t execute for layouts or partial views.<br \/>\n_ViewStart.cshtml \u5728\u6267\u884c\u6bcf\u4e2a Razor \u9875\u9762\u4e4b\u524d\u8c03\u7528\uff0c\u53ef\u7528\u4e8e\u6267\u884c\u6240\u6709 Razor \u9875\u9762\u901a\u7528\u7684\u4ee3\u7801\uff0c\u4f8b\u5982\u8bbe\u7f6e\u9ed8\u8ba4\u5e03\u5c40\u9875\u9762\u3002\u5b83\u4e0d\u4f1a\u5bf9\u5e03\u5c40\u6216\u5206\u90e8\u89c6\u56fe\u6267\u884c\u3002<\/p>\n<p>_ViewImports.cshtml and _ViewStart.cshtml are hierarchical. Files in the root folder execute first, followed by files in controller-specific view folders.<br \/>\n_ViewImports.cshtml \u548c _ViewStart.cshtml \u662f\u5206\u5c42\u7684\u3002\u9996\u5148\u6267\u884c\u6839\u6587\u4ef6\u5939\u4e2d\u7684\u6587\u4ef6\uff0c\u7136\u540e\u662f\u7279\u5b9a\u4e8e\u63a7\u5236\u5668\u7684\u89c6\u56fe\u6587\u4ef6\u5939\u4e2d\u7684\u6587\u4ef6\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>17 Rendering HTML using Razor views 17 \u4f7f\u7528 Razor \u89c6\u56fe\u5448\u73b0 HTML This chapter covers \u672c\u7ae0\u6db5\u76d6 \u2022 Creating Razor views to display HTML to a user \u521b\u5efa Razor \u89c6\u56fe\u4ee5\u5411\u7528\u6237\u663e\u793a HTML \u2022 Using C# and the Razor markup syntax to generate HTML dynamically \u4f7f\u7528 C# \u548c Razor \u6807\u8bb0\u8bed\u6cd5\u52a8\u6001\u751f\u6210 HTML \u2022 Reusing common code with layouts and partial [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-605","post","type-post","status-publish","format-standard","hentry","category-csharp"],"_links":{"self":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/605","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=605"}],"version-history":[{"count":0,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/605\/revisions"}],"wp:attachment":[{"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=605"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=605"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=605"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}