{"id":576,"date":"2025-04-05T03:24:33","date_gmt":"2025-04-04T19:24:33","guid":{"rendered":"https:\/\/www.hyy.net\/?p=576"},"modified":"2025-04-05T03:24:33","modified_gmt":"2025-04-04T19:24:33","slug":"asp-net-core-in-action-4-handling-requests-with-the-middleware-pipeline","status":"publish","type":"post","link":"https:\/\/diji.net\/?p=576","title":{"rendered":"ASP.NET Core in Action 4 Handling requests with the middleware pipeline"},"content":{"rendered":"<h1>4 Handling requests with the middleware pipeline<\/h1>\n<p>\u4f7f\u7528\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5904\u7406\u8bf7\u6c42<\/p>\n<h2>This chapter covers<\/h2>\n<h2>\u672c\u7ae0\u6db5\u76d6<\/h2>\n<ul>\n<li>Understanding middleware<br \/>\n\u4e86\u89e3\u4e2d\u95f4\u4ef6<\/li>\n<li>Serving static files using middleware<br \/>\n\u4f7f\u7528\u4e2d\u95f4\u4ef6\u63d0\u4f9b\u9759\u6001\u6587\u4ef6<\/li>\n<li>Adding functionality using middleware<br \/>\n\u4f7f\u7528\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u529f\u80fd<\/li>\n<li>Combining middleware to form a pipeline<br \/>\n\u7ec4\u5408\u4e2d\u95f4\u4ef6\u5f62\u6210\u7ba1\u9053<\/li>\n<li>Handling exceptions and errors with middleware<br \/>\n\u4f7f\u7528\u4e2d\u95f4\u4ef6\u5904\u7406\u5f02\u5e38\u548c\u9519\u8bef<\/li>\n<\/ul>\n<p>In chapter 3 you had a whistle-stop tour of a complete ASP.NET Core application to see how the components come together to create a web application. In this chapter, we\u2019ll focus on one small subsection: the middleware pipeline.<\/p>\n<p>\u5728\u7b2c 3 \u7ae0\u4e2d\uff0c\u60a8\u7b80\u8981\u4ecb\u7ecd\u4e86\u4e00\u4e2a\u5b8c\u6574\u7684 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\uff0c\u4ee5\u4e86\u89e3\u8fd9\u4e9b\u7ec4\u4ef6\u5982\u4f55\u7ec4\u5408\u5728\u4e00\u8d77\u4ee5\u521b\u5efa Web \u5e94\u7528\u7a0b\u5e8f\u3002\u5728\u672c\u7ae0\u4e2d\uff0c\u6211\u4eec\u5c06\u91cd\u70b9\u4ecb\u7ecd\u4e00\u4e2a\u5c0f\u90e8\u5206\uff1a\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002<\/p>\n<p>In ASP.NET Core, middleware consists of C# classes or functions that handle an HTTP request or response. Middleware is chained together, with the output of one acting as the input to the next to form a pipeline.<\/p>\n<p>\u5728 ASP.NET Core \u4e2d\uff0c\u4e2d\u95f4\u4ef6\u7531\u5904\u7406 HTTP \u8bf7\u6c42\u6216\u54cd\u5e94\u7684 C# \u7c7b\u6216\u51fd\u6570\u7ec4\u6210\u3002\u4e2d\u95f4\u4ef6\u94fe\u63a5\u5728\u4e00\u8d77\uff0c\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u7684\u8f93\u51fa\u5145\u5f53\u4e0b\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u7684\u8f93\u5165\uff0c\u5f62\u6210\u4e00\u4e2a\u7ba1\u9053\u3002<\/p>\n<p>The middleware pipeline is one of the most important parts of configuration for defining how your application behaves and how it responds to requests. Understanding how to build and compose middleware is key to adding functionality to your applications.<\/p>\n<p>\u4e2d\u95f4\u4ef6\u7ba1\u9053\u662f\u914d\u7f6e\u4e2d\u6700\u91cd\u8981\u7684\u90e8\u5206\u4e4b\u4e00\uff0c\u7528\u4e8e\u5b9a\u4e49\u5e94\u7528\u7a0b\u5e8f\u7684\u884c\u4e3a\u65b9\u5f0f\u548c\u54cd\u5e94\u8bf7\u6c42\u7684\u65b9\u5f0f\u3002\u4e86\u89e3\u5982\u4f55\u6784\u5efa\u548c\u7ec4\u5408\u4e2d\u95f4\u4ef6\u662f\u5411\u5e94\u7528\u7a0b\u5e8f\u6dfb\u52a0\u529f\u80fd\u7684\u5173\u952e\u3002<\/p>\n<p>In this chapter you\u2019ll learn what middleware is and how to use it to create a pipeline. You\u2019ll see how you can chain multiple middleware components together, with each component adding a discrete piece of functionality. The examples in this chapter are limited to using existing middleware components, showing how to arrange them in the correct way for your application. In chapter 31 you\u2019ll learn how to build your own middleware components and incorporate them into the pipeline.<\/p>\n<p>\u5728\u672c\u7ae0\u4e2d\uff0c\u60a8\u5c06\u4e86\u89e3\u4ec0\u4e48\u662f\u4e2d\u95f4\u4ef6\u4ee5\u53ca\u5982\u4f55\u4f7f\u7528\u5b83\u6765\u521b\u5efa\u7ba1\u9053\u3002\u60a8\u5c06\u4e86\u89e3\u5982\u4f55\u5c06\u591a\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u94fe\u63a5\u5728\u4e00\u8d77\uff0c\u6bcf\u4e2a\u7ec4\u4ef6\u6dfb\u52a0\u4e00\u4e2a\u72ec\u7acb\u7684\u529f\u80fd\u3002\u672c\u7ae0\u4e2d\u7684\u793a\u4f8b\u4ec5\u9650\u4e8e\u4f7f\u7528\u73b0\u6709\u7684\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\uff0c\u5c55\u793a\u4e86\u5982\u4f55\u4e3a\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u4ee5\u6b63\u786e\u7684\u65b9\u5f0f\u6392\u5217\u5b83\u4eec\u3002\u5728\u7b2c 31 \u7ae0\u4e2d\uff0c\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u6784\u5efa\u81ea\u5df1\u7684\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u5e76\u5c06\u5176\u5408\u5e76\u5230\u7ba1\u9053\u4e2d\u3002<\/p>\n<p>We\u2019ll begin by looking at the concept of middleware, all the things you can achieve with it, and how a middleware component often maps to a cross-cutting concern. These functions of an application cut across multiple different layers. Logging, error handling, and security are classic cross-cutting concerns that are required by many parts of your application. Because all requests pass through the middleware pipeline, it\u2019s the preferred location to configure and handle this functionality.<\/p>\n<p>\u6211\u4eec\u9996\u5148\u8981\u4e86\u89e3\u4e2d\u95f4\u4ef6\u7684\u6982\u5ff5\uff0c\u4f60\u53ef\u4ee5\u7528\u5b83\u5b9e\u73b0\u7684\u6240\u6709\u4e8b\u60c5\uff0c\u4ee5\u53ca\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u901a\u5e38\u5982\u4f55\u6620\u5c04\u5230\u4e00\u4e2a\u6a2a\u5207\u5173\u6ce8\u70b9\u3002\u5e94\u7528\u7a0b\u5e8f\u7684\u8fd9\u4e9b\u529f\u80fd\u8de8\u8d8a\u591a\u4e2a\u4e0d\u540c\u7684\u5c42\u3002\u65e5\u5fd7\u8bb0\u5f55\u3001\u9519\u8bef\u5904\u7406\u548c\u5b89\u5168\u6027\u662f\u5e94\u7528\u7a0b\u5e8f\u7684\u8bb8\u591a\u90e8\u5206\u90fd\u9700\u8981\u7684\u5178\u578b\u6a2a\u5207\u5173\u6ce8\u70b9\u3002\u7531\u4e8e\u6240\u6709\u8bf7\u6c42\u90fd\u901a\u8fc7\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4f20\u9012\uff0c\u56e0\u6b64\u5b83\u662f\u914d\u7f6e\u548c\u5904\u7406\u6b64\u529f\u80fd\u7684\u9996\u9009\u4f4d\u7f6e\u3002<\/p>\n<p>In section 4.2 I\u2019ll explain how you can compose individual middleware components into a pipeline. You\u2019ll start out small, with a web app that displays only a holding page. From there, you\u2019ll learn how to build a simple static-file server that returns requested files from a folder on disk.<\/p>\n<p>\u5728 Section 4.2 \u4e2d\uff0c\u6211\u5c06\u89e3\u91ca\u5982\u4f55\u5c06\u5355\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u7ec4\u5408\u5230\u4e00\u4e2a\u7ba1\u9053\u4e2d\u3002\u60a8\u5c06\u4ece\u5c0f\u89c4\u6a21\u5f00\u59cb\uff0c\u4f7f\u7528\u4ec5\u663e\u793a\u4fdd\u7559\u9875\u7684 Web \u5e94\u7528\u7a0b\u5e8f\u3002\u4ece\u90a3\u91cc\uff0c\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u6784\u5efa\u4e00\u4e2a\u7b80\u5355\u7684\u9759\u6001\u6587\u4ef6\u670d\u52a1\u5668\uff0c\u8be5\u670d\u52a1\u5668\u4ece\u78c1\u76d8\u4e0a\u7684\u6587\u4ef6\u5939\u8fd4\u56de\u8bf7\u6c42\u7684\u6587\u4ef6\u3002<\/p>\n<p>Next, you\u2019ll move on to a more complex pipeline containing multiple middleware. In this example you\u2019ll explore the importance of ordering in the middleware pipeline, and you\u2019ll see how requests are handled when your pipeline contains multiple middleware.<\/p>\n<p>\u63a5\u4e0b\u6765\uff0c\u60a8\u5c06\u8f6c\u5230\u5305\u542b\u591a\u4e2a\u4e2d\u95f4\u4ef6\u7684\u66f4\u590d\u6742\u7684\u7ba1\u9053\u3002\u5728\u6b64\u793a\u4f8b\u4e2d\uff0c\u60a8\u5c06\u63a2\u7d22\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4e2d\u6392\u5e8f\u7684\u91cd\u8981\u6027\uff0c\u5e76\u4e86\u89e3\u5f53\u7ba1\u9053\u5305\u542b\u591a\u4e2a\u4e2d\u95f4\u4ef6\u65f6\u5982\u4f55\u5904\u7406\u8bf7\u6c42\u3002<\/p>\n<p>In section 4.3 you\u2019ll learn how you can use middleware to deal with an important aspect of any application: error handling. Errors are a fact of life for all applications, so it\u2019s important that you account for them when building your app.<\/p>\n<p>\u5728 Section 4.3 \u4e2d\uff0c\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u4f7f\u7528 middleware \u6765\u5904\u7406\u4efb\u4f55\u5e94\u7528\u7a0b\u5e8f\u7684\u4e00\u4e2a\u91cd\u8981\u65b9\u9762\uff1a\u9519\u8bef\u5904\u7406\u3002\u9519\u8bef\u662f\u6240\u6709\u5e94\u7528\u7a0b\u5e8f\u90fd\u4e0d\u53ef\u907f\u514d\u7684\u4e8b\u5b9e\uff0c\u56e0\u6b64\u5728\u6784\u5efa\u5e94\u7528\u7a0b\u5e8f\u65f6\u8003\u8651\u9519\u8bef\u975e\u5e38\u91cd\u8981\u3002<\/p>\n<p>You can handle errors in a few ways. Errors are among the classic cross-cutting concerns, and middleware is well placed to provide the required functionality. In section 4.3 I\u2019ll show how you can handle exceptions with middleware provided by Microsoft. In particular, you\u2019ll learn about two different components:<\/p>\n<p>\u60a8\u53ef\u4ee5\u901a\u8fc7\u591a\u79cd\u65b9\u5f0f\u5904\u7406\u9519\u8bef\u3002\u9519\u8bef\u662f\u5178\u578b\u7684\u6a2a\u5207\u5173\u6ce8\u70b9\u4e4b\u4e00\uff0c\u4e2d\u95f4\u4ef6\u53ef\u4ee5\u5f88\u597d\u5730\u63d0\u4f9b\u6240\u9700\u7684\u529f\u80fd\u3002\u5728 Section 4.3 \u4e2d\uff0c\u6211\u5c06\u5c55\u793a\u5982\u4f55\u4f7f\u7528 Microsoft \u63d0\u4f9b\u7684\u4e2d\u95f4\u4ef6\u5904\u7406\u5f02\u5e38\u3002\u5177\u4f53\u800c\u8a00\uff0c\u60a8\u5c06\u4e86\u89e3\u4e24\u4e2a\u4e0d\u540c\u7684\u7ec4\u4ef6\uff1a<\/p>\n<ul>\n<li>\n<p>DeveloperExceptionPageMiddleware\u2014Provides quick error feedback when building an application<br \/>\nDeveloperExceptionPageMiddleware\u2014 \u5728\u6784\u5efa\u5e94\u7528\u7a0b\u5e8f\u65f6\u63d0\u4f9b\u5feb\u901f\u9519\u8bef\u53cd\u9988<\/p>\n<\/li>\n<li>\n<p>ExceptionHandlerMiddleware\u2014Provides a generic error page in production so that you don\u2019t leak any sensitive details<br \/>\nExceptionHandlerMiddleware- \u5728\u751f\u4ea7\u4e2d\u63d0\u4f9b\u901a\u7528\u9519\u8bef\u9875\u9762\uff0c\u4ee5\u4fbf\u60a8\u4e0d\u4f1a\u6cc4\u9732\u4efb\u4f55\u654f\u611f\u8be6\u7ec6\u4fe1\u606f<\/p>\n<\/li>\n<\/ul>\n<p>You won\u2019t see how to build your own middleware in this chapter; instead, you\u2019ll see that you can go a long way by using the components provided as part of ASP.NET Core. When you understand the middleware pipeline and its behavior, you\u2019ll find it much easier to understand when and why custom middleware is required. With that in mind, let\u2019s dive in!<\/p>\n<p>\u5728\u672c\u7ae0\u4e2d\uff0c\u60a8\u4e0d\u4f1a\u770b\u5230\u5982\u4f55\u6784\u5efa\u81ea\u5df1\u7684\u4e2d\u95f4\u4ef6;\u76f8\u53cd\uff0c\u60a8\u4f1a\u53d1\u73b0\uff0c\u901a\u8fc7\u4f7f\u7528\u4f5c\u4e3a ASP.NET Core \u7684\u4e00\u90e8\u5206\u63d0\u4f9b\u7684\u7ec4\u4ef6\uff0c\u60a8\u53ef\u4ee5\u8d70\u5f88\u957f\u4e00\u6bb5\u8def\u3002\u5f53\u60a8\u4e86\u89e3\u4e2d\u95f4\u4ef6\u7ba1\u9053\u53ca\u5176\u884c\u4e3a\u65f6\uff0c\u60a8\u4f1a\u53d1\u73b0\u66f4\u5bb9\u6613\u7406\u89e3\u4f55\u65f6\u4ee5\u53ca\u4e3a\u4ec0\u4e48\u9700\u8981\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6\u3002\u8003\u8651\u5230\u8fd9\u4e00\u70b9\uff0c\u8ba9\u6211\u4eec\u5f00\u59cb\u5427\uff01<\/p>\n<h3>4.1 Defining middleware<\/h3>\n<h3>4.1 \u5b9a\u4e49\u4e2d\u95f4\u4ef6<\/h3>\n<p>The word middleware is used in a variety of contexts in software development and IT, but it\u2019s not a particularly descriptive word.<\/p>\n<p>\u4e2d\u95f4\u4ef6\u8fd9\u4e2a\u8bcd\u5728\u8f6f\u4ef6\u5f00\u53d1\u548c IT \u4e2d\u7684\u5404\u79cd\u4e0a\u4e0b\u6587\u4e2d\u90fd\u6709\u4f7f\u7528\uff0c\u4f46\u5b83\u4e0d\u662f\u4e00\u4e2a\u7279\u522b\u5177\u6709\u63cf\u8ff0\u6027\u7684\u8bcd\u3002<\/p>\n<p>In ASP.NET Core, middleware is C# classes[1] that can handle an HTTP request or response. Middleware can<br \/>\n\u5728 ASP.NET Core \u4e2d\uff0c\u4e2d\u95f4\u4ef6\u662f\u53ef\u4ee5\u5904\u7406 HTTP \u8bf7\u6c42\u6216\u54cd\u5e94\u7684 C# \u7c7b[1]\u3002\u4e2d\u95f4\u4ef6\u53ef\u4ee5<\/p>\n<ul>\n<li>\n<p>Handle an incoming HTTP request by generating an HTTP response<br \/>\n\u901a\u8fc7\u751f\u6210 HTTP \u54cd\u5e94\u6765\u5904\u7406\u4f20\u5165\u7684 HTTP \u8bf7\u6c42<\/p>\n<\/li>\n<li>\n<p>Process an incoming HTTP request, modify it, and pass it on to another piece of middleware<br \/>\n\u5904\u7406\u4f20\u5165\u7684 HTTP \u8bf7\u6c42\uff0c\u5bf9\u5176\u8fdb\u884c\u4fee\u6539\uff0c\u5e76\u5c06\u5176\u4f20\u9012\u7ed9\u53e6\u4e00\u4e2a\u4e2d\u95f4\u4ef6<\/p>\n<\/li>\n<li>\n<p>Process an outgoing HTTP response, modify it, and pass it on to another piece of middleware or to the ASP.NET Core web server<br \/>\n\u5904\u7406\u4f20\u51fa\u7684 HTTP \u54cd\u5e94\uff0c\u5bf9\u5176\u8fdb\u884c\u4fee\u6539\uff0c\u5e76\u5c06\u5176\u4f20\u9012\u7ed9\u53e6\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u6216 ASP.NET Core Web \u670d\u52a1\u5668<\/p>\n<\/li>\n<\/ul>\n<p>You can use middleware in a multitude of ways in your own applications. A piece of logging middleware, for example, might note when a request arrived and then pass it on to another piece of middleware. Meanwhile, a static-file middleware component might spot an incoming request for an image with a specific name, load the image from disk, and send it back to the user without passing it on.<\/p>\n<p>\u60a8\u53ef\u4ee5\u5728\u81ea\u5df1\u7684\u5e94\u7528\u7a0b\u5e8f\u4e2d\u4ee5\u591a\u79cd\u65b9\u5f0f\u4f7f\u7528\u4e2d\u95f4\u4ef6\u3002\u4f8b\u5982\uff0c\u4e00\u4e2a\u65e5\u5fd7\u8bb0\u5f55\u4e2d\u95f4\u4ef6\u53ef\u80fd\u4f1a\u8bb0\u5f55\u8bf7\u6c42\u4f55\u65f6\u5230\u8fbe\uff0c\u7136\u540e\u5c06\u5176\u4f20\u9012\u7ed9\u53e6\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u3002\u540c\u65f6\uff0c\u9759\u6001\u6587\u4ef6\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u53ef\u80fd\u4f1a\u53d1\u73b0\u5bf9\u5177\u6709\u7279\u5b9a\u540d\u79f0\u7684\u56fe\u50cf\u7684\u4f20\u5165\u8bf7\u6c42\uff0c\u4ece\u78c1\u76d8\u52a0\u8f7d\u56fe\u50cf\uff0c\u5e76\u5c06\u5176\u53d1\u9001\u56de\u7ed9\u7528\u6237\uff0c\u800c\u65e0\u9700\u4f20\u9012\u3002<\/p>\n<p>The most important piece of middleware in most ASP.NET Core applications is the EndpointMiddleware class. This class normally generates all your HTML and JavaScript Object Notation (JSON) responses, and is the focus of most of this book. Like image-resizing middleware, it typically receives a request, generates a response, and then sends it back to the user (figure 4.1).<\/p>\n<p>\u5728\u5927\u591a\u6570 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u4e2d\uff0c\u6700\u91cd\u8981\u7684\u4e2d\u95f4\u4ef6\u662f\u7c7b\u3002\u6b64\u7c7b\u901a\u5e38\u4f1a\u751f\u6210\u6240\u6709 HTML \u548c JavaScript \u5bf9\u8c61\u8868\u793a\u6cd5 \uff08JSON\uff09 \u54cd\u5e94\uff0c\u5e76\u4e14\u662f\u672c\u4e66\u5927\u90e8\u5206\u5185\u5bb9\u7684\u91cd\u70b9\u3002\u4e0e\u56fe\u50cf\u5927\u5c0f\u8c03\u6574\u4e2d\u95f4\u4ef6\u4e00\u6837\uff0c\u5b83\u901a\u5e38\u63a5\u6536\u8bf7\u6c42\uff0c\u751f\u6210\u54cd\u5e94\uff0c\u7136\u540e\u5c06\u5176\u53d1\u9001\u56de\u7ed9\u7528\u6237\uff08\u56fe 4.1\uff09\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0401.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.1 Example of a middleware pipeline. Each middleware component handles the request and passes it on to the next middleware component in the pipeline. After a middleware component generates a response, it passes the response back through the pipeline. When it reaches the ASP.NET Core web server, the response is sent to the user\u2019s browser.<br \/>\n\u56fe 4.1 \u4e2d\u95f4\u4ef6\u7ba1\u9053\u793a\u4f8b\u3002\u6bcf\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u90fd\u5904\u7406\u8bf7\u6c42\u5e76\u5c06\u5176\u4f20\u9012\u7ed9\u7ba1\u9053\u4e2d\u7684\u4e0b\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u3002\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u751f\u6210\u54cd\u5e94\u540e\uff0c\u5b83\u4f1a\u901a\u8fc7\u7ba1\u9053\u5c06\u54cd\u5e94\u4f20\u56de\u3002\u5f53\u5b83\u5230\u8fbe ASP.NET Core Web \u670d\u52a1\u5668\u65f6\uff0c\u54cd\u5e94\u5c06\u53d1\u9001\u5230\u7528\u6237\u7684\u6d4f\u89c8\u5668\u3002<\/p>\n<p><strong>Definition<\/strong> This arrangement\u2014whereby a piece of middleware can call another piece of middleware, which in turn can call another, and so on\u2014is referred to as a pipeline. You can think of each piece of middleware as being like a section of pipe; when you connect all the sections, a request flows through one piece and into the next.<br \/>\n<strong>\u5b9a\u4e49<\/strong> \u8fd9\u79cd\u5b89\u6392\uff08\u5373\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u53ef\u4ee5\u8c03\u7528\u53e6\u4e00\u4e2a\u4e2d\u95f4\u4ef6\uff0c\u800c\u53e6\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u53c8\u53ef\u4ee5\u8c03\u7528\u53e6\u4e00\u4e2a\u4e2d\u95f4\u4ef6\uff0c\u4f9d\u6b64\u7c7b\u63a8\uff09\u79f0\u4e3a\u7ba1\u9053\u3002\u60a8\u53ef\u4ee5\u5c06\u6bcf\u4e2a\u4e2d\u95f4\u4ef6\u89c6\u4e3a\u4e00\u6bb5\u7ba1\u9053;\u5f53\u60a8\u8fde\u63a5\u6240\u6709\u90e8\u5206\u65f6\uff0c\u8bf7\u6c42\u5c06\u6d41\u7ecf\u4e00\u4e2a\u90e8\u5206\u5e76\u8fdb\u5165\u4e0b\u4e00\u4e2a\u90e8\u5206\u3002<\/p>\n<p>One of the most common use cases for middleware is for the cross-cutting concerns of your application. These aspects of your application need to occur for every request, regardless of the specific path in the request or the resource requested, including<\/p>\n<p>\u4e2d\u95f4\u4ef6\u6700\u5e38\u89c1\u7684\u7528\u4f8b\u4e4b\u4e00\u662f\u5e94\u7528\u7a0b\u5e8f\u7684\u6a2a\u5207\u5173\u6ce8\u70b9\u3002\u65e0\u8bba\u8bf7\u6c42\u4e2d\u7684\u5177\u4f53\u8def\u5f84\u6216\u8bf7\u6c42\u7684\u8d44\u6e90\u5982\u4f55\uff0c\u6bcf\u4e2a\u8bf7\u6c42\u90fd\u9700\u8981\u51fa\u73b0\u5e94\u7528\u7a0b\u5e8f\u7684\u8fd9\u4e9b\u65b9\u9762\uff0c\u5305\u62ec<\/p>\n<ul>\n<li>\n<p>Logging each request<br \/>\n\u8bb0\u5f55\u6bcf\u4e2a\u8bf7\u6c42<\/p>\n<\/li>\n<li>\n<p>Adding standard security headers to the response<br \/>\n\u5411\u54cd\u5e94\u6dfb\u52a0\u6807\u51c6\u5b89\u5168\u6807\u5934<\/p>\n<\/li>\n<li>\n<p>Associating a request with the relevant user<br \/>\n\u5c06\u8bf7\u6c42\u4e0e\u76f8\u5173\u7528\u6237\u5173\u8054<\/p>\n<\/li>\n<li>\n<p>Setting the language for the current request<br \/>\n\u8bbe\u7f6e\u5f53\u524d\u8bf7\u6c42\u7684\u8bed\u8a00<\/p>\n<\/li>\n<\/ul>\n<p>In each of these examples, the middleware receives a request, modifies it, and then passes the request on to the next piece of middleware in the pipeline. Subsequent middleware could use the details added by the earlier middleware to handle the request in some way. In figure 4.2, for example, the authentication middleware associates the request with a user. Then the authorization middleware uses this detail to verify whether the user has permission to make that specific request to the application.<\/p>\n<p>\u5728\u4e0a\u8ff0\u6bcf\u4e2a\u793a\u4f8b\u4e2d\uff0c\u4e2d\u95f4\u4ef6\u90fd\u4f1a\u63a5\u6536\u8bf7\u6c42\uff0c\u5bf9\u5176\u8fdb\u884c\u4fee\u6539\uff0c\u7136\u540e\u5c06\u8bf7\u6c42\u4f20\u9012\u5230\u7ba1\u9053\u4e2d\u7684\u4e0b\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u3002\u540e\u7eed\u4e2d\u95f4\u4ef6\u53ef\u4ee5\u4f7f\u7528\u65e9\u671f\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u7684\u8be6\u7ec6\u4fe1\u606f\u4ee5\u67d0\u79cd\u65b9\u5f0f\u5904\u7406\u8bf7\u6c42\u3002\u4f8b\u5982\uff0c\u5728\u56fe 4.2 \u4e2d\uff0c\u8eab\u4efd\u9a8c\u8bc1\u4e2d\u95f4\u4ef6\u5c06\u8bf7\u6c42\u4e0e\u7528\u6237\u76f8\u5173\u8054\u3002\u7136\u540e\uff0c\u6388\u6743\u4e2d\u95f4\u4ef6\u4f7f\u7528\u6b64\u8be6\u7ec6\u4fe1\u606f\u6765\u9a8c\u8bc1\u7528\u6237\u662f\u5426\u6709\u6743\u5411\u5e94\u7528\u7a0b\u5e8f\u53d1\u51fa\u8be5\u7279\u5b9a\u8bf7\u6c42\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0402.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.2 Example of a middleware component modifying a request for use later in the pipeline. Middleware can also short-circuit the pipeline, returning a response before the request reaches later middleware.<br \/>\n\u56fe 4.2 \u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u4fee\u6539\u8bf7\u6c42\u4ee5\u4f9b\u7a0d\u540e\u5728\u7ba1\u9053\u4e2d\u4f7f\u7528\u7684\u793a\u4f8b\u3002\u4e2d\u95f4\u4ef6\u8fd8\u53ef\u4ee5\u4f7f\u7ba1\u9053\u77ed\u8def\uff0c\u5728\u8bf7\u6c42\u5230\u8fbe\u540e\u9762\u7684\u4e2d\u95f4\u4ef6\u4e4b\u524d\u8fd4\u56de\u54cd\u5e94\u3002<\/p>\n<p>If the user has permission, the authorization middleware passes the request on to the endpoint middleware to allow it to generate a response. If the user doesn\u2019t have permission, the authorization middleware can short-circuit the pipeline, generating a response directly; it returns the response to the previous middleware, and the endpoint middleware never sees the request. This scenario is an example of the chain-of-responsibility design pattern.<\/p>\n<p>\u5982\u679c\u7528\u6237\u5177\u6709\u6743\u9650\uff0c\u5219\u6388\u6743\u4e2d\u95f4\u4ef6\u4f1a\u5c06\u8bf7\u6c42\u4f20\u9012\u7ed9\u7ec8\u7aef\u8282\u70b9\u4e2d\u95f4\u4ef6\uff0c\u4ee5\u5141\u8bb8\u5176\u751f\u6210\u54cd\u5e94\u3002\u5982\u679c\u7528\u6237\u6ca1\u6709\u6743\u9650\uff0c\u6388\u6743\u4e2d\u95f4\u4ef6\u53ef\u4ee5\u4f7f\u7ba1\u9053\u77ed\u8def\uff0c\u76f4\u63a5\u751f\u6210\u54cd\u5e94;\u5b83\u5c06\u54cd\u5e94\u8fd4\u56de\u7ed9\u524d\u9762\u7684\u4e2d\u95f4\u4ef6\uff0c\u800c Endpoint \u4e2d\u95f4\u4ef6\u6c38\u8fdc\u4e0d\u4f1a\u770b\u5230\u8be5\u8bf7\u6c42\u3002\u6b64\u65b9\u6848\u662f\u8d23\u4efb\u94fe\u8bbe\u8ba1\u6a21\u5f0f\u7684\u4e00\u4e2a\u793a\u4f8b\u3002<\/p>\n<p><strong>Definition<\/strong> When a middleware component short-circuits the pipeline and returns a response, it\u2019s called terminal middleware.<br \/>\n<strong>\u5b9a\u4e49<\/strong> \u5f53\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u4f7f\u7ba1\u9053\u77ed\u8def\u5e76\u8fd4\u56de\u54cd\u5e94\u65f6\uff0c\u5b83\u79f0\u4e3a\u7ec8\u7aef\u4e2d\u95f4\u4ef6\u3002<\/p>\n<p>A key point to glean from this example is that the pipeline is bidirectional. The request passes through the pipeline in one direction until a piece of middleware generates a response, at which point the response passes back through the pipeline, passing through each piece of middleware a second time, in reverse order, until it gets back to the first piece of middleware. Finally, the first\/last piece of middleware passes the response back to the ASP.NET Core web server.<\/p>\n<p>\u4ece\u8fd9\u4e2a\u4f8b\u5b50\u4e2d\u53ef\u4ee5\u4e86\u89e3\u5230\u7684\u4e00\u4e2a\u5173\u952e\u70b9\u662f\u7ba1\u9053\u662f\u53cc\u5411\u7684\u3002\u8bf7\u6c42\u6cbf\u4e00\u4e2a\u65b9\u5411\u901a\u8fc7\u7ba1\u9053\uff0c\u76f4\u5230\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u751f\u6210\u54cd\u5e94\uff0c\u6b64\u65f6\u54cd\u5e94\u901a\u8fc7\u7ba1\u9053\u4f20\u56de\uff0c\u4ee5\u76f8\u53cd\u7684\u987a\u5e8f\u7b2c\u4e8c\u6b21\u901a\u8fc7\u6bcf\u4e2a\u4e2d\u95f4\u4ef6\uff0c\u76f4\u5230\u5b83\u8fd4\u56de\u5230\u7b2c\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u3002\u6700\u540e\uff0c\u7b2c\u4e00\u4e2a\/\u6700\u540e\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u5c06\u54cd\u5e94\u4f20\u9012\u56de ASP.NET Core Web \u670d\u52a1\u5668\u3002<\/p>\n<blockquote>\n<p>The HttpContext object<br \/>\n\u5bf9\u8c61HttpContext<br \/>\nI mentioned the HttpContext in chapter 3, and it\u2019s sitting behind the scenes here too. The ASP.NET Core web server constructs an HttpContext for each request, which the ASP.NET Core application uses as a sort of storage box for a single request. Anything that\u2019s specific to this particular request and the subsequent response can be associated with and stored in it. Examples are properties of the request, request-specific services, data that\u2019s been loaded, or errors that have occurred. The web server fills the initial HttpContext with details of the original HTTP request and other configuration details, and then passes it on to the middleware pipeline and the rest of the application.<br \/>\n\u6211\u5728\u7b2c 3 \u7ae0\u4e2d\u63d0\u5230\u4e86HttpContext\uff0c\u5b83\u4e5f\u4f4d\u4e8e\u5e55\u540e\u3002ASP.NET Core Web \u670d\u52a1\u5668\u4e3a\u6bcf\u4e2a\u8bf7\u6c42\u6784\u5efa\u4e00\u4e2a\uff0cASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u5c06\u5176\u7528\u4f5c\u5355\u4e2a\u8bf7\u6c42\u7684\u5b58\u50a8\u76d2\u3002\u7279\u5b9a\u4e8e\u6b64\u7279\u5b9a\u8bf7\u6c42\u548c\u540e\u7eed\u54cd\u5e94\u7684\u4efb\u4f55\u5185\u5bb9\u90fd\u53ef\u4ee5\u4e0e\u8be5\u8bf7\u6c42\u76f8\u5173\u8054\u5e76\u5b58\u50a8\u5728\u5176\u4e2d\u3002\u793a\u4f8b\u5305\u62ec\u8bf7\u6c42\u7684\u5c5e\u6027\u3001\u7279\u5b9a\u4e8e\u8bf7\u6c42\u7684\u670d\u52a1\u3001\u5df2\u52a0\u8f7d\u7684\u6570\u636e\u6216\u53d1\u751f\u7684\u9519\u8bef\u3002Web \u670d\u52a1\u5668\u4f7f\u7528\u539f\u59cb HTTP \u8bf7\u6c42\u7684\u8be6\u7ec6\u4fe1\u606f\u548c\u5176\u4ed6\u914d\u7f6e\u8be6\u7ec6\u4fe1\u606f\u586b\u5145\u521d\u59cb\u8bf7\u6c42\uff0c\u7136\u540e\u5c06\u5176\u4f20\u9012\u7ed9\u4e2d\u95f4\u4ef6\u7ba1\u9053\u548c\u5e94\u7528\u7a0b\u5e8f\u7684\u5176\u4f59\u90e8\u5206\u3002HttpContextHttpContextHttpContext<br \/>\nAll middleware has access to the HttpContext for a request. It can use this object to determine whether the request contains any user credentials, to identify which page the request is attempting to access, and to fetch any posted data, for example. Then it can use these details to determine how to handle the request.<br \/>\n\u6240\u6709\u4e2d\u95f4\u4ef6\u90fd\u53ef\u4ee5\u8bbf\u95ee for a request.\u4f8b\u5982\uff0c\u5b83\u53ef\u4ee5\u4f7f\u7528\u6b64\u5bf9\u8c61\u6765\u786e\u5b9a\u8bf7\u6c42\u662f\u5426\u5305\u542b\u4efb\u4f55\u7528\u6237\u51ed\u8bc1\uff0c\u786e\u5b9a\u8bf7\u6c42\u5c1d\u8bd5\u8bbf\u95ee\u7684\u9875\u9762\uff0c\u4ee5\u53ca\u83b7\u53d6\u4efb\u4f55\u5df2\u53d1\u5e03\u7684\u6570\u636e\u3002\u7136\u540e\uff0c\u5b83\u53ef\u4ee5\u4f7f\u7528\u8fd9\u4e9b\u8be6\u7ec6\u4fe1\u606f\u6765\u786e\u5b9a\u5982\u4f55\u5904\u7406\u8bf7\u6c42\u3002<br \/>\nWhen the application finishes processing the request, it updates the HttpContext with an appropriate response and returns it through the middleware pipeline to the web server. Then the ASP.NET Core web server converts the representation to a raw HTTP response and sends it back to the reverse proxy, which forwards it to the user\u2019s browser.<br \/>\n\u5f53\u5e94\u7528\u7a0b\u5e8f\u5b8c\u6210\u5bf9\u8bf7\u6c42\u7684\u5904\u7406\u540e\uff0c\u5b83\u4f1a\u4f7f\u7528\u9002\u5f53\u7684\u54cd\u5e94\u8fdb\u884c\u66f4\u65b0\uff0c\u5e76\u901a\u8fc7\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5c06\u5176\u8fd4\u56de\u5230 Web \u670d\u52a1\u5668\u3002\u7136\u540e\uff0cASP.NET Core Web \u670d\u52a1\u5668\u5c06\u8868\u793a\u5f62\u5f0f\u8f6c\u6362\u4e3a\u539f\u59cb HTTP \u54cd\u5e94\uff0c\u5e76\u5c06\u5176\u53d1\u9001\u56de\u53cd\u5411\u4ee3\u7406\uff0c\u53cd\u5411\u4ee3\u7406\u5c06\u5176\u8f6c\u53d1\u5230\u7528\u6237\u7684\u6d4f\u89c8\u5668\u3002<\/p>\n<\/blockquote>\n<p>As you saw in chapter 3, you define the middleware pipeline in code as part of your initial application configuration in Program.cs. You can tailor the middleware pipeline specifically to your needs; simple apps may need only a short pipeline, whereas large apps with a variety of features may use much more middleware. Middleware is the fundamental source of behavior in your application. Ultimately, the middleware pipeline is responsible for responding to any HTTP requests it receives.<\/p>\n<p>\u6b63\u5982\u60a8\u5728\u7b2c 3 \u7ae0\u4e2d\u770b\u5230\u7684\uff0c\u60a8\u5728\u4ee3\u7801\u4e2d\u5b9a\u4e49\u4e86\u4e2d\u95f4\u4ef6\u7ba1\u9053\uff0c\u4f5c\u4e3a Program.cs \u4e2d\u521d\u59cb\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\u7684\u4e00\u90e8\u5206\u3002\u60a8\u53ef\u4ee5\u6839\u636e\u60a8\u7684\u9700\u6c42\u4e13\u95e8\u5b9a\u5236\u4e2d\u95f4\u4ef6\u7ba1\u9053;\u7b80\u5355\u7684\u5e94\u7528\u7a0b\u5e8f\u53ef\u80fd\u53ea\u9700\u8981\u4e00\u4e2a\u77ed\u7684\u7ba1\u9053\uff0c\u800c\u5177\u6709\u5404\u79cd\u529f\u80fd\u7684\u5927\u578b\u5e94\u7528\u7a0b\u5e8f\u53ef\u80fd\u4f1a\u4f7f\u7528\u66f4\u591a\u7684\u4e2d\u95f4\u4ef6\u3002\u4e2d\u95f4\u4ef6\u662f\u5e94\u7528\u7a0b\u5e8f\u4e2d\u884c\u4e3a\u7684\u57fa\u672c\u6765\u6e90\u3002\u6700\u7ec8\uff0c\u4e2d\u95f4\u4ef6\u7ba1\u9053\u8d1f\u8d23\u54cd\u5e94\u5b83\u6536\u5230\u7684\u4efb\u4f55 HTTP \u8bf7\u6c42\u3002<\/p>\n<p>Requests are passed to the middleware pipeline as HttpContext objects. As you saw in chapter 3, the ASP.NET Core web server builds an HttpContext object from an incoming request, which passes up and down the middleware pipeline. When you\u2019re using existing middleware to build a pipeline, this detail is one that you\u2019ll rarely have to deal with. But as you\u2019ll see in the final section of this chapter, its presence behind the scenes provides a route to exerting extra control over your middleware pipeline.<\/p>\n<p>\u8bf7\u6c42\u4f5c\u4e3a\u5bf9\u8c61\u4f20\u9012\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002\u6b63\u5982\u60a8\u5728\u7b2c 3 \u7ae0\u4e2d\u6240\u770b\u5230\u7684\uff0cASP.NET Core Web \u670d\u52a1\u5668\u4ece\u4f20\u5165\u8bf7\u6c42\u6784\u5efa\u4e00\u4e2a\u5bf9\u8c61\uff0c\u8be5\u8bf7\u6c42\u5728\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4e2d\u4e0a\u4e0b\u4f20\u9012\u3002\u5f53\u60a8\u4f7f\u7528\u73b0\u6709\u4e2d\u95f4\u4ef6\u6784\u5efa\u7ba1\u9053\u65f6\uff0c\u60a8\u5f88\u5c11\u9700\u8981\u5904\u7406\u8fd9\u4e9b\u7ec6\u8282\u3002\u4f46\u6b63\u5982\u60a8\u5c06\u5728\u672c\u7ae0\u7684\u6700\u540e\u4e00\u90e8\u5206\u4e2d\u770b\u5230\u7684\u90a3\u6837\uff0c\u5b83\u5728\u5e55\u540e\u7684\u5b58\u5728\u4e3a\u5bf9\u4e2d\u95f4\u4ef6\u7ba1\u9053\u65bd\u52a0\u989d\u5916\u63a7\u5236\u63d0\u4f9b\u4e86\u4e00\u6761\u9014\u5f84\u3002<\/p>\n<p>You can also think of your middleware pipeline as being a series of concentric components, similar to a traditional matryoshka (Russian) doll, as shown in figure 4.3. A request progresses through the pipeline by heading deeper into the stack of middleware until a response is returned. Then the response returns through the middleware, passing through the components in reverse order from the request.<\/p>\n<p>\u60a8\u8fd8\u53ef\u4ee5\u5c06\u4e2d\u95f4\u4ef6\u7ba1\u9053\u89c6\u4e3a\u4e00\u7cfb\u5217\u540c\u5fc3\u7ec4\u4ef6\uff0c\u7c7b\u4f3c\u4e8e\u4f20\u7edf\u7684\u4fc4\u7f57\u65af\u5957\u5a03\uff0c\u5982\u56fe 4.3 \u6240\u793a\u3002\u8bf7\u6c42\u901a\u8fc7\u66f4\u6df1\u5165\u5730\u8fdb\u5165\u4e2d\u95f4\u4ef6\u5806\u6808\u5728\u7ba1\u9053\u4e2d\u524d\u8fdb\uff0c\u76f4\u5230\u8fd4\u56de\u54cd\u5e94\u3002\u7136\u540e\uff0c\u54cd\u5e94\u901a\u8fc7\u4e2d\u95f4\u4ef6\u8fd4\u56de\uff0c\u4ee5\u4e0e\u8bf7\u6c42\u76f8\u53cd\u7684\u987a\u5e8f\u4f20\u9012\u7ec4\u4ef6\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0403.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.3 You can also think of middleware as being a series of nested components; a request is sent deeper into the middleware, and the response resurfaces from it. Each middleware component can execute logic before passing the response on to the next middleware component and can execute logic after the response has been created, on the way back out of the stack.<br \/>\n\u56fe 4.3 \u4f60\u4e5f\u53ef\u4ee5\u628a middleware \u770b\u4f5c\u662f\u4e00\u7cfb\u5217\u5d4c\u5957\u7684\u7ec4\u4ef6;\u8bf7\u6c42\u88ab\u53d1\u9001\u5230\u4e2d\u95f4\u4ef6\u7684\u66f4\u6df1\u5904\uff0c\u54cd\u5e94\u4ece\u4e2d\u91cd\u65b0\u51fa\u73b0\u3002\u6bcf\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u90fd\u53ef\u4ee5\u5728\u5c06\u54cd\u5e94\u4f20\u9012\u5230\u4e0b\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u4e4b\u524d\u6267\u884c\u903b\u8f91\uff0c\u5e76\u4e14\u53ef\u4ee5\u5728\u521b\u5efa\u54cd\u5e94\u540e\u6267\u884c\u903b\u8f91\uff0c\u5728\u8fd4\u56de\u5806\u6808\u7684\u9014\u4e2d\u6267\u884c\u903b\u8f91\u3002<\/p>\n<blockquote>\n<p>Middleware vs. HTTP modules and HTTP handlers<br \/>\n\u4e2d\u95f4\u4ef6\u4e0e HTTP \u6a21\u5757\u548c HTTP \u5904\u7406\u7a0b\u5e8f<br \/>\nIn the previous version of ASP.NET, the concept of a middleware pipeline isn\u2019t used. Instead, you have HTTP modules and HTTP handlers.<br \/>\n\u5728\u65e9\u671f\u7248\u672c\u7684 ASP.NET \u4e2d\uff0c\u672a\u4f7f\u7528\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u6982\u5ff5\u3002\u76f8\u53cd\uff0c\u60a8\u6709 HTTP \u6a21\u5757\u548c HTTP \u5904\u7406\u7a0b\u5e8f\u3002<br \/>\nAn HTTP handler is a process that runs in response to a request and generates the response. The ASP.NET page handler, for example, runs in response to requests for .aspx pages. Alternatively, you could write a custom handler that returns resized images when an image is requested.<br \/>\nHTTP \u5904\u7406\u7a0b\u5e8f\u662f\u4e3a\u54cd\u5e94\u8bf7\u6c42\u800c\u8fd0\u884c\u5e76\u751f\u6210\u54cd\u5e94\u7684\u8fdb\u7a0b\u3002\u4f8b\u5982\uff0cASP.NET \u9875\u5904\u7406\u7a0b\u5e8f\u5728\u54cd\u5e94\u5bf9 .aspx \u9875\u7684\u8bf7\u6c42\u65f6\u8fd0\u884c\u3002\u6216\u8005\uff0c\u60a8\u53ef\u4ee5\u7f16\u5199\u4e00\u4e2a\u81ea\u5b9a\u4e49\u5904\u7406\u7a0b\u5e8f\uff0c\u5728\u8bf7\u6c42\u56fe\u50cf\u65f6\u8fd4\u56de\u8c03\u6574\u5927\u5c0f\u7684\u56fe\u50cf\u3002<br \/>\nHTTP modules handle the cross-cutting concerns of applications, such as security, logging, and session management. They run in response to the life-cycle events that a request progresses through when it\u2019s received by the server. Examples of events include BeginRequest, AcquireRequestState, and PostAcquireRequestState.<br \/>\nHTTP \u6a21\u5757\u5904\u7406\u5e94\u7528\u7a0b\u5e8f\u7684\u6a2a\u5207\u5173\u6ce8\u70b9\uff0c\u4f8b\u5982\u5b89\u5168\u6027\u3001\u65e5\u5fd7\u8bb0\u5f55\u548c\u4f1a\u8bdd\u7ba1\u7406\u3002\u5b83\u4eec\u8fd0\u884c\u4ee5\u54cd\u5e94\u670d\u52a1\u5668\u6536\u5230\u8bf7\u6c42\u65f6\u6240\u7ecf\u5386\u7684\u751f\u547d\u5468\u671f\u4e8b\u4ef6\u3002\u4e8b\u4ef6\u7684\u793a\u4f8b\u5305\u62ecBeginRequest, AcquireRequestState, \u548c PostAcquireRequestState.<br \/>\nThis approach works, but sometimes it\u2019s tricky to reason about which modules will run at which points. Implementing a module requires relatively detailed understanding of the state of the request at each individual life-cycle event.<br \/>\n\u8fd9\u79cd\u65b9\u6cd5\u6709\u6548\uff0c\u4f46\u6709\u65f6\u5f88\u96be\u63a8\u65ad\u54ea\u4e9b\u6a21\u5757\u5c06\u5728\u54ea\u4e9b\u70b9\u8fd0\u884c\u3002\u5b9e\u73b0\u6a21\u5757\u9700\u8981\u76f8\u5bf9\u8be6\u7ec6\u5730\u4e86\u89e3\u6bcf\u4e2a\u751f\u547d\u5468\u671f\u4e8b\u4ef6\u4e2d\u7684\u8bf7\u6c42\u72b6\u6001\u3002<br \/>\nThe middleware pipeline makes understanding your application far simpler. The pipeline is defined completely in code, specifying which components should run and in which order. Behind the scenes, the middleware pipeline in ASP.NET Core is simply a chain of method calls, with each middleware function calling the next in the pipeline.<br \/>\n\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4f7f\u7406\u89e3\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u53d8\u5f97\u66f4\u52a0\u7b80\u5355\u3002\u7ba1\u9053\u5b8c\u5168\u5728\u4ee3\u7801\u4e2d\u5b9a\u4e49\uff0c\u6307\u5b9a\u54ea\u4e9b\u7ec4\u4ef6\u5e94\u8fd0\u884c\u4ee5\u53ca\u8fd0\u884c\u987a\u5e8f\u3002\u5728\u5e55\u540e\uff0cASP.NET Core \u4e2d\u7684\u4e2d\u95f4\u4ef6\u7ba1\u9053\u53ea\u662f\u4e00\u4e2a\u65b9\u6cd5\u8c03\u7528\u94fe\uff0c\u6bcf\u4e2a\u4e2d\u95f4\u4ef6\u51fd\u6570\u90fd\u8c03\u7528\u7ba1\u9053\u4e2d\u7684\u4e0b\u4e00\u4e2a\u3002<\/p>\n<\/blockquote>\n<p>That\u2019s pretty much all there is to the concept of middleware. In the next section, I\u2019ll discuss ways you can combine middleware components to create an application and how to use middleware to separate the concerns of your application.<\/p>\n<p>\u8fd9\u51e0\u4e4e\u5c31\u662f\u4e2d\u95f4\u4ef6\u6982\u5ff5\u7684\u5168\u90e8\u5185\u5bb9\u3002\u5728\u4e0b\u4e00\u8282\u4e2d\uff0c\u6211\u5c06\u8ba8\u8bba\u7ec4\u5408\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u6765\u521b\u5efa\u5e94\u7528\u7a0b\u5e8f\u7684\u65b9\u6cd5\uff0c\u4ee5\u53ca\u5982\u4f55\u4f7f\u7528\u4e2d\u95f4\u4ef6\u6765\u5206\u79bb\u5e94\u7528\u7a0b\u5e8f\u7684\u5173\u6ce8\u70b9\u3002<\/p>\n<h3>4.2 Combining middleware in a pipeline<\/h3>\n<h3>4.2 \u5c06\u4e2d\u95f4\u4ef6\u7ec4\u5408\u5230\u4e00\u4e2a\u7ba1\u9053\u4e2d<\/h3>\n<p>Generally speaking, each middleware component has a single primary concern; it handles only one aspect of a request. Logging middleware deals only with logging the request, authentication middleware is concerned only with identifying the current user, and static-file middleware is concerned only with returning static files.<\/p>\n<p>\u4e00\u822c\u6765\u8bf4\uff0c\u6bcf\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u90fd\u6709\u4e00\u4e2a\u4e3b\u8981\u5173\u6ce8\u70b9;\u5b83\u53ea\u5904\u7406\u8bf7\u6c42\u7684\u4e00\u4e2a\u65b9\u9762\u3002\u65e5\u5fd7\u8bb0\u5f55\u4e2d\u95f4\u4ef6\u53ea\u5904\u7406\u8bb0\u5f55\u8bf7\u6c42\uff0c\u8eab\u4efd\u9a8c\u8bc1\u4e2d\u95f4\u4ef6\u53ea\u5173\u5fc3\u8bc6\u522b\u5f53\u524d\u7528\u6237\uff0c\u9759\u6001\u6587\u4ef6\u4e2d\u95f4\u4ef6\u53ea\u5173\u5fc3\u8fd4\u56de\u9759\u6001\u6587\u4ef6\u3002<\/p>\n<p>Each of these concerns is highly focused, which makes the components themselves small and easy to reason about. This approach also gives your app added flexibility. Adding static-file middleware, for example, doesn\u2019t mean you\u2019re forced to have image-resizing behavior or authentication; each of these features is an additional piece of middleware.<\/p>\n<p>\u8fd9\u4e9b\u5173\u6ce8\u70b9\u4e2d\u7684\u6bcf\u4e00\u4e2a\u90fd\u662f\u9ad8\u5ea6\u96c6\u4e2d\u7684\uff0c\u8fd9\u4f7f\u5f97\u7ec4\u4ef6\u672c\u8eab\u5f88\u5c0f\u5e76\u4e14\u6613\u4e8e\u63a8\u7406\u3002\u6b64\u65b9\u6cd5\u8fd8\u4e3a\u5e94\u7528\u63d0\u4f9b\u4e86\u66f4\u5927\u7684\u7075\u6d3b\u6027\u3002\u4f8b\u5982\uff0c\u6dfb\u52a0\u9759\u6001\u6587\u4ef6\u4e2d\u95f4\u4ef6\u5e76\u4e0d\u610f\u5473\u7740\u60a8\u88ab\u8feb\u5177\u6709\u56fe\u50cf\u5927\u5c0f\u8c03\u6574\u884c\u4e3a\u6216\u8eab\u4efd\u9a8c\u8bc1;\u8fd9\u4e9b\u529f\u80fd\u4e2d\u7684\u6bcf\u4e00\u4e2a\u90fd\u662f\u4e2d\u95f4\u4ef6\u7684\u9644\u52a0\u90e8\u5206\u3002<\/p>\n<p>To build a complete application, you compose multiple middleware components into a pipeline, as shown in section 4.1. Each middleware component has access to the original request, as well as any changes made to the HttpContext by middleware earlier in the pipeline. When a response has been generated, each middleware component can inspect and\/or modify the response as it passes back through the pipeline before it\u2019s sent to the user. This feature allows you to build complex application behaviors from small, focused components.<\/p>\n<p>\u8981\u6784\u5efa\u4e00\u4e2a\u5b8c\u6574\u7684\u5e94\u7528\u7a0b\u5e8f\uff0c\u60a8\u9700\u8981\u5c06\u591a\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u7ec4\u5408\u5230\u4e00\u4e2a\u7ba1\u9053\u4e2d\uff0c\u5982\u7b2c 4.1 \u8282\u6240\u793a\u3002\u6bcf\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u90fd\u53ef\u4ee5\u8bbf\u95ee\u539f\u59cb\u8bf7\u6c42\uff0c\u4ee5\u53ca\u7ba1\u9053\u4e2d\u8f83\u65e9\u65f6\u5bf9 by \u4e2d\u95f4\u4ef6\u6240\u505a\u7684\u4efb\u4f55\u66f4\u6539\u3002\u751f\u6210\u54cd\u5e94\u540e\uff0c\u6bcf\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u90fd\u53ef\u4ee5\u5728\u54cd\u5e94\u901a\u8fc7\u7ba1\u9053\u4f20\u56de\u54cd\u5e94\u4e4b\u524d\u68c0\u67e5\u548c\/\u6216\u4fee\u6539\u54cd\u5e94\uff0c\u7136\u540e\u518d\u5c06\u5176\u53d1\u9001\u7ed9\u7528\u6237\u3002\u6b64\u529f\u80fd\u5141\u8bb8\u60a8\u4ece\u5c0f\u578b\u3001\u4e13\u6ce8\u7684\u7ec4\u4ef6\u6784\u5efa\u590d\u6742\u7684\u5e94\u7528\u7a0b\u5e8f\u884c\u4e3a\u3002<\/p>\n<p>In the rest of this section, you\u2019ll see how to create a middleware pipeline by combining various middleware components. Using standard middleware components, you\u2019ll learn to create a holding page and to serve static files from a folder on disk. Finally, you\u2019ll take a look at a more complex pipeline such as you\u2019d get in a minimal API application with multiple middleware, routing, and endpoints.<\/p>\n<p>\u5728\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\uff0c\u60a8\u5c06\u4e86\u89e3\u5982\u4f55\u901a\u8fc7\u7ec4\u5408\u5404\u79cd\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u6765\u521b\u5efa\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002\u4f7f\u7528\u6807\u51c6\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\uff0c\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u521b\u5efa\u4fdd\u7559\u9875\u5e76\u4ece\u78c1\u76d8\u4e0a\u7684\u6587\u4ef6\u5939\u4e2d\u63d0\u4f9b\u9759\u6001\u6587\u4ef6\u3002\u6700\u540e\uff0c\u60a8\u5c06\u4e86\u89e3\u66f4\u590d\u6742\u7684\u7ba1\u9053\uff0c\u4f8b\u5982\u5728\u5177\u6709\u591a\u4e2a\u4e2d\u95f4\u4ef6\u3001\u8def\u7531\u548c\u7ec8\u7aef\u8282\u70b9\u7684\u6700\u5c0f API \u5e94\u7528\u7a0b\u5e8f\u4e2d\u83b7\u5f97\u7684\u7ba1\u9053\u3002<\/p>\n<h4>4.2.1 Simple pipeline scenario 1: A holding page<\/h4>\n<h4>4.2.1 \u7b80\u5355\u7ba1\u9053\u573a\u666f 1\uff1a\u4e00\u4e2a\u4fdd\u6301\u9875<\/h4>\n<p>For your first app in this chapter and your first middleware pipeline, you\u2019ll learn how to create an app consisting of a holding page. Adding a holding page can be useful occasionally when you\u2019re setting up your application to ensure that it\u2019s processing requests without errors.<\/p>\n<p>\u5bf9\u4e8e\u672c\u7ae0\u4e2d\u7684\u7b2c\u4e00\u4e2a\u5e94\u7528\u7a0b\u5e8f\u548c\u7b2c\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u7ba1\u9053\uff0c\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u521b\u5efa\u7531\u4fdd\u6301\u9875\u9762\u7ec4\u6210\u7684\u5e94\u7528\u7a0b\u5e8f\u3002\u5728\u8bbe\u7f6e\u5e94\u7528\u7a0b\u5e8f\u65f6\uff0c\u6dfb\u52a0\u4fdd\u7559\u9875\u6709\u65f6\u53ef\u80fd\u5f88\u6709\u7528\uff0c\u4ee5\u786e\u4fdd\u5b83\u5904\u7406\u8bf7\u6c42\u65f6\u6ca1\u6709\u9519\u8bef\u3002<\/p>\n<p><strong>Tip<\/strong> Remember that you can view the application code for this book in the GitHub repository at <a href=\"http:\/\/mng.bz\/Y1qN\">http:\/\/mng.bz\/Y1qN<\/a>.<br \/>\n<strong>\u63d0\u793a<\/strong> \u8bf7\u8bb0\u4f4f\uff0c\u60a8\u53ef\u4ee5\u5728 <a href=\"http:\/\/mng.bz\/Y1qN\">http:\/\/mng.bz\/Y1qN<\/a> \u7684 GitHub \u5b58\u50a8\u5e93\u4e2d\u67e5\u770b\u672c\u4e66\u7684\u5e94\u7528\u7a0b\u5e8f\u4ee3\u7801\u3002<\/p>\n<p>In previous chapters, I mentioned that the ASP.NET Core framework is composed of many small individual libraries. You typically add a piece of middleware by referencing a package in your application\u2019s .csproj project file and configuring the middleware in Program.cs. Microsoft ships many standard middleware components with ASP.NET Core for you to choose among; you can also use third-party components from NuGet and GitHub, or you can build your own custom middleware. You can find the list of built-in middleware at <a href=\"http:\/\/mng.bz\/Gyxq\">http:\/\/mng.bz\/Gyxq<\/a>.<\/p>\n<p>\u5728\u524d\u9762\u7684\u7ae0\u8282\u4e2d\uff0c\u6211\u63d0\u5230\u4e86 ASP.NET Core \u6846\u67b6\u7531\u8bb8\u591a\u5c0f\u578b\u7684\u5355\u4e2a\u5e93\u7ec4\u6210\u3002\u901a\u5e38\uff0c\u60a8\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u5e94\u7528\u7a0b\u5e8f\u7684 .csproj \u9879\u76ee\u6587\u4ef6\u4e2d\u7684\u5305\u5e76\u5728 Program.cs \u4e2d\u914d\u7f6e\u4e2d\u95f4\u4ef6\u6765\u6dfb\u52a0\u4e2d\u95f4\u4ef6\u3002Microsoft Core \u9644\u5e26\u4e86\u8bb8\u591a\u6807\u51c6\u4e2d\u95f4\u4ef6\u7ec4\u4ef6 ASP.NET \u4f9b\u60a8\u9009\u62e9;\u60a8\u8fd8\u53ef\u4ee5\u4f7f\u7528 NuGet \u548c GitHub \u4e2d\u7684\u7b2c\u4e09\u65b9\u7ec4\u4ef6\uff0c\u4e5f\u53ef\u4ee5\u6784\u5efa\u81ea\u5df1\u7684\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6\u3002\u60a8\u53ef\u4ee5\u5728 <a href=\"http:\/\/mng.bz\/Gyxq\">http:\/\/mng.bz\/Gyxq<\/a> \u4e2d\u627e\u5230\u5185\u7f6e\u4e2d\u95f4\u4ef6\u7684\u5217\u8868\u3002<\/p>\n<p><strong>Note<\/strong> I discuss building custom middleware in chapter 31.<br \/>\n<strong>\u6ce8\u610f<\/strong> \u6211\u5728\u7b2c 31 \u7ae0\u4e2d\u8ba8\u8bba\u4e86\u6784\u5efa\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6\u3002<\/p>\n<p>In this section, you\u2019ll see how to create one of the simplest middleware pipelines, consisting only of WelcomePageMiddleware. WelcomePageMiddleware is designed to provide a sample HTML page quickly when you\u2019re first developing an application, as you can see in figure 4.4. You wouldn\u2019t use it in a production app, as you can\u2019t customize the output, but it\u2019s a single, self-contained middleware component you can use to ensure that your application is running correctly.<\/p>\n<p>\u5728\u672c\u8282\u4e2d\uff0c\u60a8\u5c06\u4e86\u89e3\u5982\u4f55\u521b\u5efa\u6700\u7b80\u5355\u7684\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4e4b\u4e00\uff0c\u5176\u4e2d\u4ec5\u7531WelcomePageMiddleware. WelcomePageMiddleware\u65e8\u5728\u5728\u60a8\u9996\u6b21\u5f00\u53d1\u5e94\u7528\u7a0b\u5e8f\u65f6\u5feb\u901f\u63d0\u4f9b\u793a\u4f8b HTML \u9875\u9762\uff0c\u5982\u56fe 4.4 \u6240\u793a\u3002\u60a8\u4e0d\u4f1a\u5728\u751f\u4ea7\u5e94\u7528\u7a0b\u5e8f\u4e2d\u4f7f\u7528\u5b83\uff0c\u56e0\u4e3a\u60a8\u65e0\u6cd5\u81ea\u5b9a\u4e49\u8f93\u51fa\uff0c\u4f46\u5b83\u662f\u4e00\u4e2a\u72ec\u7acb\u7684\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528\u5b83\u6765\u786e\u4fdd\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u6b63\u786e\u8fd0\u884c\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0404.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.4 The Welcome-page middleware response. Every request to the application, at any path, will return the same Welcome-page response.<br \/>\n\u56fe 4.4 Welcome-page \u4e2d\u95f4\u4ef6\u54cd\u5e94\u3002\u5728\u4efb\u4f55\u8def\u5f84\u4e0a\u5bf9\u5e94\u7528\u7a0b\u5e8f\u7684\u6bcf\u4e2a\u8bf7\u6c42\u90fd\u5c06\u8fd4\u56de\u76f8\u540c\u7684 Welcome-page \u54cd\u5e94\u3002<\/p>\n<p><strong>Tip<\/strong> WelcomePageMiddleware is included as part of the base ASP.NET Core framework, so you don\u2019t need to add a reference to any additional NuGet packages.<br \/>\n<strong>\u63d0\u793a<\/strong> WelcomePageMiddleware\u4f5c\u4e3a\u57fa\u672c ASP.NET Core \u6846\u67b6\u7684\u4e00\u90e8\u5206\u5305\u542b\u5728\u5185\uff0c\u56e0\u6b64\u65e0\u9700\u6dfb\u52a0\u5bf9\u4efb\u4f55\u5176\u4ed6 NuGet \u5305\u7684\u5f15\u7528\u3002<\/p>\n<p>Even though this application is simple, the same process you\u2019ve seen before occurs when the application receives an HTTP request, as shown in figure 4.5.<\/p>\n<p>\u5c3d\u7ba1\u6b64\u5e94\u7528\u7a0b\u5e8f\u5f88\u7b80\u5355\uff0c\u4f46\u5f53\u5e94\u7528\u7a0b\u5e8f\u6536\u5230 HTTP \u8bf7\u6c42\u65f6\uff0c\u60a8\u4e4b\u524d\u770b\u5230\u7684\u76f8\u540c\u8fc7\u7a0b\u4e5f\u4f1a\u53d1\u751f\uff0c\u5982\u56fe 4.5 \u6240\u793a\u3002<br \/>\n<img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0405.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.5 WelcomePageMiddleware handles a request. The request passes from the reverse proxy to the ASP.NET Core web server and finally to the middleware pipeline, which generates an HTML response.<br \/>\n\u56fe 4.5 WelcomePageMiddleware\u5904\u7406\u8bf7\u6c42\u3002\u8bf7\u6c42\u4ece\u53cd\u5411\u4ee3\u7406\u4f20\u9012\u5230 ASP.NET Core Web \u670d\u52a1\u5668\uff0c\u6700\u540e\u4f20\u9012\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\uff0c\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4f1a\u751f\u6210 HTML \u54cd\u5e94\u3002<\/p>\n<p>The request passes to the ASP.NET Core web server, which builds a representation of the request and passes it to the middleware pipeline. As it\u2019s the first (only!) middleware in the pipeline, WelcomePageMiddleware receives the request and must decide how to handle it. The middleware responds by generating an HTML response, no matter what request it receives. This response passes back to the ASP.NET Core web server, which forwards it to the reverse proxy and then to the user to display in their browser.<\/p>\n<p>\u8bf7\u6c42\u4f20\u9012\u5230 ASP.NET Core Web \u670d\u52a1\u5668\uff0c\u8be5\u670d\u52a1\u5668\u6784\u5efa\u8bf7\u6c42\u7684\u8868\u793a\u5f62\u5f0f\u5e76\u5c06\u5176\u4f20\u9012\u7ed9\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002\u56e0\u4e3a\u5b83\u662f\u7ba1\u9053\u4e2d\u7684\u7b2c\u4e00\u4e2a\uff08\u552f\u4e00\u7684\uff09\u4e2d\u95f4\u4ef6\uff0c\u6240\u4ee5WelcomePageMiddleware\u63a5\u6536\u8bf7\u6c42\u5e76\u4e14\u5fc5\u987b\u51b3\u5b9a\u5982\u4f55\u5904\u7406\u5b83\u3002\u4e2d\u95f4\u4ef6\u901a\u8fc7\u751f\u6210 HTML \u54cd\u5e94\u6765\u54cd\u5e94\uff0c\u65e0\u8bba\u5b83\u6536\u5230\u4ec0\u4e48\u8bf7\u6c42\u3002\u6b64\u54cd\u5e94\u5c06\u4f20\u9012\u56de ASP.NET Core Web \u670d\u52a1\u5668\uff0c\u8be5\u670d\u52a1\u5668\u5c06\u5176\u8f6c\u53d1\u5230\u53cd\u5411\u4ee3\u7406\uff0c\u7136\u540e\u8f6c\u53d1\u7ed9\u7528\u6237\u4ee5\u5728\u5176\u6d4f\u89c8\u5668\u4e2d\u663e\u793a\u3002<\/p>\n<p>As with all ASP.NET Core applications, you define the middleware pipeline in Program.cs by calling Use* methods on the WebApplication instance. To create your first middleware pipeline, which consists of a single middleware component, you need a single method call. The application doesn\u2019t need any extra configuration or services, so your whole application consists of the four lines in the following listing.<\/p>\n<p>\u4e0e\u6240\u6709 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u4e00\u6837\uff0c\u60a8\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u5b9e\u4f8b\u4e0a\u7684\u65b9\u6cd5\u5728 Program.cs \u4e2d\u5b9a\u4e49\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002\u8981\u521b\u5efa\u60a8\u7684\u7b2c\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u7ba1\u9053\uff08\u7531\u5355\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u7ec4\u6210\uff09\uff0c\u60a8\u9700\u8981\u4e00\u4e2a\u65b9\u6cd5\u8c03\u7528\u3002\u8be5\u5e94\u7528\u7a0b\u5e8f\u4e0d\u9700\u8981\u4efb\u4f55\u989d\u5916\u7684\u914d\u7f6e\u6216\u670d\u52a1\uff0c\u56e0\u6b64\u60a8\u7684\u6574\u4e2a\u5e94\u7528\u7a0b\u5e8f\u7531\u4ee5\u4e0b\u6e05\u5355\u4e2d\u7684 4 \u884c\u7ec4\u6210\u3002<\/p>\n<p>Listing 4.1 Program.cs for a Welcome-page middleware pipeline<br \/>\n\u5217\u8868 4.1 Welcome-page \u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684 Program.cs<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nWebApplicationBuilder builder = WebApplication.CreateBuilder(args);   \/\/ \u2776\nWebApplication app = builder.Build();                                 \/\/ \u2776\napp.UseWelcomePage();                                                 \/\/ \u2777\napp.Run();                                                            \/\/ \u2778\n<\/pre>\n<p>\u2776 Uses the default WebApplication configuration<br \/>\n\u4f7f\u7528\u9ed8\u8ba4\u7684 WebApplication \u914d\u7f6e<br \/>\n\u2777 The only custom middleware in the pipeline<br \/>\n\u7ba1\u9053\u4e2d\u552f\u4e00\u7684\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6<br \/>\n\u2778 Runs the application to handle requests<br \/>\n\u8fd0\u884c\u5e94\u7528\u7a0b\u5e8f\u4ee5\u5904\u7406\u8bf7\u6c42<\/p>\n<p>You build up the middleware pipeline in ASP.NET Core by calling methods on WebApplication (which implements IApplicationBuilder). WebApplication doesn\u2019t define methods like UseWelcomePage itself; instead, these are extension methods.<\/p>\n<p>\u60a8\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528 WebApplication\uff08\u5b9e\u73b0 IApplicationBuilder\uff09\u4e0a\u7684\u65b9\u6cd5\uff0c\u5728 ASP.NET Core \u4e2d\u6784\u5efa\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002WebApplication \u4e0d\u5b9a\u4e49 UseWelcomePage \u672c\u8eab\u7b49\u65b9\u6cd5;\u76f8\u53cd\uff0c\u8fd9\u4e9b\u662f\u6269\u5c55\u65b9\u6cd5\u3002<\/p>\n<p>Using extension methods allows you to add functionality to the WebApplication class, while keeping the implementation isolated from it. Under the hood, the methods typically call another extension method to add the middleware to the pipeline. Behind the scenes, for example, the UseWelcomePage method adds the WelcomePageMiddleware to the pipeline by calling<br \/>\n\u4f7f\u7528\u6269\u5c55\u65b9\u6cd5\u53ef\u4ee5\u5411 WebApplication \u7c7b\u6dfb\u52a0\u529f\u80fd\uff0c\u540c\u65f6\u4fdd\u6301\u5b9e\u73b0\u4e0e\u8be5\u7c7b\u9694\u79bb\u3002\u5728\u540e\u53f0\uff0c\u8fd9\u4e9b\u65b9\u6cd5\u901a\u5e38\u4f1a\u8c03\u7528\u53e6\u4e00\u4e2a\u6269\u5c55\u65b9\u6cd5\u4ee5\u5c06\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u7ba1\u9053\u4e2d\u3002\u4f8b\u5982\uff0c\u5728\u540e\u53f0\uff0cUseWelcomePage \u65b9\u6cd5\u901a\u8fc7\u8c03\u7528<\/p>\n<pre><code>UseMiddleware&lt;WelcomePageMiddleware&gt;();<\/code><\/pre>\n<p>This convention of creating an extension method for each piece of middleware and starting the method name with Use is designed to improve discoverability when you add middleware to your application.[2] ASP.NET Core includes a lot of middleware as part of the core framework, so you can use IntelliSense in Visual Studio and other integrated development environments (IDEs) to view all the middleware that\u2019s available, as shown in figure 4.6.<\/p>\n<p>\u8fd9\u79cd\u4e3a\u6bcf\u4e2a\u4e2d\u95f4\u4ef6\u521b\u5efa\u4e00\u4e2a\u6269\u5c55\u65b9\u6cd5\u5e76\u4ee5 Use \u5f00\u5934\u7684\u65b9\u6cd5\u540d\u79f0\u7684\u7ea6\u5b9a\u65e8\u5728\u63d0\u9ad8\u5411\u5e94\u7528\u7a0b\u5e8f\u6dfb\u52a0\u4e2d\u95f4\u4ef6\u65f6\u7684\u53ef\u53d1\u73b0\u6027\u30022 ASP.NET Core \u5305\u542b\u8bb8\u591a\u4e2d\u95f4\u4ef6\u4f5c\u4e3a\u6838\u5fc3\u6846\u67b6\u7684\u4e00\u90e8\u5206\uff0c\u56e0\u6b64\u60a8\u53ef\u4ee5\u5728 Visual Studio \u548c\u5176\u4ed6\u96c6\u6210\u5f00\u53d1\u73af\u5883 \uff08IDE\uff09 \u4e2d\u4f7f\u7528 IntelliSense \u6765\u67e5\u770b\u6240\u6709\u53ef\u7528\u7684\u4e2d\u95f4\u4ef6\uff0c\u5982\u56fe 4.6 \u6240\u793a\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0406.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.6 IntelliSense makes it easy to view all the available middleware to add to your middleware pipeline.<br \/>\n\u56fe 4.6 \u4f7f\u7528 IntelliSense \u53ef\u4ee5\u8f7b\u677e\u67e5\u770b\u8981\u6dfb\u52a0\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u6240\u6709\u53ef\u7528\u4e2d\u95f4\u4ef6\u3002<\/p>\n<p>Calling the UseWelcomePage method adds the WelcomePageMiddleware as the next middleware in the pipeline. Although you\u2019re using only a single middleware component here, it\u2019s important to remember that the order in which you make calls to IApplicationBuilder in Configure defines the order in which the middleware will run in the pipeline.<\/p>\n<p>\u8c03\u7528 UseWelcomePage \u65b9\u6cd5\u4f1a\u5c06 WelcomePageMiddleware \u6dfb\u52a0\u4e3a\u7ba1\u9053\u4e2d\u7684\u4e0b\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u3002\u5c3d\u7ba1\u60a8\u5728\u6b64\u5904\u53ea\u4f7f\u7528\u5355\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\uff0c\u4f46\u8bf7\u52a1\u5fc5\u8bb0\u4f4f\uff0c\u60a8\u5728 Configure \u4e2d\u8c03\u7528 IApplicationBuilder \u7684\u987a\u5e8f\u5b9a\u4e49\u4e86\u4e2d\u95f4\u4ef6\u5728\u7ba1\u9053\u4e2d\u8fd0\u884c\u7684\u987a\u5e8f\u3002<\/p>\n<p><strong>Warning<\/strong> When you\u2019re adding middleware to the pipeline, always take care to consider the order in which it will run. A component can access only data created by middleware that comes before it in the pipeline.<br \/>\n<strong>\u8b66\u544a<\/strong> \u5f53\u60a8\u5c06\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u7ba1\u9053\u65f6\uff0c\u8bf7\u59cb\u7ec8\u6ce8\u610f\u8003\u8651\u5b83\u7684\u8fd0\u884c\u987a\u5e8f\u3002\u7ec4\u4ef6\u53ea\u80fd\u8bbf\u95ee\u7ba1\u9053\u4e2d\u4f4d\u4e8e\u5176\u524d\u9762\u7684\u4e2d\u95f4\u4ef6\u521b\u5efa\u7684\u6570\u636e\u3002<\/p>\n<p>This application is the most basic kind, returning the same response no matter which URL you navigate to, but it shows how easy it is to define your application behavior with middleware. Next, we\u2019ll make things a little more interesting by returning different responses when you make requests to different paths.<\/p>\n<p>\u6b64\u5e94\u7528\u7a0b\u5e8f\u662f\u6700\u57fa\u672c\u7684\u7c7b\u578b\uff0c\u65e0\u8bba\u60a8\u5bfc\u822a\u5230\u54ea\u4e2a URL\uff0c\u5b83\u90fd\u4f1a\u8fd4\u56de\u76f8\u540c\u7684\u54cd\u5e94\uff0c\u4f46\u5b83\u663e\u793a\u4e86\u4f7f\u7528\u4e2d\u95f4\u4ef6\u5b9a\u4e49\u5e94\u7528\u7a0b\u5e8f\u884c\u4e3a\u662f\u591a\u4e48\u5bb9\u6613\u3002\u63a5\u4e0b\u6765\uff0c\u5f53\u60a8\u5411\u4e0d\u540c\u7684\u8def\u5f84\u53d1\u51fa\u8bf7\u6c42\u65f6\uff0c\u6211\u4eec\u5c06\u8fd4\u56de\u4e0d\u540c\u7684\u54cd\u5e94\uff0c\u4ece\u800c\u4f7f\u4e8b\u60c5\u53d8\u5f97\u66f4\u6709\u8da3\u3002<\/p>\n<h4>4.2.2 Simple pipeline scenario 2: Handling static files<\/h4>\n<h4>4.2.2 \u7b80\u5355\u7ba1\u9053\u573a\u666f 2\uff1a\u5904\u7406\u9759\u6001\u6587\u4ef6<\/h4>\n<p>In this section, I\u2019ll show you how to create one of the simplest middleware pipelines you can use for a full application: a static-file application. Most web applications, including those with dynamic content, serve some pages by using static files. Images, JavaScript, and CSS stylesheets are normally saved to disk during development and are served up when requested from the special wwwroot folder of your project, normally as part of a full HTML page request.<\/p>\n<p>\u5728\u672c\u8282\u4e2d\uff0c\u6211\u5c06\u5411\u60a8\u5c55\u793a\u5982\u4f55\u521b\u5efa\u53ef\u7528\u4e8e\u5b8c\u6574\u5e94\u7528\u7a0b\u5e8f\u7684\u6700\u7b80\u5355\u7684\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4e4b\u4e00\uff1a\u9759\u6001\u6587\u4ef6\u5e94\u7528\u7a0b\u5e8f\u3002\u5927\u591a\u6570 Web \u5e94\u7528\u7a0b\u5e8f\uff08\u5305\u62ec\u5177\u6709\u52a8\u6001\u5185\u5bb9\u7684\u5e94\u7528\u7a0b\u5e8f\uff09\u90fd\u4f7f\u7528\u9759\u6001\u6587\u4ef6\u6765\u63d0\u4f9b\u67d0\u4e9b\u9875\u9762\u3002\u56fe\u50cf\u3001JavaScript \u548c CSS \u6837\u5f0f\u8868\u901a\u5e38\u5728\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u4fdd\u5b58\u5230\u78c1\u76d8\u4e2d\uff0c\u5e76\u5728\u4ece\u9879\u76ee\u7684\u7279\u6b8a wwwroot \u6587\u4ef6\u5939\u8bf7\u6c42\u65f6\u63d0\u4f9b\uff0c\u901a\u5e38\u4f5c\u4e3a\u5b8c\u6574 HTML \u9875\u9762\u8bf7\u6c42\u7684\u4e00\u90e8\u5206\u3002<\/p>\n<p><strong>Definition<\/strong> By default, the wwwroot folder is the only folder in your application that ASP.NET Core will serve files from. It doesn\u2019t serve files from other folders for security reasons. The wwwroot folder in an ASP.NET Core project is typically deployed as is to production, including all the files and folders it contains.<br \/>\n<strong>\u5b9a\u4e49<\/strong> \u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cwwwroot \u6587\u4ef6\u5939\u662f\u5e94\u7528\u7a0b\u5e8f\u4e2d ASP.NET Core \u5c06\u4ece\u4e2d\u63d0\u4f9b\u6587\u4ef6\u7684\u552f\u4e00\u6587\u4ef6\u5939\u3002\u51fa\u4e8e\u5b89\u5168\u539f\u56e0\uff0c\u5b83\u4e0d\u4f1a\u63d0\u4f9b\u6765\u81ea\u5176\u4ed6\u6587\u4ef6\u5939\u7684\u6587\u4ef6\u3002ASP.NET Core \u9879\u76ee\u4e2d\u7684 wwwroot \u6587\u4ef6\u5939\u901a\u5e38\u6309\u539f\u6837\u90e8\u7f72\u5230\u751f\u4ea7\u73af\u5883\uff0c\u5305\u62ec\u5b83\u5305\u542b\u7684\u6240\u6709\u6587\u4ef6\u548c\u6587\u4ef6\u5939\u3002<\/p>\n<p>You can use StaticFileMiddleware to serve static files from the wwwroot folder when requested, as shown in figure 4.7. In this example, an image called moon.jpg exists in the wwwroot folder. When you request the file using the \/moon.jpg path, it\u2019s loaded and returned as the response to the request.<br \/>\n\u5f53\u8bf7\u6c42\u65f6\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528 wwwroot \u6587\u4ef6\u5939\u4e2d\u7684\u9759\u6001\u6587\u4ef6\uff0c\u5982\u56fe 4.7 \u6240\u793a\u3002\u5728\u6b64\u793a\u4f8b\u4e2d\uff0c\u540d\u4e3a moon.jpg \u7684\u6620\u50cf\u5b58\u5728\u4e8e wwwroot \u6587\u4ef6\u5939\u4e2d\u3002\u5f53\u60a8\u4f7f\u7528\u8def\u5f84\u8bf7\u6c42\u6587\u4ef6StaticFileMiddleware\/moon.jpg\u65f6\uff0c\u8be5\u6587\u4ef6\u5c06\u52a0\u8f7d\u5e76\u4f5c\u4e3a\u5bf9\u8bf7\u6c42\u7684\u54cd\u5e94\u8fd4\u56de\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0407.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.7 Serving a static image file using the static-file middleware<br \/>\n\u56fe 4.7 \u4f7f\u7528 static-file \u4e2d\u95f4\u4ef6\u63d0\u4f9b\u9759\u6001\u56fe\u50cf\u6587\u4ef6<\/p>\n<p>If the user requests a file that doesn\u2019t exist in the wwwroot folder, such as missing.jpg, the static-file middleware won\u2019t serve a file. Instead, a 404 HTTP error code response will be sent to the user\u2019s browser, which displays its default \u201cFile Not Found\u201d page, as shown in figure 4.8.<\/p>\n<p>\u5982\u679c\u7528\u6237\u8bf7\u6c42 wwwroot \u6587\u4ef6\u5939\u4e2d\u4e0d\u5b58\u5728\u7684\u6587\u4ef6\uff08\u5982 missing.jpg\uff09\uff0c\u5219\u9759\u6001\u6587\u4ef6\u4e2d\u95f4\u4ef6\u4e0d\u4f1a\u63d0\u4f9b\u6587\u4ef6\u3002\u76f8\u53cd\uff0c404 HTTP \u9519\u8bef\u4ee3\u7801\u54cd\u5e94\u5c06\u53d1\u9001\u5230\u7528\u6237\u7684\u6d4f\u89c8\u5668\uff0c\u8be5\u6d4f\u89c8\u5668\u663e\u793a\u5176\u9ed8\u8ba4\u7684 \u201cFile Not Found\u201d \u9875\u9762\uff0c\u5982\u56fe 4.8 \u6240\u793a\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0408.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.8 Returning a 404 to the browser when a file doesn\u2019t exist. The requested file didn\u2019t exist in the wwwroot folder, so the ASP.NET Core application returned a 404 response. Then the browser (Microsoft Edge, in this case) show the user a default \u201cFile Not Found\u201d error pager<br \/>\n\u56fe 4.8 \u5f53\u6587\u4ef6\u4e0d\u5b58\u5728\u65f6\u5411\u6d4f\u89c8\u5668\u8fd4\u56de 404\u3002\u8bf7\u6c42\u7684\u6587\u4ef6\u5728 wwwroot \u6587\u4ef6\u5939\u4e2d\u4e0d\u5b58\u5728\uff0c\u56e0\u6b64 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u8fd4\u56de 404 \u54cd\u5e94\u3002\u7136\u540e\uff0c\u6d4f\u89c8\u5668\uff08\u5728\u672c\u4f8b\u4e2d\u4e3a Microsoft Edge\uff09\u5411\u7528\u6237\u663e\u793a\u9ed8\u8ba4\u7684\u201c\u627e\u4e0d\u5230\u6587\u4ef6\u201d\u9519\u8bef\u5206\u9875\u7a0b\u5e8f<\/p>\n<p><strong>Note<\/strong> How this page looks depends on your browser. In some browsers, you may see a blank page.<br \/>\n<strong>\u6ce8\u610f<\/strong> \u6b64\u9875\u9762\u7684\u5916\u89c2\u53d6\u51b3\u4e8e\u60a8\u7684\u6d4f\u89c8\u5668\u3002\u5728\u67d0\u4e9b\u6d4f\u89c8\u5668\u4e2d\uff0c\u60a8\u53ef\u80fd\u4f1a\u770b\u5230\u4e00\u4e2a\u7a7a\u767d\u9875\u9762\u3002<\/p>\n<p>Building the middleware pipeline for this simple static-file application is easy. The pipeline consists of a single piece of middleware, StaticFileMiddleware, as you can see in the following listing. You don\u2019t need any services, so configuring the middleware pipeline with UseStaticFiles is all that\u2019s required.<\/p>\n<p>\u4e3a\u8fd9\u4e2a\u7b80\u5355\u7684\u9759\u6001\u6587\u4ef6\u5e94\u7528\u7a0b\u5e8f\u6784\u5efa\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5f88\u5bb9\u6613\u3002\u8be5\u7ba1\u9053\u7531\u4e00\u4e2a\u4e2d\u95f4\u4ef6StaticFileMiddleware \u7ec4\u6210\uff0c\u5982\u4e0b\u9762\u7684\u6e05\u5355\u6240\u793a\u3002\u60a8\u4e0d\u9700\u8981\u4efb\u4f55\u670d\u52a1\uff0c\u56e0\u6b64\u4f7f\u7528 UseStaticFiles \u914d\u7f6e\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5c31\u662f\u5168\u90e8\u9700\u8981\u7684\u3002<\/p>\n<p>Listing 4.2 Program.cs for a static-file middleware pipeline<br \/>\n\u5217\u8868 4.2 \u9759\u6001\u6587\u4ef6\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684 Program.cs<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nWebApplicationBuilder builder = WebApplication.CreateBuilder(args);\nWebApplication app = builder.Build();\napp.UseStaticFiles();                                                  \/\/ \u2776\napp.Run();\n<\/pre>\n<p>\u2776 Adds the StaticFileMiddleware to the pipeline<br \/>\n\u5c06 StaticFileMiddleware \u6dfb\u52a0\u5230\u7ba1\u9053\u4e2d<\/p>\n<p><strong>Tip<\/strong> Remember that you can view the application code for this book in the GitHub repository at <a href=\"http:\/\/mng.bz\/Y1qN\">http:\/\/mng.bz\/Y1qN<\/a>.<br \/>\n<strong>\u63d0\u793a<\/strong> \u8bb0\u4f4f\uff0c\u60a8\u53ef\u4ee5\u5728 <a href=\"http:\/\/mng.bz\/Y1qN\">http:\/\/mng.bz\/Y1qN<\/a> \u7684 GitHub \u5b58\u50a8\u5e93\u4e2d\u67e5\u770b\u672c\u4e66\u7684\u5e94\u7528\u7a0b\u5e8f\u4ee3\u7801\u3002<\/p>\n<p>When the application receives a request, the ASP.NET Core web server handles it and passes it to the middleware pipeline. StaticFileMiddleware receives the request and determines whether it can handle it. If the requested file exists, the middleware handles the request and returns the file as the response, as shown in figure 4.9.<\/p>\n<p>\u5f53\u5e94\u7528\u7a0b\u5e8f\u6536\u5230\u8bf7\u6c42\u65f6\uff0cASP.NET Core Web \u670d\u52a1\u5668\u4f1a\u5904\u7406\u8be5\u8bf7\u6c42\u5e76\u5c06\u5176\u4f20\u9012\u7ed9\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002StaticFileMiddleware \u63a5\u6536\u8bf7\u6c42\u5e76\u786e\u5b9a\u5b83\u662f\u5426\u53ef\u4ee5\u5904\u7406\u5b83\u3002\u5982\u679c\u8bf7\u6c42\u7684\u6587\u4ef6\u5b58\u5728\uff0c\u4e2d\u95f4\u4ef6\u4f1a\u5904\u7406\u8bf7\u6c42\u5e76\u8fd4\u56de\u8be5\u6587\u4ef6\u4f5c\u4e3a\u54cd\u5e94\uff0c\u5982\u56fe 4.9 \u6240\u793a\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0409.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.9 StaticFileMiddleware handles a request for a file. The middleware checks the wwwroot folder to see if whether requested moon.jpg file exists. The file exists, so the middleware retrieves it and returns it as the response to the web server and, ultimately, to the browser.<br \/>\n\u56fe 4.9 StaticFileMiddleware \u5904\u7406\u6587\u4ef6\u8bf7\u6c42\u3002\u4e2d\u95f4\u4ef6\u68c0\u67e5 wwwroot \u6587\u4ef6\u5939\u4ee5\u67e5\u770b\u8bf7\u6c42\u7684 moon.jpg \u6587\u4ef6\u662f\u5426\u5b58\u5728\u3002\u8be5\u6587\u4ef6\u5b58\u5728\uff0c\u56e0\u6b64\u4e2d\u95f4\u4ef6\u4f1a\u68c0\u7d22\u5b83\u5e76\u5c06\u5176\u4f5c\u4e3a\u54cd\u5e94\u8fd4\u56de\u7ed9 Web \u670d\u52a1\u5668\uff0c\u5e76\u6700\u7ec8\u8fd4\u56de\u7ed9\u6d4f\u89c8\u5668\u3002<\/p>\n<p>If the file doesn\u2019t exist, the request effectively passes through the static-file middleware unchanged. But wait\u2014you added only one piece of middleware, right? Surely you can\u2019t pass the request through to the next middleware component if there isn\u2019t another one.<\/p>\n<p>\u5982\u679c\u6587\u4ef6\u4e0d\u5b58\u5728\uff0c\u5219\u8bf7\u6c42\u5c06\u539f\u5c01\u4e0d\u52a8\u5730\u6709\u6548\u5730\u901a\u8fc7 static-file \u4e2d\u95f4\u4ef6\u3002\u4f46\u662f\u7b49\u7b49 \u2014 \u60a8\u53ea\u6dfb\u52a0\u4e86\u4e00\u4e2a\u4e2d\u95f4\u4ef6\uff0c\u5bf9\u5427\uff1f\u5f53\u7136\uff0c\u5982\u679c\u6ca1\u6709\u53e6\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\uff0c\u4f60\u5c31\u4e0d\u80fd\u5c06\u8bf7\u6c42\u4f20\u9012\u7ed9\u4e0b\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u3002<\/p>\n<p>ASP.NET Core automatically adds a dummy piece of middleware to the end of the pipeline. This middleware always returns a 404 response if it\u2019s called.<\/p>\n<p>ASP.NET Core \u4f1a\u81ea\u52a8\u5c06\u4e00\u4e2a\u865a\u62df\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u7ba1\u9053\u7684\u672b\u5c3e\u3002\u5982\u679c\u8c03\u7528\u6b64\u4e2d\u95f4\u4ef6\uff0c\u5219\u59cb\u7ec8\u8fd4\u56de 404 \u54cd\u5e94\u3002<\/p>\n<p><strong>Tip<\/strong> If no middleware generates a response for a request, the pipeline automatically returns a simple 404 error response to the browser.<br \/>\n<strong>\u63d0\u793a<\/strong> \u5982\u679c\u6ca1\u6709\u4e2d\u95f4\u4ef6\u4e3a\u8bf7\u6c42\u751f\u6210\u54cd\u5e94\uff0c\u5219\u7ba1\u9053\u4f1a\u81ea\u52a8\u5411\u6d4f\u89c8\u5668\u8fd4\u56de\u7b80\u5355\u7684 404 \u9519\u8bef\u54cd\u5e94\u3002<\/p>\n<blockquote>\n<p>HTTP response status codes<br \/>\nHTTP \u54cd\u5e94\u72b6\u6001\u4ee3\u7801<br \/>\nEvery HTTP response contains a status code and, optionally, a reason phrase describing the status code. Status codes are fundamental to the HTTP protocol and are a standardized way of indicating common results. A 200 response, for example, means that the request was successfully answered, whereas a 404 response indicates that the resource requested couldn\u2019t be found. You can see the full list of standardized status codes at <a href=\"https:\/\/www.rfc-editor.org\/rfc\/rfc9110#name-status-codes\">https:\/\/www.rfc-editor.org\/rfc\/rfc9110#name-status-codes<\/a>.<br \/>\n\u6bcf\u4e2a HTTP \u54cd\u5e94\u90fd\u5305\u542b\u4e00\u4e2a\u72b6\u6001\u4ee3\u7801\u548c\u4e00\u4e2a\u63cf\u8ff0\u72b6\u6001\u4ee3\u7801\u7684\u539f\u56e0\u77ed\u8bed\uff08\u53ef\u9009\uff09\u3002\u72b6\u6001\u4ee3\u7801\u662f HTTP \u534f\u8bae\u7684\u57fa\u7840\uff0c\u662f\u8868\u793a\u5e38\u89c1\u7ed3\u679c\u7684\u6807\u51c6\u5316\u65b9\u5f0f\u3002\u4f8b\u5982\uff0c200 \u54cd\u5e94\u8868\u793a\u8bf7\u6c42\u5df2\u6210\u529f\u54cd\u5e94\uff0c\u800c 404 \u54cd\u5e94\u8868\u793a\u627e\u4e0d\u5230\u8bf7\u6c42\u7684\u8d44\u6e90\u3002\u60a8\u53ef\u4ee5\u5728 <a href=\"https:\/\/www.rfc-editor.org\/rfc\/rfc9110#name-status-codes\">https:\/\/www.rfc-editor.org\/rfc\/rfc9110#name-status-codes<\/a> \u4e0a\u67e5\u770b\u6807\u51c6\u5316\u72b6\u6001\u4ee3\u7801\u7684\u5b8c\u6574\u5217\u8868\u3002<br \/>\nStatus codes are always three digits long and are grouped in five classes, based on the first digit:<br \/>\n\u72b6\u6001\u4ee3\u7801\u59cb\u7ec8\u4e3a\u4e09\u4f4d\u6570\uff0c\u5e76\u6839\u636e\u7b2c\u4e00\u4f4d\u6570\u5b57\u5206\u4e3a\u4e94\u7c7b\uff1a<br \/>\n\u00b7   1xx\u2014Information. This code is not often used; it provides a general acknowledgment.<br \/>\n1xx - \u4fe1\u606f\u3002\u6b64\u4ee3\u7801\u4e0d\u7ecf\u5e38\u4f7f\u7528;\u5b83\u63d0\u4f9b\u4e86\u4e00\u4e2a\u4e00\u822c\u6027\u7684\u786e\u8ba4\u3002<br \/>\n\u00b7   2xx\u2014Success. The request was successfully handled and processed.<br \/>\n2xx - \u6210\u529f\u3002\u5df2\u6210\u529f\u5904\u7406\u548c\u5904\u7406\u8bf7\u6c42\u3002<br \/>\n\u00b7   3xx\u2014Redirection. The browser must follow the provided link to allow the user to log in, for example.<br \/>\n3xx \u2014 \u91cd\u5b9a\u5411\u3002\u4f8b\u5982\uff0c\u6d4f\u89c8\u5668\u5fc5\u987b\u6309\u7167\u63d0\u4f9b\u7684\u94fe\u63a5\u5141\u8bb8\u7528\u6237\u767b\u5f55\u3002<br \/>\n\u00b7   4xx\u2014Client error. A problem occurred with the request. The request sent invalid data, for example, or the user isn\u2019t authorized to perform the request.<br \/>\n4xx \u2014 \u5ba2\u6237\u7aef\u9519\u8bef\u3002\u8bf7\u6c42\u51fa\u73b0\u95ee\u9898\u3002\u4f8b\u5982\uff0c\u8bf7\u6c42\u53d1\u9001\u4e86\u65e0\u6548\u6570\u636e\uff0c\u6216\u8005\u7528\u6237\u65e0\u6743\u6267\u884c\u8bf7\u6c42\u3002<br \/>\n\u00b7   5xx\u2014Server error. A problem on the server caused the request to fail.<br \/>\n5xx \u2014 \u670d\u52a1\u5668\u9519\u8bef\u3002\u670d\u52a1\u5668\u4e0a\u7684\u95ee\u9898\u5bfc\u81f4\u8bf7\u6c42\u5931\u8d25\u3002<br \/>\nThese status codes typically drive the behavior of a user\u2019s browser. The browser will handle a 301 response automatically, for example, by redirecting to the provided new link and making a second request, all without the user\u2019s interaction.<br \/>\n\u8fd9\u4e9b\u72b6\u6001\u4ee3\u7801\u901a\u5e38\u9a71\u52a8\u7528\u6237\u6d4f\u89c8\u5668\u7684\u884c\u4e3a\u3002\u6d4f\u89c8\u5668\u5c06\u81ea\u52a8\u5904\u7406 301 \u54cd\u5e94\uff0c\u4f8b\u5982\uff0c\u91cd\u5b9a\u5411\u5230\u63d0\u4f9b\u7684\u65b0\u94fe\u63a5\u5e76\u53d1\u51fa\u7b2c\u4e8c\u4e2a\u8bf7\u6c42\uff0c\u6240\u6709\u8fd9\u4e9b\u90fd\u65e0\u9700\u7528\u6237\u4ea4\u4e92\u3002<br \/>\nError codes are in the 4xx and 5xx classes. Common codes include a 404 response when a file couldn\u2019t be found, a 400 error when a client sends invalid data (such as an invalid email address), and a 500 error when an error occurs on the server. HTTP responses for error codes may include a response body, which is content to display when the client receives the response.<br \/>\n\u9519\u8bef\u4ee3\u7801\u4f4d\u4e8e 4xx \u548c 5xx \u7c7b\u4e2d\u3002\u5e38\u89c1\u4ee3\u7801\u5305\u62ec\u627e\u4e0d\u5230\u6587\u4ef6\u65f6\u7684 404 \u54cd\u5e94\u3001\u5ba2\u6237\u7aef\u53d1\u9001\u65e0\u6548\u6570\u636e\uff08\u4f8b\u5982\u65e0\u6548\u7684\u7535\u5b50\u90ae\u4ef6\u5730\u5740\uff09\u65f6\u7684 400 \u9519\u8bef\uff0c\u4ee5\u53ca\u670d\u52a1\u5668\u4e0a\u53d1\u751f\u9519\u8bef\u65f6\u7684 500 \u9519\u8bef\u3002\u9519\u8bef\u4ee3\u7801\u7684 HTTP \u54cd\u5e94\u53ef\u80fd\u5305\u62ec\u54cd\u5e94\u6b63\u6587\uff0c\u8be5\u6b63\u6587\u662f\u5ba2\u6237\u7aef\u6536\u5230\u54cd\u5e94\u65f6\u8981\u663e\u793a\u7684\u5185\u5bb9\u3002<\/p>\n<\/blockquote>\n<p>This basic ASP.NET Core application makes it easy to see the behavior of the ASP.NET Core middleware pipeline and the static-file middleware in particular, but it\u2019s unlikely that your applications will be this simple. It\u2019s more likely that static files will form one part of your middleware pipeline. In the next section you\u2019ll see how to combine multiple middleware components as we look at a simple minimal API application.<\/p>\n<p>\u8fd9\u4e2a\u57fa\u672c\u7684 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u53ef\u4ee5\u8f7b\u677e\u67e5\u770b ASP.NET Core \u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u884c\u4e3a\uff0c\u5c24\u5176\u662f\u9759\u6001\u6587\u4ef6\u4e2d\u95f4\u4ef6\uff0c\u4f46\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u4e0d\u592a\u53ef\u80fd\u5982\u6b64\u7b80\u5355\u3002\u9759\u6001\u6587\u4ef6\u66f4\u6709\u53ef\u80fd\u6784\u6210\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u4e00\u90e8\u5206\u3002\u5728\u4e0b\u4e00\u8282\u4e2d\uff0c\u60a8\u5c06\u770b\u5230\u5982\u4f55\u7ec4\u5408\u591a\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\uff0c\u56e0\u4e3a\u6211\u4eec\u5c06\u4e86\u89e3\u4e00\u4e2a\u7b80\u5355\u7684\u6700\u5c0f API \u5e94\u7528\u7a0b\u5e8f\u3002<\/p>\n<h4>4.2.3 Simple pipeline scenario 3: A minimal API application<\/h4>\n<h4>4.2.3 \u7b80\u5355\u7ba1\u9053\u573a\u666f 3\uff1a\u4e00\u4e2a\u6700\u5c0f\u7684 API \u5e94\u7528\u7a0b\u5e8f<\/h4>\n<p>By this point, you should have a decent grasp of the middleware pipeline, insofar as you understand that it defines your application\u2019s behavior. In this section you\u2019ll see how to combine several standard middleware components to form a pipeline. As before, you do this in Program.cs by adding middleware to the WebApplication object.<\/p>\n<p>\u6b64\u65f6\uff0c\u60a8\u5e94\u8be5\u5bf9\u4e2d\u95f4\u4ef6\u7ba1\u9053\u6709\u4e00\u5b9a\u7684\u4e86\u89e3\uff0c\u53ea\u8981\u60a8\u4e86\u89e3\u5b83\u5b9a\u4e49\u4e86\u5e94\u7528\u7a0b\u5e8f\u7684\u884c\u4e3a\u3002\u5728\u672c\u8282\u4e2d\uff0c\u60a8\u5c06\u4e86\u89e3\u5982\u4f55\u7ec4\u5408\u591a\u4e2a\u6807\u51c6\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u4ee5\u5f62\u6210\u4e00\u4e2a\u7ba1\u9053\u3002\u548c\u4ee5\u524d\u4e00\u6837\uff0c\u60a8\u53ef\u4ee5\u901a\u8fc7\u5c06\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230 WebApplication \u5bf9\u8c61\u6765\u5728 Program.cs \u4e2d\u6267\u884c\u6b64\u4f5c\u3002<\/p>\n<p>You\u2019ll begin by creating a basic middleware pipeline that you\u2019d find in a typical ASP.NET Core minimal APIs template and then extend it by adding middleware. Figure 4.10 shows the output you see when you navigate to the home page of the application\u2014identical to the sample application in chapter 3.<\/p>\n<p>\u9996\u5148\uff0c\u60a8\u5c06\u521b\u5efa\u4e00\u4e2a\u57fa\u672c\u7684\u4e2d\u95f4\u4ef6\u7ba1\u9053\uff0c\u8be5\u7ba1\u9053\u53ef\u4ee5\u5728\u5178\u578b\u7684 ASP.NET Core \u6700\u5c0f API \u6a21\u677f\u4e2d\u627e\u5230\uff0c\u7136\u540e\u901a\u8fc7\u6dfb\u52a0\u4e2d\u95f4\u4ef6\u6765\u6269\u5c55\u5b83\u3002\u56fe 4.10 \u663e\u793a\u4e86\u5bfc\u822a\u5230\u5e94\u7528\u7a0b\u5e8f\u4e3b\u9875\u65f6\u770b\u5230\u7684\u8f93\u51fa\uff0c\u4e0e\u7b2c 3 \u7ae0\u4e2d\u7684\u793a\u4f8b\u5e94\u7528\u7a0b\u5e8f\u76f8\u540c\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0410.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.10 A simple minimal API application. The application uses only four pieces of middleware: routing middleware to choose the endpoint to run, endpoint middleware to generate the response from a Razor Page, static-file middleware to serve image files, and exception-handler middleware to capture any errors.<br \/>\n\u56fe 4.10 \u4e00\u4e2a\u7b80\u5355\u7684\u6700\u5c0f API \u5e94\u7528\u7a0b\u5e8f\u3002\u5e94\u7528\u7a0b\u5e8f\u53ea\u4f7f\u7528\u56db\u4e2a\u4e2d\u95f4\u4ef6\uff1a\u8def\u7531\u4e2d\u95f4\u4ef6\u6765\u9009\u62e9\u8981\u8fd0\u884c\u7684\u7aef\u70b9\uff0cendpoint \u4e2d\u95f4\u4ef6\uff08\u7528\u4e8e\u4ece Razor \u9875\u9762\u751f\u6210\u54cd\u5e94\uff09\u3001\u9759\u6001\u6587\u4ef6\u4e2d\u95f4\u4ef6\uff08\u7528\u4e8e\u63d0\u4f9b\u56fe\u50cf\u6587\u4ef6\uff09\u548c\u5f02\u5e38\u5904\u7406\u7a0b\u5e8f\u4e2d\u95f4\u4ef6\uff08\u7528\u4e8e\u6355\u83b7\u4efb\u4f55\u9519\u8bef\uff09\u3002<\/p>\n<p>Creating this application requires only four pieces of middleware: routing middleware to choose a minimal API endpoint to execute, endpoint middleware to generate the response, static-file middleware to serve any image files from the wwwroot folder, and exception-handler middleware to handle any errors that might occur. Even though this example is still a Hello World! example, this architecture is much closer to a realistic example. The following listing shows an example of such an application.<\/p>\n<p>\u521b\u5efa\u6b64\u5e94\u7528\u7a0b\u5e8f\u53ea\u9700\u8981\u56db\u4e2a\u4e2d\u95f4\u4ef6\uff1a\u7528\u4e8e\u9009\u62e9\u8981\u6267\u884c\u7684\u6700\u5c0f API \u7ec8\u7aef\u8282\u70b9\u7684\u8def\u7531\u4e2d\u95f4\u4ef6\u3001\u7528\u4e8e\u751f\u6210\u54cd\u5e94\u7684\u7ec8\u7aef\u8282\u70b9\u4e2d\u95f4\u4ef6\u3001\u7528\u4e8e\u63d0\u4f9b wwwroot \u6587\u4ef6\u5939\u4e2d\u4efb\u4f55\u56fe\u50cf\u6587\u4ef6\u7684\u9759\u6001\u6587\u4ef6\u4e2d\u95f4\u4ef6\uff0c\u4ee5\u53ca\u7528\u4e8e\u5904\u7406\u53ef\u80fd\u53d1\u751f\u7684\u4efb\u4f55\u9519\u8bef\u7684\u5f02\u5e38\u5904\u7406\u7a0b\u5e8f\u4e2d\u95f4\u4ef6\u3002\u5373\u4f7f\u6b64\u793a\u4f8b\u4ecd\u7136\u662f Hello World\uff01 example\uff0c\u6b64\u4f53\u7cfb\u7ed3\u6784\u66f4\u63a5\u8fd1\u4e8e\u5b9e\u9645\u793a\u4f8b\u3002\u4e0b\u9762\u7684\u6e05\u5355\u663e\u793a\u4e86\u6b64\u7c7b\u5e94\u7528\u7a0b\u5e8f\u7684\u4e00\u4e2a\u793a\u4f8b\u3002<\/p>\n<p>Listing 4.3 A basic middleware pipeline for a minimal APIs application<br \/>\n\u6e05\u5355 4.3 \u7528\u4e8e\u6700\u5c0f API \u5e94\u7528\u7a0b\u5e8f\u7684\u57fa\u672c\u4e2d\u95f4\u4ef6\u7ba1\u9053<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nvar builder = WebApplication.CreateBuilder(args);\nvar app = builder.Build();\napp.UseDeveloperExceptionPage();         \/\/ \u2776\napp.UseStaticFiles();                    \/\/ \u2777\napp.UseRouting();                        \/\/ \u2778\napp.MapGet(&quot;\/&quot;, () =&gt; &quot;Hello World!&quot;);   \/\/ \u2779\n\napp.Run();\n<\/pre>\n<p>\u2776 This call isn\u2019t strictly necessary, as it\u2019s already added by WebApplication by default.<br \/>\n\u6b64\u8c03\u7528\u5e76\u975e\u7edd\u5bf9\u5fc5\u8981\uff0c\u56e0\u4e3a\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u5b83\u5df2\u7531 WebApplication \u6dfb\u52a0\u3002<\/p>\n<p>\u2777 Adds the StaticFileMiddleware to the pipeline<br \/>\n\u5c06 StaticFileMiddleware \u6dfb\u52a0\u5230\u7ba1\u9053\u4e2d<\/p>\n<p>\u2778 Adds the RoutingMiddleware to the pipeline<br \/>\n\u5c06 RoutingMiddleware \u6dfb\u52a0\u5230\u7ba1\u9053\u4e2d<\/p>\n<p>\u2779 Defines an endpoint for the application<br \/>\n\u4e3a\u5e94\u7528\u7a0b\u5e8f\u5b9a\u4e49\u7aef\u70b9<\/p>\n<p>The addition of middleware to WebApplication to form the pipeline should be familiar to you now, but several points are worth noting in this example:<br \/>\n\u60a8\u73b0\u5728\u5e94\u8be5\u5f88\u719f\u6089\u5411 WebApplication \u6dfb\u52a0\u4e2d\u95f4\u4ef6\u4ee5\u5f62\u6210\u7ba1\u9053\uff0c\u4f46\u5728\u6b64\u793a\u4f8b\u4e2d\uff0c\u6709\u51e0\u70b9\u503c\u5f97\u6ce8\u610f\uff1a<\/p>\n<ul>\n<li>Middleware is added with Use<em>() methods.<br \/>\n\u4e2d\u95f4\u4ef6\u662f\u4f7f\u7528 Use<\/em>\uff08\uff09 \u65b9\u6cd5\u6dfb\u52a0\u7684\u3002<\/li>\n<li>MapGet defines an endpoint, not middleware. It defines the endpoints that the routing and endpoint middleware can use.<br \/>\nMapGet \u5b9a\u4e49\u7aef\u70b9\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u4ef6\u3002\u5b83\u5b9a\u4e49\u8def\u7531\u548c\u7ec8\u7aef\u8282\u70b9\u4e2d\u95f4\u4ef6\u53ef\u4ee5\u4f7f\u7528\u7684\u7ec8\u7aef\u8282\u70b9\u3002<\/li>\n<li>WebApplication automatically adds some middleware to the pipeline, such as the EndpointMiddleware.<br \/>\nWebApplication \u4f1a\u81ea\u52a8\u5411\u7ba1\u9053\u4e2d\u6dfb\u52a0\u4e00\u4e9b\u4e2d\u95f4\u4ef6\uff0c\u4f8b\u5982 EndpointMiddleware\u3002<\/li>\n<li>The order of the Use<em>() method calls is important and defines the order of the middleware pipeline.<br \/>\nUse<\/em>\uff08\uff09 \u65b9\u6cd5\u8c03\u7528\u7684\u987a\u5e8f\u5f88\u91cd\u8981\uff0c\u5b83\u5b9a\u4e49\u4e86\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u987a\u5e8f\u3002<\/li>\n<\/ul>\n<p>First, all the methods for adding middleware start with Use. As I mentioned earlier, this is thanks to the convention of using extension methods to extend the functionality of WebApplication; prefixing the methods with Use should make them easier to discover.<\/p>\n<p>\u9996\u5148\uff0c\u6dfb\u52a0\u4e2d\u95f4\u4ef6\u7684\u6240\u6709\u65b9\u6cd5\u90fd\u4ee5 Use \u5f00\u5934\u3002\u6b63\u5982\u6211\u524d\u9762\u63d0\u5230\u7684\uff0c\u8fd9\u8981\u5f52\u529f\u4e8e\u4f7f\u7528\u6269\u5c55\u65b9\u6cd5\u6765\u6269\u5c55 WebApplication \u529f\u80fd\u7684\u7ea6\u5b9a;\u4e3a\u65b9\u6cd5\u6dfb\u52a0\u524d\u7f00 Use \u5e94\u8be5\u4f1a\u4f7f\u5b83\u4eec\u66f4\u5bb9\u6613\u88ab\u53d1\u73b0\u3002<\/p>\n<p>Second, it\u2019s important to understand that the MapGet method does not add middleware to the pipeline; it defines an endpoint in your application. These endpoints are used by the routing and endpoint middleware. You\u2019ll learn more about endpoints and routing in chapter 5.<\/p>\n<p>\u5176\u6b21\uff0c\u8bf7\u52a1\u5fc5\u4e86\u89e3 MapGet \u65b9\u6cd5\u4e0d\u4f1a\u5c06\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u7ba1\u9053\u4e2d;\u5b83\u5b9a\u4e49\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u7ec8\u7aef\u8282\u70b9\u3002\u8fd9\u4e9b\u7ec8\u7aef\u8282\u70b9\u7531\u8def\u7531\u548c\u7ec8\u7aef\u8282\u70b9\u4e2d\u95f4\u4ef6\u4f7f\u7528\u3002\u60a8\u5c06\u5728\u7b2c 5 \u7ae0\u4e2d\u4e86\u89e3\u6709\u5173\u7ec8\u7aef\u8282\u70b9\u548c\u8def\u7531\u7684\u66f4\u591a\u4fe1\u606f\u3002<\/p>\n<p><strong>Tip<\/strong> You can define the endpoints for your app by using MapGet() anywhere in Program.cs before the call to app.Run(), but the calls are typically placed after the middleware pipeline definition.<br \/>\n<strong>\u63d0\u793a<\/strong> \u60a8\u53ef\u4ee5\u4f7f\u7528MapGet\uff08\uff09 Program.cs\u5728\u8c03\u7528\u5e94\u7528\u7a0b\u5e8f\u3002Run\uff08\uff09\uff0c\u4f46\u8c03\u7528\u901a\u5e38\u653e\u5728\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5b9a\u4e49\u4e4b\u540e\u3002<\/p>\n<p>In chapter 3, I mentioned that WebApplication automatically adds middleware to your app. You can see this process in action in listing 4.3 automatically adding the EndpointMiddleware to the end of the middleware pipeline. WebApplication also automatically adds the developer exception page middleware to the start of the middleware pipeline when you\u2019re running in development. As a result, you can omit the call to UseDeveloperExceptionPage() from listing 4.3, and your middleware pipeline will be essentially the same.<\/p>\n<p>\u5728\u7b2c 3 \u7ae0\u4e2d\uff0c\u6211\u63d0\u5230\u4e86 WebApplication \u4f1a\u81ea\u52a8\u5c06\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u4e2d\u3002\u4f60\u53ef\u4ee5\u5728\u6e05\u5355 4.3 \u4e2d\u770b\u5230\u8fd9\u4e2a\u8fc7\u7a0b\u7684\u5b9e\u9645\u6548\u679c\uff0c\u5b83\u81ea\u52a8\u5c06 EndpointMiddleware \u6dfb\u52a0\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u672b\u5c3e\u3002\u5f53\u60a8\u5728\u5f00\u53d1\u4e2d\u8fd0\u884c\u65f6\uff0cWebApplication \u8fd8\u4f1a\u81ea\u52a8\u5c06\u5f00\u53d1\u4eba\u5458\u5f02\u5e38\u9875\u9762\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u5f00\u5934\u3002\u56e0\u6b64\uff0c\u60a8\u53ef\u4ee5\u7701\u7565\u6e05\u5355 4.3 \u4e2d\u5bf9 UseDeveloperExceptionPage\uff08\uff09 \u7684\u8c03\u7528\uff0c\u60a8\u7684\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5c06\u57fa\u672c\u76f8\u540c\u3002<\/p>\n<blockquote>\n<p>WebApplication and autoadded middleware<br \/>\nWebApplication \u548c\u81ea\u52a8\u6dfb\u52a0\u7684\u4e2d\u95f4\u4ef6<br \/>\nWebApplication and WebApplicationBuilder were introduced in .NET 6 to try to reduce the amount of boilerplate code required for a Hello World! ASP.NET Core application. As part of this initiative, Microsoft chose to have WebApplication automatically add various middleware to the pipeline. This decision alleviates some of the common getting-started pain points of middleware ordering by ensuring that, for example, UseRouting() is always called before UseAuthorization().<br \/>\nWebApplication \u548c WebApplicationBuilder \u662f\u5728 .NET 6 \u4e2d\u5f15\u5165\u7684\uff0c\u65e8\u5728\u5c1d\u8bd5\u51cf\u5c11 &quot;Hello World&quot; ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u6240\u9700\u7684\u6837\u677f\u4ee3\u7801\u91cf\uff01\u3002\u4f5c\u4e3a\u8be5\u8ba1\u5212\u7684\u4e00\u90e8\u5206\uff0cMicrosoft \u9009\u62e9\u8ba9 WebApplication \u81ea\u52a8\u5c06\u5404\u79cd\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u7ba1\u9053\u4e2d\u3002\u6b64\u51b3\u5b9a\u901a\u8fc7\u786e\u4fdd\uff08\u4f8b\u5982\uff09\u59cb\u7ec8\u5728 UseAuthorization\uff08\uff09 \u4e4b\u524d\u8c03\u7528 UseRouting\uff08\uff09\uff0c\u7f13\u89e3\u4e86\u4e2d\u95f4\u4ef6\u6392\u5e8f\u7684\u4e00\u4e9b\u5e38\u89c1\u5165\u95e8\u75db\u70b9\u3002<br \/>\nEverything has trade-offs, of course, and for WebApplication the trade-off is that it\u2019s harder to understand exactly what\u2019s in your middleware pipeline without having deep knowledge of the framework code itself.<br \/>\n\u5f53\u7136\uff0c\u4e00\u5207\u90fd\u6709\u6743\u8861\uff0c\u5bf9\u4e8e WebApplication \u6765\u8bf4\uff0c\u6743\u8861\u662f\uff0c\u5982\u679c\u4e0d\u6df1\u5165\u4e86\u89e3\u6846\u67b6\u4ee3\u7801\u672c\u8eab\uff0c\u5c31\u66f4\u96be\u51c6\u786e\u7406\u89e3\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4e2d\u7684\u5185\u5bb9\u3002<br \/>\nLuckily, you don\u2019t need to worry about the middleware that WebApplication adds for the most part. If you\u2019re new to ASP.NET Core, generally you can accept that WebApplication will add the middleware only when it\u2019s necessary and safe to do so.<br \/>\n\u5e78\u8fd0\u7684\u662f\uff0c\u60a8\u65e0\u9700\u62c5\u5fc3WebApplication \u5728\u5f88\u5927\u7a0b\u5ea6\u4e0a\u589e\u52a0\u4e86\u3002\u5982\u679c\u60a8\u662f ASP.NET Core \u7684\u65b0\u7528\u6237\uff0c\u901a\u5e38\uff0c\u4f60\u53ef\u4ee5\u63a5\u53d7 WebApplication \u4ec5\u5728\u5fc5\u8981\u4e14\u5b89\u5168\u7684\u60c5\u51b5\u4e0b\u624d\u4f1a\u6dfb\u52a0\u4e2d\u95f4\u4ef6\u3002<br \/>\nNevertheless, in some cases it may pay to know exactly what\u2019s in your pipeline, especially if you\u2019re familiar with ASP.NET Core. In .NET 7, WebApplication automatically adds some or all of the following middleware to the start of the middleware pipeline:<br \/>\n\u4e0d\u8fc7\uff0c\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u786e\u5207\u5730\u4e86\u89e3\u4f60\u7684\u7ba1\u9053\u4e2d\u7684\u5185\u5bb9\u53ef\u80fd\u662f\u503c\u5f97\u7684\uff0c\u7279\u522b\u662f\u5982\u679c\u4f60\u719f\u6089 ASP.NET Core\u3002\u5728 .NET 7 \u4e2d\uff0cWebApplication \u4f1a\u81ea\u52a8\u5c06\u4ee5\u4e0b\u90e8\u5206\u6216\u5168\u90e8\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u5f00\u5934\uff1a<br \/>\n\u00b7   HostFilteringMiddleware\u2014This middleware is security-related. You can read more about why it\u2019s useful and how to configure it at <a href=\"http:\/\/mng.bz\/zXxa\">http:\/\/mng.bz\/zXxa<\/a>.<br \/>\nHostFilteringMiddleware \u2014 \u6b64\u4e2d\u95f4\u4ef6\u4e0e\u5b89\u5168\u6027\u76f8\u5173\u3002\u60a8\u53ef\u4ee5\u5728 <a href=\"http:\/\/mng.bz\/zXxa\">http:\/\/mng.bz\/zXxa<\/a> \u4e2d\u9605\u8bfb\u6709\u5173\u5b83\u4e3a\u4f55\u6709\u7528\u4ee5\u53ca\u5982\u4f55\u914d\u7f6e\u5b83\u7684\u66f4\u591a\u4fe1\u606f\u3002<br \/>\n\u00b7   ForwardedHeadersMiddleware\u2014This middleware controls how forwarded headers are handled. You can read more about it in chapter 27.<br \/>\nForwardedHeadersMiddleware \u2014 \u6b64\u4e2d\u95f4\u4ef6\u63a7\u5236\u5982\u4f55\u5904\u7406\u8f6c\u53d1\u7684\u6807\u5934\u3002\u60a8\u53ef\u4ee5\u5728\u7b2c 27 \u7ae0\u4e2d\u9605\u8bfb\u66f4\u591a\u76f8\u5173\u4fe1\u606f\u3002<br \/>\n\u00b7   DeveloperExceptionPageMiddleware\u2014As already discussed, this middleware is added when you run in a development environment.<br \/>\nDeveloperExceptionPageMiddleware \u2014 \u5982\u524d\u6240\u8ff0\uff0c\u5f53\u60a8\u5728\u5f00\u53d1\u73af\u5883\u4e2d\u8fd0\u884c\u65f6\uff0c\u4f1a\u6dfb\u52a0\u6b64\u4e2d\u95f4\u4ef6\u3002<br \/>\n\u00b7   RoutingMiddleware\u2014If you add any endpoints to your application, UseRouting() runs before you add any custom middleware to your application.<br \/>\nRoutingMiddleware \u2014 \u5982\u679c\u60a8\u5411\u5e94\u7528\u7a0b\u5e8f\u6dfb\u52a0\u4efb\u4f55\u7ec8\u7aef\u8282\u70b9\uff0c\u5219 UseRouting\uff08\uff09 \u4f1a\u5728\u60a8\u5411\u5e94\u7528\u7a0b\u5e8f\u6dfb\u52a0\u4efb\u4f55\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6\u4e4b\u524d\u8fd0\u884c\u3002<br \/>\n\u00b7   AuthenticationMiddleware\u2014If you configure authentication, this middleware authenticates a user for the request. Chapter 23 discusses authentication in detail.<br \/>\nAuthenticationMiddleware \u2014 \u5982\u679c\u60a8\u914d\u7f6e\u8eab\u4efd\u9a8c\u8bc1\uff0c\u5219\u6b64\u4e2d\u95f4\u4ef6\u5c06\u5bf9\u8bf7\u6c42\u7684\u7528\u6237\u8fdb\u884c\u8eab\u4efd\u9a8c\u8bc1\u3002\u7b2c 23 \u7ae0\u8be6\u7ec6\u8ba8\u8bba\u4e86\u8eab\u4efd\u9a8c\u8bc1\u3002<br \/>\n\u00b7   AuthorizationMiddleware\u2014The authorization middleware runs after authentication and determines whether a user is permitted to execute an endpoint. If the user doesn\u2019t have permission, the request is short-circuited. I discuss authorization in detail in chapter 24.<br \/>\nAuthorizationMiddleware \u2014 \u6388\u6743\u4e2d\u95f4\u4ef6\u5728\u8eab\u4efd\u9a8c\u8bc1\u540e\u8fd0\u884c\uff0c\u5e76\u786e\u5b9a\u662f\u5426\u5141\u8bb8\u7528\u6237\u6267\u884c\u7ec8\u7aef\u8282\u70b9\u3002\u5982\u679c\u7528\u6237\u6ca1\u6709\u6743\u9650\uff0c\u5219\u8bf7\u6c42\u5c06\u77ed\u8def\u3002\u6211\u5728\u7b2c 24 \u7ae0\u4e2d\u8be6\u7ec6\u8ba8\u8bba\u4e86\u6388\u6743\u3002<br \/>\n\u00b7   EndpointMiddleware\u2014This middleware pairs with the RoutingMiddleware to execute an endpoint. Unlike the other middleware described here, the EndpointMiddleware is added to the end of the middleware pipeline, after any other middleware you configure in Program.cs.<br \/>\nEndpointMiddleware \u2014 \u6b64\u4e2d\u95f4\u4ef6\u4e0e RoutingMiddleware \u914d\u5bf9\u4ee5\u6267\u884c\u7ec8\u7aef\u8282\u70b9\u3002\u4e0e\u6b64\u5904\u63cf\u8ff0\u7684\u5176\u4ed6\u4e2d\u95f4\u4ef6\u4e0d\u540c\uff0cEndpointMiddleware \u88ab\u6dfb\u52a0\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u672b\u5c3e\uff0c\u4f4d\u4e8e\u60a8\u5728 Program.cs \u4e2d\u914d\u7f6e\u7684\u4efb\u4f55\u5176\u4ed6\u4e2d\u95f4\u4ef6\u4e4b\u540e\u3002<br \/>\nDepending on your Program.cs configuration, WebApplication may not add all this middleware. Also, if you don\u2019t want some of this automatic middleware to be at the start of your middleware pipeline, generally you can override the location. In listing 4.3, for example, we override the automatic RoutingMiddleware location by calling UseRouting() explicitly, ensuring that routing occurs exactly where we need it.<br \/>\n\u6839\u636e\u60a8\u7684 Program.cs \u914d\u7f6e\uff0cWebApplication \u53ef\u80fd\u4e0d\u4f1a\u6dfb\u52a0\u6240\u6709\u8fd9\u4e9b\u4e2d\u95f4\u4ef6\u3002\u6b64\u5916\uff0c\u5982\u679c\u60a8\u4e0d\u5e0c\u671b\u67d0\u4e9b\u81ea\u52a8\u4e2d\u95f4\u4ef6\u4f4d\u4e8e\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u5f00\u5934\uff0c\u901a\u5e38\u53ef\u4ee5\u8986\u76d6\u8be5\u4f4d\u7f6e\u3002\u4f8b\u5982\uff0c\u5728\u6e05\u5355 4.3 \u4e2d\uff0c\u6211\u4eec\u901a\u8fc7\u663e\u5f0f\u8c03\u7528 UseRouting\uff08\uff09\u6765\u8986\u76d6\u81ea\u52a8\u5b9a\u4f4dRoutingMiddleware\uff0c\u786e\u4fdd\u8def\u7531\u6070\u597d\u53d1\u751f\u5728\u6211\u4eec\u9700\u8981\u7684\u5730\u65b9\u3002<\/p>\n<\/blockquote>\n<p>Another important point about listing 4.3 is that the order in which you add the middleware to the WebApplication object is the order in which the middleware is added to the pipeline. The order of the calls in listing 4.3 creates a pipeline similar to that shown in figure 4.11.<\/p>\n<p>\u6e05\u5355 4.3 \u7684\u53e6\u4e00\u4e2a\u8981\u70b9\u662f\uff0c\u5c06\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230 WebApplication \u5bf9\u8c61\u7684\u987a\u5e8f\u5c31\u662f\u5c06\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u7ba1\u9053\u7684\u987a\u5e8f\u3002\u6e05\u5355 4.3 \u4e2d\u7684\u8c03\u7528\u987a\u5e8f\u5c06\u521b\u5efa\u4e00\u4e2a\u7c7b\u4f3c\u4e8e\u56fe 4.11 \u6240\u793a\u7684\u7ba1\u9053\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0411.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.11 The middleware pipeline for the example application in listing 4.3. The order in which you add the middleware to WebApplication defines the order of the middleware in the pipeline.<br \/>\n\u56fe 4.11 \u6e05\u5355 4.3 \u4e2d\u793a\u4f8b\u5e94\u7528\u7a0b\u5e8f\u7684\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002\u5c06\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230 WebApplication \u7684\u987a\u5e8f\u5b9a\u4e49\u4e86\u4e2d\u95f4\u4ef6\u5728\u7ba1\u9053\u4e2d\u7684\u987a\u5e8f\u3002<\/p>\n<p>The ASP.NET Core web server passes the incoming request to the developer exception page middleware first. This exception-handler middleware ignores the request initially; its purpose is to catch any exceptions thrown by later middleware in the pipeline, as you\u2019ll see in section 4.3. It\u2019s important for this middleware to be placed early in the pipeline so that it can catch errors produced by later middleware.<\/p>\n<p>ASP.NET Core Web \u670d\u52a1\u5668\u9996\u5148\u5c06\u4f20\u5165\u8bf7\u6c42\u4f20\u9012\u7ed9\u5f00\u53d1\u4eba\u5458\u5f02\u5e38\u9875\u9762\u4e2d\u95f4\u4ef6\u3002\u6b64\u5f02\u5e38\u5904\u7406\u7a0b\u5e8f\u4e2d\u95f4\u4ef6\u6700\u521d\u4f1a\u5ffd\u7565\u8bf7\u6c42;\u5b83\u7684\u76ee\u7684\u662f\u6355\u83b7\u7ba1\u9053\u4e2d\u540e\u7eed middleware \u629b\u51fa\u7684\u4efb\u4f55\u5f02\u5e38\uff0c\u5982 4.3 \u8282\u6240\u793a\u3002\u5c06\u6b64\u4e2d\u95f4\u4ef6\u653e\u5728\u7ba1\u9053\u7684\u65e9\u671f\u975e\u5e38\u91cd\u8981\uff0c\u8fd9\u6837\u5b83\u5c31\u53ef\u4ee5\u6355\u83b7\u540e\u7eed\u4e2d\u95f4\u4ef6\u4ea7\u751f\u7684\u9519\u8bef\u3002<\/p>\n<p>The developer exception page middleware passes the request on to the static-file middleware. The static-file handler generates a response if the request corresponds to a file; otherwise, it passes the request on to the routing middleware. The routing middleware selects a minimal API endpoint based on the endpoints defined and the request URL, and the endpoint middleware executes the selected minimal API endpoint. If no endpoint can handle the requested URL, the automatic dummy middleware returns a 404 response.<\/p>\n<p>\u5f00\u53d1\u4eba\u5458\u5f02\u5e38\u9875\u9762\u4e2d\u95f4\u4ef6\u5c06\u8bf7\u6c42\u4f20\u9012\u7ed9\u9759\u6001\u6587\u4ef6\u4e2d\u95f4\u4ef6\u3002\u5982\u679c\u8bf7\u6c42\u5bf9\u5e94\u4e8e\u6587\u4ef6\uff0c\u5219 static-file \u5904\u7406\u7a0b\u5e8f\u4f1a\u751f\u6210\u54cd\u5e94;\u5426\u5219\uff0c\u5b83\u5c06\u8bf7\u6c42\u4f20\u9012\u7ed9\u8def\u7531\u4e2d\u95f4\u4ef6\u3002\u8def\u7531\u4e2d\u95f4\u4ef6\u6839\u636e\u5b9a\u4e49\u7684\u7aef\u70b9\u548c\u8bf7\u6c42 URL \u9009\u62e9\u6700\u5c0f API \u7aef\u70b9\uff0c\u7aef\u70b9\u4e2d\u95f4\u4ef6\u6267\u884c\u9009\u5b9a\u7684\u6700\u5c0f API \u7aef\u70b9\u3002\u5982\u679c\u6ca1\u6709\u7ec8\u7aef\u8282\u70b9\u53ef\u4ee5\u5904\u7406\u8bf7\u6c42\u7684 URL\uff0c\u5219\u81ea\u52a8\u865a\u62df\u4e2d\u95f4\u4ef6\u5c06\u8fd4\u56de 404 \u54cd\u5e94\u3002<\/p>\n<p>In chapter 3, I mentioned that WebApplication adds the RoutingMiddleware to the start of the middleware pipeline automatically. So you may be wondering why I explicitly added it to the pipeline in listing 4.3 using UseRouting().<\/p>\n<p>\u5728\u7b2c 3 \u7ae0\u4e2d\uff0c\u6211\u63d0\u5230 WebApplication \u4f1a\u81ea\u52a8\u5c06 RoutingMiddleware \u6dfb\u52a0\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u5f00\u5934\u3002\u56e0\u6b64\uff0c\u60a8\u53ef\u80fd\u60f3\u77e5\u9053\u4e3a\u4ec0\u4e48\u6211\u4f7f\u7528 UseRouting\uff08\uff09 \u5c06\u5b83\u663e\u5f0f\u6dfb\u52a0\u5230\u6e05\u5355 4.3 \u4e2d\u7684\u7ba1\u9053\u4e2d\u3002<\/p>\n<p>The answer, again, is related to the order of the middleware. Adding an explicit call to UseRouting() tells WebApplication not to add the RoutingMiddleware automatically before the middleware defined in Program.cs. This allows us to \u201cmove\u201d the RoutingMiddleware to be placed after the StaticFileMiddleware. Although this step isn\u2019t strictly necessary in this case, it\u2019s good practice. The StaticFileMiddleware doesn\u2019t use routing, so it\u2019s preferable to let this middleware check whether the incoming request is for a static file; if so, it can short-circuit the pipeline and avoid the unnecessary call to the RoutingMiddleware.<\/p>\n<p>\u7b54\u6848\u540c\u6837\u4e0e\u4e2d\u95f4\u4ef6\u7684\u987a\u5e8f\u6709\u5173\u3002\u6dfb\u52a0\u5bf9 UseRouting\uff08\uff09 \u7684\u663e\u5f0f\u8c03\u7528\u4f1a\u544a\u8bc9 WebApplication \u4e0d\u8981\u5728 Program.cs \u4e2d\u5b9a\u4e49\u7684\u4e2d\u95f4\u4ef6\u4e4b\u524d\u81ea\u52a8\u6dfb\u52a0 RoutingMiddleware\u3002\u8fd9\u5141\u8bb8\u6211\u4eec\u5c06 RoutingMiddleware \u201c\u79fb\u52a8\u201d \u4e3a\u653e\u7f6e\u5728 StaticFileMiddleware \u4e4b\u540e\u3002\u5c3d\u7ba1\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u6b64\u6b65\u9aa4\u5e76\u975e\u7edd\u5bf9\u5fc5\u8981\uff0c\u4f46\u8fd9\u662f\u4e00\u79cd\u5f88\u597d\u7684\u505a\u6cd5\u3002StaticFileMiddleware \u4e0d\u4f7f\u7528\u8def\u7531\uff0c\u56e0\u6b64\u6700\u597d\u8ba9\u8fd9\u4e2a\u4e2d\u95f4\u4ef6\u68c0\u67e5\u4f20\u5165\u7684\u8bf7\u6c42\u662f\u5426\u662f\u9488\u5bf9\u9759\u6001\u6587\u4ef6\u7684;\u5982\u679c\u662f\u8fd9\u6837\uff0c\u5b83\u53ef\u4ee5\u4f7f\u7ba1\u9053\u77ed\u8def\u5e76\u907f\u514d\u5bf9 RoutingMiddleware \u7684\u4e0d\u5fc5\u8981\u8c03\u7528\u3002<\/p>\n<p><strong>Note<\/strong> In versions 1.x and 2.x of ASP.NET Core, the routing and endpoint middleware were combined in a single Model-View-Controller (MVC) middleware component. Splitting the responsibilities for routing from execution makes it possible to insert middleware between the routing and endpoint middleware. I discuss routing further in chapters 6 and 14.<br \/>\n<strong>\u6ce8\u610f<\/strong> \u5728 ASP.NET Core \u7684 1.x \u548c 2.x \u7248\u672c\u4e2d\uff0c\u8def\u7531\u548c\u7aef\u70b9\u4e2d\u95f4\u4ef6\u7ec4\u5408\u5728\u4e00\u4e2a\u6a21\u578b-\u89c6\u56fe-\u63a7\u5236\u5668 \uff08MVC\uff09 \u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u4e2d\u3002\u5c06\u8def\u7531\u7684\u8d23\u4efb\u4e0e\u6267\u884c\u5206\u5f00\uff0c\u53ef\u4ee5\u5728\u8def\u7531\u548c\u7ec8\u7aef\u8282\u70b9\u4e2d\u95f4\u4ef6\u4e4b\u95f4\u63d2\u5165\u4e2d\u95f4\u4ef6\u3002\u6211\u5728\u7b2c 6 \u7ae0\u548c\u7b2c 14 \u7ae0\u4e2d\u8fdb\u4e00\u6b65\u8ba8\u8bba\u4e86\u8def\u7531\u3002<\/p>\n<p>The impact of ordering is most obvious when you have two pieces of middleware that are listening for the same path. The endpoint middleware in the example pipeline currently responds to a request to the home page of the application (with the \/ path) by returning the string &quot;Hello World!&quot;, as shown in figure 4.10. Figure 4.12 shows what happens if you reintroduce a piece of middleware that you saw previously, WelcomePageMiddleware, and configure it to respond to the \/ path as well.<\/p>\n<p>\u5f53\u4f60\u6709\u4e24\u4e2a middleware \u6b63\u5728\u4fa6\u542c\u540c\u4e00\u8def\u5f84\u65f6\uff0c\u6392\u5e8f\u7684\u5f71\u54cd\u6700\u4e3a\u660e\u663e\u3002\u793a\u4f8b\u7ba1\u9053\u4e2d\u7684\u7ec8\u7aef\u8282\u70b9\u4e2d\u95f4\u4ef6\u5f53\u524d\u901a\u8fc7\u8fd4\u56de\u5b57\u7b26\u4e32 \u201cHello World\uff01\u201d \u6765\u54cd\u5e94\u5bf9\u5e94\u7528\u7a0b\u5e8f\u4e3b\u9875\uff08\u4f7f\u7528 \/ \u8def\u5f84\uff09\u7684\u8bf7\u6c42\uff0c\u5982\u56fe 4.10 \u6240\u793a\u3002\u56fe 4.12 \u663e\u793a\u4e86\u5982\u679c\u4f60\u91cd\u65b0\u5f15\u5165\u4e4b\u524d\u770b\u5230\u7684\u4e2d\u95f4\u4ef6 WelcomePageMiddleware\uff0c\u5e76\u5c06\u5176\u914d\u7f6e\u4e3a\u4e5f\u54cd\u5e94 \/ \u8def\u5f84\u4f1a\u53d1\u751f\u4ec0\u4e48\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0412.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.12 The Welcome-page middleware response. The Welcome-page middleware comes before the endpoint middleware, so a request to the home page returns the Welcome-page middleware instead of the minimal API response.<br \/>\n\u56fe 4.12 Welcome-page \u4e2d\u95f4\u4ef6\u54cd\u5e94\u3002Welcome-page \u4e2d\u95f4\u4ef6\u4f4d\u4e8e\u7aef\u70b9\u4e2d\u95f4\u4ef6\u4e4b\u524d\uff0c\u56e0\u6b64\u5bf9\u4e3b\u9875\u7684\u8bf7\u6c42\u5c06\u8fd4\u56de Welcome-page \u4e2d\u95f4\u4ef6\uff0c\u800c\u4e0d\u662f\u6700\u5c0f\u7684 API \u54cd\u5e94\u3002<\/p>\n<p>As you saw in section 4.2.1, WelcomePageMiddleware is designed to return a fixed HTML response, so you wouldn\u2019t use it in a production app, but it illustrates the point nicely. In the following listing, it\u2019s added to the start of the middleware pipeline and configured to respond only to the &quot;\/&quot; path.<\/p>\n<p>\u6b63\u5982\u4f60\u5728 4.2.1 \u8282\u4e2d\u770b\u5230\u7684\uff0cWelcomePageMiddleware \u88ab\u8bbe\u8ba1\u4e3a\u8fd4\u56de\u4e00\u4e2a\u56fa\u5b9a\u7684 HTML \u54cd\u5e94\uff0c\u6240\u4ee5\u4f60\u4e0d\u4f1a\u5728\u751f\u4ea7\u5e94\u7528\u7a0b\u5e8f\u4e2d\u4f7f\u7528\u5b83\uff0c\u4f46\u5b83\u5f88\u597d\u5730\u8bf4\u660e\u4e86\u8fd9\u4e00\u70b9\u3002\u5728\u4e0b\u9762\u7684\u6e05\u5355\u4e2d\uff0c\u5b83\u88ab\u6dfb\u52a0\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u5f00\u5934\uff0c\u5e76\u914d\u7f6e\u4e3a\u4ec5\u54cd\u5e94 \u201c\/\u201d \u8def\u5f84\u3002<\/p>\n<p>Listing 4.4 Adding WelcomePageMiddleware to the pipeline<br \/>\n\u6e05\u5355 4.4 \u6dfb\u52a0\u5230\u7ba1\u9053WelcomePageMiddleware<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nWebApplicationBuilder builder = WebApplication.CreateBuilder(args);\nWebApplication app = builder.Build();\napp.UseWelcomePage(&quot;\/&quot;);                                 \/\/\u2776\napp.UseDeveloperExceptionPage();\napp.UseStaticFiles();\napp.UseRouting();                                        \/\/\u2777\napp.MapGet(&quot;\/&quot;, () =&gt; &quot;Hello World!&quot;);                   \/\/\u2777\napp.Run();\n<\/pre>\n<p>\u2776 WelcomePageMiddleware handles all requests to the \u201c\/\u201d path and returns a sample HTML response.<br \/>\nWelcomePageMiddleware \u5904\u7406\u5bf9 \u201c\/\u201d \u8def\u5f84\u7684\u6240\u6709\u8bf7\u6c42\uff0c\u5e76\u8fd4\u56de\u4e00\u4e2a\u793a\u4f8b HTML \u54cd\u5e94\u3002<br \/>\n\u2777 Requests to \u201c\/\u201d will never reach the endpoint middleware, so this endpoint won\u2019t be called.<br \/>\n\u5bf9 \u201c\/\u201d \u7684\u8bf7\u6c42\u6c38\u8fdc\u4e0d\u4f1a\u5230\u8fbe\u7aef\u70b9\u4e2d\u95f4\u4ef6\uff0c\u56e0\u6b64\u4e0d\u4f1a\u8c03\u7528\u6b64\u7aef\u70b9\u3002<\/p>\n<p>Even though you know that the endpoint middleware can also handle the &quot;\/&quot; path, WelcomePageMiddleware is earlier in the pipeline, so it returns a response when it receives the request to &quot;\/&quot;, short-circuiting the pipeline, as shown in figure 4.13. None of the other middleware in the pipeline runs for the request, so none has an opportunity to generate a response.<br \/>\n\u5373\u4f7f\u60a8\u77e5\u9053\u7aef\u70b9\u4e2d\u95f4\u4ef6\u4e5f\u53ef\u4ee5\u5904\u7406 \u201c\/\u201d \u8def\u5f84\uff0c\u4f46 WelcomePageMiddleware \u4f4d\u4e8e\u7ba1\u9053\u7684\u65e9\u671f\uff0c\u56e0\u6b64\u5f53\u5b83\u6536\u5230\u5bf9 \u201c\/\u201d \u7684\u8bf7\u6c42\u65f6\uff0c\u5b83\u4f1a\u8fd4\u56de\u54cd\u5e94\uff0c\u4ece\u800c\u4f7f\u7ba1\u9053\u77ed\u8def\uff0c\u5982\u56fe 4.13 \u6240\u793a\u3002\u7ba1\u9053\u4e2d\u7684\u5176\u4ed6\u4e2d\u95f4\u4ef6\u90fd\u4e0d\u4f1a\u4e3a\u8bf7\u6c42\u8fd0\u884c\uff0c\u56e0\u6b64\u6ca1\u6709\u673a\u4f1a\u751f\u6210\u54cd\u5e94\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0413.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.13 Overview of the application handling a request to the &quot;\/&quot; path. The Welcome-page middleware is first in the middleware pipeline, so it receives the request before any other middleware. It generates an HTML response, short-circuiting the pipeline. No other middleware runs for the request.<br \/>\n\u56fe 4.13 \u5904\u7406\u5bf9 \u201c\/\u201d \u8def\u5f84\u8bf7\u6c42\u7684\u5e94\u7528\u7a0b\u5e8f\u6982\u8ff0\u3002\u6b22\u8fce\u9875\u9762middleware \u5728\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4e2d\u6392\u5728\u7b2c\u4e00\u4f4d\uff0c\u56e0\u6b64\u5b83\u4f1a\u5728\u4efb\u4f55\u5176\u4ed6\u4e2d\u95f4\u4ef6\u4e4b\u524d\u6536\u5230\u8bf7\u6c42\u3002\u5b83\u751f\u6210 HTML \u54cd\u5e94\uff0c\u4f7f\u7ba1\u9053\u77ed\u8def\u3002\u6ca1\u6709\u5176\u4ed6\u4e2d\u95f4\u4ef6\u4e3a\u8bf7\u6c42\u8fd0\u884c\u3002<\/p>\n<p>As WebApplication automatically adds EndpointMiddleware to the end of the middleware pipeline, the WelcomePageMiddleware will always be ahead of it, so it always generates a response before the endpoint can execute in this example.<\/p>\n<p>\u7531\u4e8e WebApplication \u4f1a\u81ea\u52a8\u5c06 EndpointMiddleware \u6dfb\u52a0\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u672b\u5c3e\uff0c\u56e0\u6b64 WelcomePageMiddleware \u5c06\u59cb\u7ec8\u4f4d\u4e8e\u5176\u524d\u9762\uff0c\u56e0\u6b64\u5728\u6b64\u793a\u4f8b\u4e2d\uff0c\u5b83\u603b\u662f\u5728\u7aef\u70b9\u53ef\u4ee5\u6267\u884c\u4e4b\u524d\u751f\u6210\u54cd\u5e94\u3002<\/p>\n<p><strong>Tip<\/strong> You should always consider the order of middleware when adding it to WebApplication. Middleware added earlier in the pipeline will run (and potentially return a response) before middleware added later.<br \/>\n<strong>\u63d0\u793a<\/strong> \u5728\u5c06\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230 WebApplication \u65f6\uff0c\u60a8\u5e94\u8be5\u59cb\u7ec8\u8003\u8651\u4e2d\u95f4\u4ef6\u7684\u987a\u5e8f\u3002\u5728\u7ba1\u9053\u4e2d\u8f83\u65e9\u6dfb\u52a0\u7684\u4e2d\u95f4\u4ef6\u5c06\u5728\u7a0d\u540e\u6dfb\u52a0\u7684\u4e2d\u95f4\u4ef6\u4e4b\u524d\u8fd0\u884c \uff08\u5e76\u53ef\u80fd\u8fd4\u56de\u54cd\u5e94\uff09 \u3002<\/p>\n<p>All the examples shown so far try to handle an incoming request and generate a response, but it\u2019s important to remember that the middleware pipeline is bidirectional. Each middleware component gets an opportunity to handle both the incoming request and the outgoing response. The order of middleware is most important for those components that create or modify the outgoing response.<\/p>\n<p>\u5230\u76ee\u524d\u4e3a\u6b62\u663e\u793a\u7684\u6240\u6709\u793a\u4f8b\u90fd\u5c1d\u8bd5\u5904\u7406\u4f20\u5165\u8bf7\u6c42\u5e76\u751f\u6210\u54cd\u5e94\uff0c\u4f46\u8bf7\u52a1\u5fc5\u8bb0\u4f4f\uff0c\u4e2d\u95f4\u4ef6\u7ba1\u9053\u662f\u53cc\u5411\u7684\u3002\u6bcf\u4e2a\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u90fd\u6709\u673a\u4f1a\u540c\u65f6\u5904\u7406\u4f20\u5165\u8bf7\u6c42\u548c\u4f20\u51fa\u54cd\u5e94\u3002\u4e2d\u95f4\u4ef6\u7684\u987a\u5e8f\u5bf9\u4e8e\u521b\u5efa\u6216\u4fee\u6539\u4f20\u51fa\u54cd\u5e94\u7684\u7ec4\u4ef6\u6700\u4e3a\u91cd\u8981\u3002<\/p>\n<p>In listing 4.3, I included DeveloperExceptionPageMiddleware at the start of the application\u2019s middleware pipeline, but it didn\u2019t seem to do anything. Error-handling middleware characteristically ignores the incoming request as it arrives in the pipeline; instead, it inspects the outgoing response, modifying it only when an error has occurred. In the next section, I discuss the types of error-handling middleware that are available to use with your application and when to use them.<\/p>\n<p>\u5728\u6e05\u5355 4.3 \u4e2d\uff0c\u6211\u5728\u5e94\u7528\u7a0b\u5e8f\u7684\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u5f00\u5934\u6dfb\u52a0\u4e86 DeveloperExceptionPageMiddleware\uff0c\u4f46\u5b83\u4f3c\u4e4e\u6ca1\u6709\u505a\u4efb\u4f55\u4e8b\u60c5\u3002\u9519\u8bef\u5904\u7406\u4e2d\u95f4\u4ef6\u901a\u5e38\u5728\u4f20\u5165\u8bf7\u6c42\u5230\u8fbe\u7ba1\u9053\u65f6\u5ffd\u7565\u8be5\u8bf7\u6c42;\u76f8\u53cd\uff0c\u5b83\u4f1a\u68c0\u67e5\u4f20\u51fa\u54cd\u5e94\uff0c\u4ec5\u5728\u53d1\u751f\u9519\u8bef\u65f6\u5bf9\u5176\u8fdb\u884c\u4fee\u6539\u3002\u5728\u4e0b\u4e00\u8282\u4e2d\uff0c\u6211\u5c06\u8ba8\u8bba\u53ef\u7528\u4e8e\u5e94\u7528\u7a0b\u5e8f\u7684\u9519\u8bef\u5904\u7406\u4e2d\u95f4\u4ef6\u7684\u7c7b\u578b\u4ee5\u53ca\u4f55\u65f6\u4f7f\u7528\u5b83\u4eec\u3002<\/p>\n<h3>4.3 Handling errors using middleware<\/h3>\n<h3>4.3 \u4f7f\u7528\u4e2d\u95f4\u4ef6\u5904\u7406\u9519\u8bef<\/h3>\n<p>Errors are a fact of life when you\u2019re developing applications. Even if you write perfect code, as soon as you release and deploy your application, users will find a way to break it, by accident or intentionally! The important thing is that your application handles these errors gracefully, providing a suitable response to the user and not causing your whole application to fail.<\/p>\n<p>\u5728\u5f00\u53d1\u5e94\u7528\u7a0b\u5e8f\u65f6\uff0c\u9519\u8bef\u662f\u4e0d\u53ef\u907f\u514d\u7684\u4e8b\u5b9e\u3002\u5373\u4f7f\u60a8\u7f16\u5199\u4e86\u5b8c\u7f8e\u7684\u4ee3\u7801\uff0c\u4e00\u65e6\u60a8\u53d1\u5e03\u548c\u90e8\u7f72\u4e86\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\uff0c\u7528\u6237\u4e5f\u4f1a\u627e\u5230\u4e00\u79cd\u65b9\u6cd5\u6765\u7834\u574f\u5b83\uff0c\u65e0\u8bba\u662f\u6709\u610f\u8fd8\u662f\u6709\u610f\uff01\u91cd\u8981\u7684\u662f\uff0c\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u8981\u59a5\u5584\u5904\u7406\u8fd9\u4e9b\u9519\u8bef\uff0c\u4e3a\u7528\u6237\u63d0\u4f9b\u9002\u5f53\u7684\u54cd\u5e94\uff0c\u5e76\u4e14\u4e0d\u4f1a\u5bfc\u81f4\u6574\u4e2a\u5e94\u7528\u7a0b\u5e8f\u5931\u8d25\u3002<\/p>\n<p>The design philosophy for ASP.NET Core is that every feature is opt-in. So because error handling is a feature, you need to enable it explicitly in your application. Many types of errors could occur in your application, and you have many ways to handle them, but in this section I focus on a single type of error: exceptions.<\/p>\n<p>ASP.NET Core \u7684\u8bbe\u8ba1\u7406\u5ff5\u662f\u6bcf\u4e2a\u529f\u80fd\u90fd\u662f\u53ef\u9009\u7684\u3002\u56e0\u6b64\uff0c\u7531\u4e8e\u9519\u8bef\u5904\u7406\u662f\u4e00\u9879\u529f\u80fd\uff0c\u56e0\u6b64\u60a8\u9700\u8981\u5728\u5e94\u7528\u7a0b\u5e8f\u4e2d\u663e\u5f0f\u542f\u7528\u5b83\u3002\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u4e2d\u53ef\u80fd\u4f1a\u53d1\u751f\u8bb8\u591a\u7c7b\u578b\u7684\u9519\u8bef\uff0c\u60a8\u6709\u591a\u79cd\u65b9\u6cd5\u53ef\u4ee5\u5904\u7406\u8fd9\u4e9b\u9519\u8bef\uff0c\u4f46\u5728\u672c\u8282\u4e2d\uff0c\u6211\u5c06\u91cd\u70b9\u4ecb\u7ecd\u4e00\u79cd\u7c7b\u578b\u7684\u9519\u8bef\uff1a\u5f02\u5e38\u3002<\/p>\n<p>Exceptions typically occur whenever you find an unexpected circumstance. A typical (and highly frustrating) exception you\u2019ll no doubt have experienced before is NullReferenceException, which is thrown when you attempt to access a variable that hasn\u2019t been initialized.[3] If an exception occurs in a middleware component, it propagates up the pipeline, as shown in figure 4.14. If the pipeline doesn\u2019t handle the exception, the web server returns a 500 status code to the user.<\/p>\n<p>\u6bcf\u5f53\u53d1\u73b0\u610f\u5916\u60c5\u51b5\u65f6\uff0c\u901a\u5e38\u4f1a\u53d1\u751f\u5f02\u5e38\u3002\u60a8\u4ee5\u524d\u65e0\u7591\u4f1a\u9047\u5230\u4e00\u4e2a\u5178\u578b\u7684\uff08\u4e14\u975e\u5e38\u4ee4\u4eba\u6cae\u4e27\u7684\uff09\u5f02\u5e38\u662f NullReferenceException\uff0c\u5f53\u60a8\u5c1d\u8bd5\u8bbf\u95ee\u5c1a\u672a\u521d\u59cb\u5316\u7684\u53d8\u91cf\u65f6\uff0c\u4f1a\u5f15\u53d1\u8be5\u5f02\u5e38\u30023 \u5982\u679c\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u4e2d\u53d1\u751f\u5f02\u5e38\uff0c\u5b83\u4f1a\u6cbf\u7ba1\u9053\u5411\u4e0a\u4f20\u64ad\uff0c\u5982\u56fe 4.14 \u6240\u793a\u3002\u5982\u679c\u7ba1\u9053\u672a\u5904\u7406\u5f02\u5e38\uff0c\u5219 Web \u670d\u52a1\u5668\u5c06\u5411\u7528\u6237\u8fd4\u56de 500 \u72b6\u6001\u4ee3\u7801\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0414.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.14 An exception in the endpoint middleware propagates through the pipeline. If the exception isn\u2019t caught by middleware earlier in the pipeline, a 500 \u201cServer error\u201d status code is sent to the user\u2019s browser.<br \/>\n\u56fe 4.14 \u7aef\u70b9\u4e2d\u95f4\u4ef6\u4e2d\u7684\u5f02\u5e38\u901a\u8fc7\u7ba1\u9053\u4f20\u64ad\u3002\u5982\u679c\u7ba1\u9053\u4e2d\u8f83\u65e9\u7684\u4e2d\u95f4\u4ef6\u672a\u6355\u83b7\u5f02\u5e38\uff0c\u5219\u4f1a\u5411\u7528\u6237\u7684\u6d4f\u89c8\u5668\u53d1\u9001 500 \u7684\u201c\u670d\u52a1\u5668\u9519\u8bef\u201d\u72b6\u6001\u4ee3\u7801\u3002<\/p>\n<p>In some situations, an error won\u2019t cause an exception. Instead, middleware might generate an error status code. One such case occurs when a requested path isn\u2019t handled. In that situation, the pipeline returns a 404 error.<br \/>\n\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u9519\u8bef\u4e0d\u4f1a\u5bfc\u81f4\u5f02\u5e38\u3002\u76f8\u53cd\uff0c\u4e2d\u95f4\u4ef6\u53ef\u80fd\u4f1a\u751f\u6210\u9519\u8bef\u72b6\u6001\u4ee3\u7801\u3002\u5f53\u8bf7\u6c42\u7684\u8def\u5f84\u672a\u5f97\u5230\u5904\u7406\u65f6\uff0c\u5c31\u4f1a\u51fa\u73b0\u4e00\u79cd\u60c5\u51b5\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u7ba1\u9053\u5c06\u8fd4\u56de 404 \u9519\u8bef\u3002<\/p>\n<p>For APIs, which typically are consumed by apps (as opposed to end users), that result probably is fine. But for apps that typically generate HTML, such as Razor Pages apps, returning a 404 typically results in a generic, unfriendly page being shown to the user, as you saw in figure 4.8. Although this behavior is correct, it doesn\u2019t provide a great experience for users of these types of applications.<\/p>\n<p>\u5bf9\u4e8e\u901a\u5e38\u7531\u5e94\u7528\u7a0b\u5e8f \uff08\u800c\u4e0d\u662f\u6700\u7ec8\u7528\u6237\uff09 \u4f7f\u7528\u7684 API\uff0c\u8be5\u7ed3\u679c\u53ef\u80fd\u5f88\u597d\u3002\u4f46\u5bf9\u4e8e\u901a\u5e38\u751f\u6210 HTML \u7684\u5e94\u7528\u7a0b\u5e8f\uff08\u5982 Razor Pages \u5e94\u7528\u7a0b\u5e8f\uff09\uff0c\u8fd4\u56de 404 \u901a\u5e38\u4f1a\u5bfc\u81f4\u5411\u7528\u6237\u663e\u793a\u901a\u7528\u7684\u3001\u4e0d\u53cb\u597d\u7684\u9875\u9762\uff0c\u5982\u56fe 4.8 \u6240\u793a\u3002\u5c3d\u7ba1\u6b64\u884c\u4e3a\u662f\u6b63\u786e\u7684\uff0c\u4f46\u5b83\u4e0d\u4f1a\u4e3a\u8fd9\u4e9b\u7c7b\u578b\u5e94\u7528\u7a0b\u5e8f\u7684\u7528\u6237\u63d0\u4f9b\u51fa\u8272\u7684\u4f53\u9a8c\u3002<\/p>\n<p>Error-handling middleware attempts to address these problems by modifying the response before the app returns it to the user. Typically, error-handling middleware returns either details on the error that occurred or a generic but friendly HTML page to the user. You\u2019ll learn how to handle this use case in chapter 13 when you learn about generating responses with Razor Pages.<\/p>\n<p>\u9519\u8bef\u5904\u7406\u4e2d\u95f4\u4ef6\u5c1d\u8bd5\u901a\u8fc7\u5728\u5e94\u7528\u7a0b\u5e8f\u5c06\u54cd\u5e94\u8fd4\u56de\u7ed9\u7528\u6237\u4e4b\u524d\u4fee\u6539\u54cd\u5e94\u6765\u89e3\u51b3\u8fd9\u4e9b\u95ee\u9898\u3002\u901a\u5e38\uff0c\u9519\u8bef\u5904\u7406\u4e2d\u95f4\u4ef6\u4f1a\u8fd4\u56de\u6709\u5173\u6240\u53d1\u751f\u9519\u8bef\u7684\u8be6\u7ec6\u4fe1\u606f\uff0c\u6216\u8005\u5411\u7528\u6237\u8fd4\u56de\u901a\u7528\u4f46\u53cb\u597d\u7684 HTML \u9875\u9762\u3002\u5728\u7b2c 13 \u7ae0\u4e2d\uff0c\u60a8\u5c06\u4e86\u89e3\u5982\u4f55\u4f7f\u7528 Razor Pages \u751f\u6210\u54cd\u5e94\uff0c\u4ece\u800c\u4e86\u89e3\u5982\u4f55\u5904\u7406\u6b64\u7528\u4f8b\u3002<\/p>\n<p>The remainder of this section looks at the two main types of exception-handling middleware that\u2019s available for use in your application. Both are available as part of the base ASP.NET Core framework, so you don\u2019t need to reference any additional NuGet packages to use them.<\/p>\n<p>\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u5c06\u4ecb\u7ecd\u53ef\u5728\u5e94\u7528\u7a0b\u5e8f\u4e2d\u4f7f\u7528\u7684\u4e24\u79cd\u4e3b\u8981\u7c7b\u578b\u7684\u5f02\u5e38\u5904\u7406\u4e2d\u95f4\u4ef6\u3002\u4e24\u8005\u90fd\u4f5c\u4e3a\u57fa\u672c ASP.NET Core \u6846\u67b6\u7684\u4e00\u90e8\u5206\u63d0\u4f9b\uff0c\u56e0\u6b64\u65e0\u9700\u5f15\u7528\u4efb\u4f55\u5176\u4ed6 NuGet \u5305\u5373\u53ef\u4f7f\u7528\u5b83\u4eec\u3002<\/p>\n<h4>4.3.1 Viewing exceptions in development: DeveloperExceptionPage<\/h4>\n<h4>\u67e5\u770b\u5f00\u53d1\u4e2d\u7684\u5f02\u5e38\uff1aDeveloperExceptionPage<\/h4>\n<p>When you\u2019re developing an application, you typically want access to as much information as possible when an error occurs somewhere in your app. For that reason, Microsoft provides DeveloperExceptionPageMiddleware, which you can add to your middleware pipeline by using<br \/>\n\u5728\u5f00\u53d1\u5e94\u7528\u7a0b\u5e8f\u65f6\uff0c\u60a8\u901a\u5e38\u5e0c\u671b\u5728\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u67d0\u4e2a\u4f4d\u7f6e\u53d1\u751f\u9519\u8bef\u65f6\u8bbf\u95ee\u5c3d\u53ef\u80fd\u591a\u7684\u4fe1\u606f\u3002\u56e0\u6b64\uff0cMicrosoft \u63d0\u4f9b\u4e86 DeveloperExceptionPageMiddleware\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528<\/p>\n<pre><code>app.UseDeveloperExceptionPage();<\/code><\/pre>\n<p><strong>Note<\/strong> As shown previously, WebApplication automatically adds this middleware to your middleware pipeline when you\u2019re running in the Development environment, so you don\u2019t need to add it explicitly. You\u2019ll learn more about environments in chapter 10.<br \/>\n<strong>\u6ce8\u610f<\/strong> \u5982\u524d\u6240\u8ff0\uff0c\u5f53\u60a8\u5728 Development \u73af\u5883\u4e2d\u8fd0\u884c\u65f6\uff0cWebApplication \u4f1a\u81ea\u52a8\u5c06\u6b64\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u60a8\u7684\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4e2d\uff0c\u56e0\u6b64\u60a8\u65e0\u9700\u663e\u5f0f\u6dfb\u52a0\u5b83\u3002\u60a8\u5c06\u5728\u7b2c 10 \u7ae0\u4e2d\u4e86\u89e3\u6709\u5173\u73af\u5883\u7684\u66f4\u591a\u4fe1\u606f\u3002<\/p>\n<p>When an exception is thrown and propagates up the pipeline to this middleware, it\u2019s captured. Then the middleware generates a friendly HTML page, which it returns with a 500 status code, as shown in figure 4.15. This page contains a variety of details about the request and the exception, including the exception stack trace; the source code at the line the exception occurred; and details on the request, such as any cookies or headers that were sent.<\/p>\n<p>\u5f53\u5f15\u53d1\u5f02\u5e38\u5e76\u6cbf\u7ba1\u9053\u5411\u4e0a\u4f20\u64ad\u5230\u6b64\u4e2d\u95f4\u4ef6\u65f6\uff0c\u4f1a\u6355\u83b7\u8be5\u5f02\u5e38\u3002\u7136\u540e\uff0c\u4e2d\u95f4\u4ef6\u751f\u6210\u4e00\u4e2a\u53cb\u597d\u7684 HTML \u9875\u9762\uff0c\u8be5\u9875\u9762\u8fd4\u56de\u4e00\u4e2a 500 \u72b6\u6001\u4ee3\u7801\uff0c\u5982\u56fe 4.15 \u6240\u793a\u3002\u6b64\u9875\u9762\u5305\u542b\u6709\u5173\u8bf7\u6c42\u548c\u5f02\u5e38\u7684\u5404\u79cd\u8be6\u7ec6\u4fe1\u606f\uff0c\u5305\u62ec\u5f02\u5e38\u5806\u6808\u8ddf\u8e2a;\u53d1\u751f\u5f02\u5e38\u7684\u884c\u5904\u7684\u6e90\u4ee3\u7801;\u4ee5\u53ca\u6709\u5173\u8bf7\u6c42\u7684\u8be6\u7ec6\u4fe1\u606f\uff0c\u4f8b\u5982\u53d1\u9001\u7684\u4efb\u4f55 Cookie \u6216\u6807\u5934\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0415.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.15 The developer exception page shows details about the exception when it occurs during the process of a request. The location in the code that caused the exception, the source code line itself, and the stack trace are all shown by default. You can also click the Query, Cookies, Headers, and Routing buttons to reveal further details about the request that caused the exception.<br \/>\n\u56fe 4.15 \u5f00\u53d1\u8005\u5f02\u5e38\u9875\u9762\u5c55\u793a\u8bf7\u6c42\u8fc7\u7a0b\u4e2d\u53d1\u751f\u7684\u5f02\u5e38\u8be6\u60c5\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5c06\u663e\u793a\u4ee3\u7801\u4e2d\u5bfc\u81f4\u5f02\u5e38\u7684\u4f4d\u7f6e\u3001\u6e90\u4ee3\u7801\u884c\u672c\u8eab\u548c\u5806\u6808\u8ddf\u8e2a\u3002\u60a8\u8fd8\u53ef\u4ee5\u5355\u51fb Query\u3001Cookie\u3001Headers \u548c Routing \u6309\u94ae\uff0c\u4ee5\u663e\u793a\u6709\u5173\u5bfc\u81f4\u5f02\u5e38\u7684\u8bf7\u6c42\u7684\u66f4\u591a\u8be6\u7ec6\u4fe1\u606f\u3002<\/p>\n<p>Having these details available when an error occurs is invaluable for debugging a problem, but they also represent a security risk if used incorrectly. You should never return more details about your application to users than absolutely necessary, so you should use DeveloperExceptionPage only when developing your application. The clue is in the name!<\/p>\n<p>\u5728\u53d1\u751f\u9519\u8bef\u65f6\u63d0\u4f9b\u8fd9\u4e9b\u8be6\u7ec6\u4fe1\u606f\u5bf9\u4e8e\u8c03\u8bd5\u95ee\u9898\u975e\u5e38\u6709\u4ef7\u503c\uff0c\u4f46\u5982\u679c\u4f7f\u7528\u4e0d\u5f53\uff0c\u5b83\u4eec\u4e5f\u4f1a\u5e26\u6765\u5b89\u5168\u98ce\u9669\u3002\u60a8\u7edd\u4e0d\u5e94\u5411\u7528\u6237\u8fd4\u56de\u6709\u5173\u5e94\u7528\u7a0b\u5e8f\u7684\u66f4\u591a\u8be6\u7ec6\u4fe1\u606f\uff0c\u56e0\u6b64\u60a8\u53ea\u5e94\u5728\u5f00\u53d1\u5e94\u7528\u7a0b\u5e8f\u65f6\u4f7f\u7528 DeveloperExceptionPage\u3002\u7ebf\u7d22\u5c31\u5728\u540d\u5b57\u91cc\uff01<\/p>\n<p><strong>Warning<\/strong> Never use the developer exception page when running in production. Doing so is a security risk, as it could publicly reveal details about your application\u2019s code, making you an easy target for attackers. WebApplication uses the correct behavior by default and adds the middleware only when running in development.<br \/>\n<strong>\u8b66\u544a<\/strong> \u5728\u751f\u4ea7\u73af\u5883\u4e2d\u8fd0\u884c\u65f6\uff0c\u5207\u52ff\u4f7f\u7528\u5f00\u53d1\u4eba\u5458\u5f02\u5e38\u9875\u9762\u3002\u8fd9\u6837\u505a\u4f1a\u5e26\u6765\u5b89\u5168\u98ce\u9669\uff0c\u56e0\u4e3a\u5b83\u53ef\u80fd\u4f1a\u516c\u5f00\u6cc4\u9732\u6709\u5173\u5e94\u7528\u7a0b\u5e8f\u4ee3\u7801\u7684\u8be6\u7ec6\u4fe1\u606f\uff0c\u4f7f\u60a8\u5f88\u5bb9\u6613\u6210\u4e3a\u653b\u51fb\u8005\u7684\u76ee\u6807\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cWebApplication \u4f7f\u7528\u6b63\u786e\u7684\u884c\u4e3a\uff0c\u5e76\u4e14\u4ec5\u5728\u5f00\u53d1\u4e2d\u8fd0\u884c\u65f6\u6dfb\u52a0\u4e2d\u95f4\u4ef6\u3002<\/p>\n<p>If the developer exception page isn\u2019t appropriate for production use, what should you use instead? Luckily, you can use another type of general-purpose error-handling middleware in production: ExceptionHandlerMiddleware.<\/p>\n<p>\u5982\u679c\u5f00\u53d1\u4eba\u5458\u4f8b\u5916\u9875\u9762\u4e0d\u9002\u5408\u751f\u4ea7\u4f7f\u7528\uff0c\u60a8\u5e94\u8be5\u4f7f\u7528\u4ec0\u4e48\uff1f\u5e78\u8fd0\u7684\u662f\uff0c\u60a8\u53ef\u4ee5\u5728\u751f\u4ea7\u4e2d\u4f7f\u7528\u53e6\u4e00\u79cd\u7c7b\u578b\u7684\u901a\u7528\u9519\u8bef\u5904\u7406\u4e2d\u95f4\u4ef6\uff1aExceptionHandlerMiddleware\u3002<\/p>\n<h4>4.3.2 Handling exceptions in production: ExceptionHandlerMiddleware<\/h4>\n<h4>4.3.2 \u5728\u751f\u4ea7\u73af\u5883\u4e2d\u5904\u7406\u5f02\u5e38\uff1aExceptionHandlerMiddleware<\/h4>\n<p>The developer exception page is handy when you\u2019re developing your applications, but you shouldn\u2019t use it in production, as it can leak information about your app to potential attackers. You still want to catch errors, though; otherwise, users will see unfriendly error pages or blank pages, depending on the browser they\u2019re using.<br \/>\n\u5728\u5f00\u53d1\u5e94\u7528\u7a0b\u5e8f\u65f6\uff0c\u5f00\u53d1\u4eba\u5458\u5f02\u5e38\u9875\u9762\u5f88\u65b9\u4fbf\uff0c\u4f46\u4e0d\u5e94\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u4f7f\u7528\u5b83\uff0c\u56e0\u4e3a\u5b83\u53ef\u80fd\u4f1a\u5c06\u6709\u5173\u5e94\u7528\u7a0b\u5e8f\u7684\u4fe1\u606f\u6cc4\u9732\u7ed9\u6f5c\u5728\u7684\u653b\u51fb\u8005\u3002\u4e0d\u8fc7\uff0c\u60a8\u4ecd\u7136\u5e0c\u671b\u6355\u83b7\u9519\u8bef;\u5426\u5219\uff0c\u7528\u6237\u5c06\u770b\u5230\u4e0d\u53cb\u597d\u7684\u9519\u8bef\u9875\u9762\u6216\u7a7a\u767d\u9875\u9762\uff0c\u5177\u4f53\u53d6\u51b3\u4e8e\u4ed6\u4eec\u4f7f\u7528\u7684\u6d4f\u89c8\u5668\u3002<\/p>\n<p>You can solve this problem by using ExceptionHandlerMiddleware. If an error occurs in your application, the user will see a custom error response that\u2019s consistent with the rest of the application but provides only necessary details about the error. For a minimal API application, that response could be JSON or plain text, as shown in figure 4.16.<\/p>\n<p>\u60a8\u53ef\u4ee5\u4f7f\u7528 ExceptionHandlerMiddleware \u6765\u89e3\u51b3\u6b64\u95ee\u9898\u3002\u5982\u679c\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u4e2d\u53d1\u751f\u9519\u8bef\uff0c\u7528\u6237\u5c06\u770b\u5230\u4e00\u4e2a\u81ea\u5b9a\u4e49\u9519\u8bef\u54cd\u5e94\uff0c\u8be5\u54cd\u5e94\u4e0e\u5e94\u7528\u7a0b\u5e8f\u7684\u5176\u4f59\u90e8\u5206\u4e00\u81f4\uff0c\u4f46\u4ec5\u63d0\u4f9b\u6709\u5173\u9519\u8bef\u7684\u5fc5\u8981\u8be6\u7ec6\u4fe1\u606f\u3002\u5bf9\u4e8e\u6700\u5c0f\u7684 API \u5e94\u7528\u7a0b\u5e8f\uff0c\u8be5\u54cd\u5e94\u53ef\u4ee5\u662f JSON \u6216\u7eaf\u6587\u672c\uff0c\u5982\u56fe 4.16 \u6240\u793a\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0416.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.16 Using the ExceptionHandlerMiddleware, you can return a generic error message when an exception occurs, ensuring that you don\u2019t leak any sensitive details about your application in production.<br \/>\n\u56fe 4.16 \u4f7f\u7528 ExceptionHandlerMiddleware\uff0c\u60a8\u53ef\u4ee5\u5728\u53d1\u751f\u5f02\u5e38\u65f6\u8fd4\u56de\u901a\u7528\u9519\u8bef\u6d88\u606f\uff0c\u4ece\u800c\u786e\u4fdd\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u4e0d\u4f1a\u6cc4\u9732\u6709\u5173\u5e94\u7528\u7a0b\u5e8f\u7684\u4efb\u4f55\u654f\u611f\u8be6\u7ec6\u4fe1\u606f\u3002<\/p>\n<p>For Razor Pages apps, you can create a custom error response, such as the one shown in figure 4.17. You maintain the look and feel of the application by using the same header, displaying the currently logged-in user, and displaying an appropriate message to the user instead of full details on the exception.<\/p>\n<p>\u5bf9\u4e8e Razor Pages \u5e94\u7528\u7a0b\u5e8f\uff0c\u60a8\u53ef\u4ee5\u521b\u5efa\u81ea\u5b9a\u4e49\u9519\u8bef\u54cd\u5e94\uff0c\u5982\u56fe 4.17 \u6240\u793a\u3002\u901a\u8fc7\u4f7f\u7528\u76f8\u540c\u7684\u6807\u5934\uff0c\u663e\u793a\u5f53\u524d\u767b\u5f55\u7684\u7528\u6237\uff0c\u5e76\u5411\u7528\u6237\u663e\u793a\u9002\u5f53\u7684\u6d88\u606f\uff0c\u800c\u4e0d\u662f\u6709\u5173\u5f02\u5e38\u7684\u5b8c\u6574\u8be6\u7ec6\u4fe1\u606f\uff0c\u53ef\u4ee5\u7ef4\u62a4\u5e94\u7528\u7a0b\u5e8f\u7684\u5916\u89c2\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0417.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.17 A custom error page created by ExceptionHandlerMiddleware. The custom error page can have the same look and feel as the rest of the application by reusing elements such as the header and footer. More important, you can easily control the error details displayed to users.<br \/>\n\u56fe 4.17 \u7531 ExceptionHandlerMiddleware \u521b\u5efa\u7684\u81ea\u5b9a\u4e49\u9519\u8bef\u9875\u9762\u3002\u901a\u8fc7\u91cd\u7528 header \u548c footer \u7b49\u5143\u7d20\uff0c\u81ea\u5b9a\u4e49\u9519\u8bef\u9875\u9762\u53ef\u4ee5\u5177\u6709\u4e0e\u5e94\u7528\u7a0b\u5e8f\u5176\u4f59\u90e8\u5206\u76f8\u540c\u7684\u5916\u89c2\u3002\u66f4\u91cd\u8981\u7684\u662f\uff0c\u60a8\u53ef\u4ee5\u8f7b\u677e\u63a7\u5236\u5411\u7528\u6237\u663e\u793a\u7684\u9519\u8bef\u8be6\u7ec6\u4fe1\u606f\u3002<\/p>\n<p>Given the differing requirements for error handlers in development and production, most ASP.NET Core apps add their error-handler middleware conditionally, based on the hosting environment. WebApplication automatically adds the developer exception page when running in the development hosting environment, so you typically add ExceptionHandlerMiddleware when you\u2019re not in the development environment, as shown in the following listing.<\/p>\n<p>\u9274\u4e8e\u5f00\u53d1\u548c\u751f\u4ea7\u4e2d\u5bf9\u9519\u8bef\u5904\u7406\u7a0b\u5e8f\u7684\u8981\u6c42\u4e0d\u540c\uff0c\u5927\u591a\u6570 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u90fd\u4f1a\u6dfb\u52a0\u4ed6\u4eec\u7684 error-handler \u4e2d\u95f4\u4ef6\u3002WebApplication \u5728\u5f00\u53d1\u6258\u7ba1\u73af\u5883\u4e2d\u8fd0\u884c\u65f6\u4f1a\u81ea\u52a8\u6dfb\u52a0\u5f00\u53d1\u4eba\u5458\u5f02\u5e38\u9875\u9762\uff0c\u56e0\u6b64\u60a8\u901a\u5e38\u5728\u4e0d\u5728\u5f00\u53d1\u73af\u5883\u4e2d\u65f6\u6dfb\u52a0 ExceptionHandlerMiddleware\uff0c\u5982\u4e0b\u9762\u7684\u6e05\u5355\u6240\u793a\u3002<\/p>\n<p>Listing 4.5 Adding exception-handler middleware when in production<br \/>\n\u5217\u8868 4.5 \u6dfb\u52a0\u5f02\u5e38\u5904\u7406\u7a0b\u5e8f\u4e2d\u95f4\u4ef6\u5728\u751f\u4ea7\u73af\u5883\u4e2d<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nWebApplicationBuilder builder = WebApplication.CreateBuilder(args);\nWebApplication app = builder.Build();                     \/\/ \u2776\nif (!app.Environment.IsDevelopment())                     \/\/ \u2777\n{\n    app.UseExceptionHandler(&quot;\/error&quot;);                    \/\/ \u2778\n}\n\/\/ additional middleware configuration\napp.MapGet(&quot;\/error&quot;, () =&gt; &quot;Sorry, an error occurred&quot;);   \/\/ \u2779\n<\/pre>\n<p>\u2776 In development, WebApplication automatically adds the developer exception page middleware.<br \/>\n\u5728\u5f00\u53d1\u4e2d\uff0cWebApplication \u4f1a\u81ea\u52a8\u6dfb\u52a0\u5f00\u53d1\u8005\u5f02\u5e38\u9875\u9762\u4e2d\u95f4\u4ef6\u3002<br \/>\n\u2777 Configures a different pipeline when not running in development<br \/>\n\u5728\u5f00\u53d1\u4e2d\u672a\u8fd0\u884c\u65f6\u914d\u7f6e\u4e0d\u540c\u7684\u7ba1\u9053<br \/>\n\u2778 The ExceptionHandlerMiddleware won\u2019t leak sensitive details when running in production.<br \/>\nExceptionHandlerMiddleware \u5728\u751f\u4ea7\u73af\u5883\u4e2d\u8fd0\u884c\u65f6\u4e0d\u4f1a\u6cc4\u9732\u654f\u611f\u7ec6\u8282\u3002<br \/>\n\u2779 This error endpoint will be executed when an exception is handled.<br \/>\n\u5904\u7406\u5f02\u5e38\u65f6\u5c06\u6267\u884c\u6b64\u9519\u8bef\u7aef\u70b9\u3002<\/p>\n<p>As well as demonstrating how to add ExceptionHandlerMiddleware to your middleware pipeline, this listing shows that it\u2019s perfectly acceptable to configure different middleware pipelines depending on the environment when the application starts. You could also vary your pipeline based on other values, such as settings loaded from configuration.<\/p>\n<p>\u9664\u4e86\u6f14\u793a\u5982\u4f55\u5c06 ExceptionHandlerMiddleware \u6dfb\u52a0\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4e4b\u5916\uff0c\u6b64\u6e05\u5355\u8fd8\u8868\u660e\uff0c\u5728\u5e94\u7528\u7a0b\u5e8f\u542f\u52a8\u65f6\uff0c\u6839\u636e\u73af\u5883\u914d\u7f6e\u4e0d\u540c\u7684\u4e2d\u95f4\u4ef6\u7ba1\u9053\u662f\u5b8c\u5168\u53ef\u4ee5\u63a5\u53d7\u7684\u3002\u60a8\u8fd8\u53ef\u4ee5\u6839\u636e\u5176\u4ed6\u503c\uff08\u4f8b\u5982\u4ece\u914d\u7f6e\u52a0\u8f7d\u7684\u8bbe\u7f6e\uff09\u6765\u6539\u53d8\u7ba1\u9053\u3002<\/p>\n<p><strong>Note<\/strong> You\u2019ll see how to use configuration values to customize the middleware pipeline in chapter 10.<br \/>\n<strong>\u6ce8\u610f<\/strong> \u60a8\u5c06\u5728\u7b2c 10 \u7ae0\u4e2d\u770b\u5230\u5982\u4f55\u4f7f\u7528\u914d\u7f6e\u503c\u6765\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002<\/p>\n<p>When adding ExceptionHandlerMiddleware to your application, you typically provide a path to the custom error page that will be displayed to the user. In the example in listing 4.5, you used an error handling path of &quot;\/error&quot;:<br \/>\n\u5728\u5c06 ExceptionHandlerMiddleware \u6dfb\u52a0\u5230\u5e94\u7528\u7a0b\u5e8f\u65f6\uff0c\u901a\u5e38\u4f1a\u63d0\u4f9b\u5c06\u5411\u7528\u6237\u663e\u793a\u7684\u81ea\u5b9a\u4e49\u9519\u8bef\u9875\u9762\u7684\u8def\u5f84\u3002\u5728\u6e05\u5355 4.5 \u7684\u793a\u4f8b\u4e2d\uff0c\u60a8\u4f7f\u7528\u4e86 \u201c\/error\u201d \u7684\u9519\u8bef\u5904\u7406\u8def\u5f84\uff1a<\/p>\n<pre><code>app.UseExceptionHandler(&quot;\/error&quot;);<\/code><\/pre>\n<p>ExceptionHandlerMiddleware invokes this path after it captures an exception to generate the final response. The ability to generate a response dynamically is a key feature of ExceptionHandlerMiddleware; it allows you to reexecute a middleware pipeline to generate the response sent to the user.<\/p>\n<p>ExceptionHandlerMiddleware \u5728\u6355\u83b7\u5f02\u5e38\u540e\u8c03\u7528\u6b64\u8def\u5f84\u4ee5\u751f\u6210\u6700\u7ec8\u54cd\u5e94\u3002\u52a8\u6001\u751f\u6210\u54cd\u5e94\u7684\u80fd\u529b\u662f ExceptionHandlerMiddleware \u7684\u4e00\u4e2a\u5173\u952e\u529f\u80fd;\u5b83\u5141\u8bb8\u60a8\u91cd\u65b0\u6267\u884c\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4ee5\u751f\u6210\u53d1\u9001\u7ed9\u7528\u6237\u7684\u54cd\u5e94\u3002<\/p>\n<p>Figure 4.18 shows what happens when ExceptionHandlerMiddleware handles an exception. It shows the flow of events when the minimal API endpoint for the &quot;\/&quot; path generates an exception. The final response returns an error status code but also provides an error string, using the &quot;\/error&quot; endpoint.<br \/>\n\u56fe 4.18 \u663e\u793a\u4e86\u5f53 ExceptionHandlerMiddleware \u5904\u7406\u5f02\u5e38\u65f6\u4f1a\u53d1\u751f\u4ec0\u4e48\u3002\u5b83\u663e\u793a\u5f53 \u201c\/\u201d \u8def\u5f84\u7684\u6700\u5c0f API \u7aef\u70b9\u751f\u6210\u5f02\u5e38\u65f6\u7684\u4e8b\u4ef6\u6d41\u3002\u6700\u7ec8\u54cd\u5e94\u8fd4\u56de\u9519\u8bef\u72b6\u6001\u4ee3\u7801\uff0c\u4f46\u4e5f\u4f7f\u7528\u201c\/error\u201d\u7aef\u70b9\u63d0\u4f9b\u9519\u8bef\u5b57\u7b26\u4e32\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/0418.png\" alt=\"alt text\" \/><\/p>\n<p>Figure 4.18 ExceptionHandlerMiddleware handling an exception to generate a JSON response. A request to the \/ path generates an exception, which is handled by the middleware. The pipeline is reexecuted, using the \/error path to generate the JSON response.<br \/>\n\u56fe 4.18 ExceptionHandlerMiddleware \u5904\u7406\u5f02\u5e38\u4ee5\u751f\u6210 JSON \u54cd\u5e94\u3002\u5bf9 \/ \u8def\u5f84\u7684\u8bf7\u6c42\u4f1a\u751f\u6210\u5f02\u5e38\uff0c\u8be5\u5f02\u5e38\u7531\u4e2d\u95f4\u4ef6\u5904\u7406\u3002\u7ba1\u9053\u5c06\u91cd\u65b0\u6267\u884c\uff0c\u4f7f\u7528 \/error \u8def\u5f84\u751f\u6210 JSON \u54cd\u5e94\u3002<\/p>\n<p>The sequence of events when an unhandled exception occurs somewhere in the middleware pipeline (or in an endpoint) after ExceptionHandlerMiddleware is as follows:<\/p>\n<p>\u5f53 ExceptionHandlerMiddleware \u4e4b\u540e\u7684\u4e2d\u95f4\u4ef6\u7ba1\u9053\uff08\u6216\u7aef\u70b9\uff09\u4e2d\u7684\u67d0\u4e2a\u4f4d\u7f6e\u53d1\u751f\u672a\u7ecf\u5904\u7406\u7684\u5f02\u5e38\u65f6\uff0c\u4e8b\u4ef6\u5e8f\u5217\u5982\u4e0b\uff1a<\/p>\n<ol>\n<li>\n<p>A piece of middleware throws an exception.<br \/>\n\u4e00\u4e2a middleware \u4f1a\u5f15\u53d1\u4e00\u4e2a\u5f02\u5e38\u3002<\/p>\n<\/li>\n<li>\n<p>ExceptionHandlerMiddleware catches the exception.<br \/>\nExceptionHandlerMiddleware \u6355\u83b7\u5f02\u5e38\u3002<\/p>\n<\/li>\n<li>\n<p>Any partial response that has been defined is cleared.<br \/>\n\u5c06\u6e05\u9664\u5df2\u5b9a\u4e49\u7684\u4efb\u4f55\u90e8\u5206\u54cd\u5e94\u3002<\/p>\n<\/li>\n<li>\n<p>The ExceptionHandlerMiddleware overwrites the request path with the provided error-handling path.<br \/>\nExceptionHandlerMiddleware \u4f7f\u7528\u63d0\u4f9b\u7684\u9519\u8bef\u5904\u7406\u8def\u5f84\u8986\u76d6\u8bf7\u6c42\u8def\u5f84\u3002<\/p>\n<\/li>\n<li>\n<p>The middleware sends the request back down the pipeline, as though the original request had been for the error-handling path.<br \/>\n\u4e2d\u95f4\u4ef6\u5c06\u8bf7\u6c42\u53d1\u9001\u56de\u7ba1\u9053\uff0c\u5c31\u50cf\u539f\u59cb\u8bf7\u6c42\u662f\u9488\u5bf9\u9519\u8bef\u5904\u7406\u8def\u5f84\u7684\u4e00\u6837\u3002<\/p>\n<\/li>\n<li>\n<p>The middleware pipeline generates a new response as normal.<br \/>\n\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7167\u5e38\u751f\u6210\u65b0\u7684\u54cd\u5e94\u3002<\/p>\n<\/li>\n<li>\n<p>When the response gets back to ExceptionHandlerMiddleware, it modifies the status code to a 500 error and continues to pass the response up the pipeline to the web server.<br \/>\n\u5f53\u54cd\u5e94\u8fd4\u56de\u5230 ExceptionHandlerMiddleware \u65f6\uff0c\u5b83\u4f1a\u5c06\u72b6\u6001\u4ee3\u7801\u4fee\u6539\u4e3a 500 \u9519\u8bef\uff0c\u5e76\u7ee7\u7eed\u5c06\u54cd\u5e94\u4ece\u7ba1\u9053\u5411\u4e0a\u4f20\u9012\u5230 Web \u670d\u52a1\u5668\u3002<\/p>\n<\/li>\n<\/ol>\n<p>One of the main advantages of reexecuting the pipeline for Razor Page apps is the ability to have your error messages integrated into your normal site layout, as shown in figure 4.17. It\u2019s certainly possible to return a fixed response when an error occurs without reexecuting the pipeline, but you wouldn\u2019t be able to have a menu bar with dynamically generated links or display the current user\u2019s name in the menu, for example. By reexecuting the pipeline, you ensure that all the dynamic areas of your application are integrated correctly, as though the page were a standard page of your site.<\/p>\n<p>\u91cd\u65b0\u6267\u884c Razor Page \u5e94\u7528\u7a0b\u5e8f\u7684\u7ba1\u9053\u7684\u4e3b\u8981\u4f18\u70b9\u4e4b\u4e00\u662f\u80fd\u591f\u5c06\u9519\u8bef\u6d88\u606f\u96c6\u6210\u5230\u6b63\u5e38\u7684\u7ad9\u70b9\u5e03\u5c40\u4e2d\uff0c\u5982\u56fe\u6240\u793a4.17. \u5f53\u9519\u8bef\u53d1\u751f\u65f6\uff0c\u5f53\u7136\u53ef\u4ee5\u5728\u4e0d\u91cd\u65b0\u6267\u884c\u7ba1\u9053\u7684\u60c5\u51b5\u4e0b\u8fd4\u56de\u56fa\u5b9a\u7684\u54cd\u5e94\uff0c\u4f46\u4f60\u5c06\u65e0\u6cd5\u62e5\u6709\u4e00\u4e2a\u5e26\u6709 dynamic \u7684\u83dc\u5355\u680f\u751f\u6210\u7684\u94fe\u63a5\u6216\u5728\u83dc\u5355\u4e2d\u663e\u793a\u5f53\u524d\u7528\u6237\u7684\u540d\u79f0\u3002\u901a\u8fc7\u91cd\u65b0\u6267\u884c\u7ba1\u9053\uff0c\u60a8\u53ef\u4ee5\u786e\u4fdd\u5e94\u7528\u7a0b\u5e8f\u7684\u6240\u6709\u52a8\u6001\u533a\u57df\u90fd\u5df2\u6b63\u786e\u96c6\u6210\uff0c\u5c31\u50cf\u8be5\u9875\u9762\u662f\u7f51\u7ad9\u7684\u6807\u51c6\u9875\u9762\u4e00\u6837\u3002<\/p>\n<p><strong>Note<\/strong> You don\u2019t need to do anything other than add ExceptionHandlerMiddleware to your application and configure a valid error-handling path to enable reexecuting the pipeline, as shown in figure 4.18. The middleware will catch the exception and reexecute the pipeline for you. Subsequent middleware will treat the reexecution as a new request, but previous middleware in the pipeline won\u2019t be aware that anything unusual happened.<br \/>\n<strong>\u6ce8\u610f<\/strong> \u9664\u4e86\u5c06 ExceptionHandlerMiddleware \u6dfb\u52a0\u5230\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u5e76\u914d\u7f6e\u6709\u6548\u7684\u9519\u8bef\u5904\u7406\u8def\u5f84\u4ee5\u542f\u7528\u91cd\u65b0\u6267\u884c\u7ba1\u9053\u4e4b\u5916\uff0c\u60a8\u4e0d\u9700\u8981\u6267\u884c\u4efb\u4f55\u5176\u4ed6\u4f5c\uff0c\u5982\u56fe 4.18 \u6240\u793a\u3002\u4e2d\u95f4\u4ef6\u5c06\u6355\u83b7\u5f02\u5e38\u5e76\u4e3a\u60a8\u91cd\u65b0\u6267\u884c\u7ba1\u9053\u3002\u540e\u7eed\u4e2d\u95f4\u4ef6\u4f1a\u5c06\u91cd\u65b0\u6267\u884c\u89c6\u4e3a\u65b0\u8bf7\u6c42\uff0c\u4f46\u7ba1\u9053\u4e2d\u5148\u524d\u7684\u4e2d\u95f4\u4ef6\u4e0d\u4f1a\u610f\u8bc6\u5230\u53d1\u751f\u4e86\u4efb\u4f55\u5f02\u5e38\u60c5\u51b5\u3002<\/p>\n<p>Reexecuting the middleware pipeline is a great way to keep consistency in your web application for error pages, but you should be aware of some gotchas. First, middleware can modify a response generated farther down the pipeline only if the response hasn\u2019t yet been sent to the client. This situation can be a problem if, for example, an error occurs while ASP.NET Core is sending a static file to a client. In that case, ASP.NET Core may start streaming bytes to the client immediately for performance reasons. In that case, the error-handling middleware won\u2019t be able to run, as it can\u2019t reset the response. Generally speaking, you can\u2019t do much about this problem, but it\u2019s something to be aware of.<\/p>\n<p>\u91cd\u65b0\u6267\u884c\u4e2d\u95f4\u4ef6\u7ba1\u9053\u662f\u4fdd\u6301 Web \u5e94\u7528\u7a0b\u5e8f\u9519\u8bef\u9875\u9762\u4e00\u81f4\u6027\u7684\u597d\u65b9\u6cd5\uff0c\u4f46\u60a8\u5e94\u8be5\u6ce8\u610f\u4e00\u4e9b\u95ee\u9898\u3002\u9996\u5148\uff0c\u4ec5\u5f53\u54cd\u5e94\u5c1a\u672a\u53d1\u9001\u5230\u5ba2\u6237\u7aef\u65f6\uff0c\u4e2d\u95f4\u4ef6\u624d\u80fd\u4fee\u6539\u5728\u7ba1\u9053\u4e2d\u8f83\u8fdc\u5904\u751f\u6210\u7684\u54cd\u5e94\u3002\u4f8b\u5982\uff0c\u5982\u679c\u5728 ASP.NET Core \u5411\u5ba2\u6237\u7aef\u53d1\u9001\u9759\u6001\u6587\u4ef6\u65f6\u53d1\u751f\u9519\u8bef\uff0c\u5219\u8fd9\u79cd\u60c5\u51b5\u53ef\u80fd\u662f\u4e00\u4e2a\u95ee\u9898\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u51fa\u4e8e\u6027\u80fd\u539f\u56e0\uff0cASP.NET Core \u53ef\u80fd\u4f1a\u7acb\u5373\u5f00\u59cb\u5c06\u5b57\u8282\u6d41\u5f0f\u4f20\u8f93\u5230\u5ba2\u6237\u7aef\u3002\u53d1\u751f\u8fd9\u79cd\u60c5\u51b5\u65f6\uff0c\u9519\u8bef\u5904\u7406\u4e2d\u95f4\u4ef6\u5c06\u65e0\u6cd5\u8fd0\u884c\uff0c\u56e0\u4e3a\u5b83\u65e0\u6cd5\u91cd\u7f6e\u54cd\u5e94\u3002\u4e00\u822c\u6765\u8bf4\uff0c\u60a8\u5bf9\u6b64\u95ee\u9898\u65e0\u80fd\u4e3a\u529b\uff0c\u4f46\u9700\u8981\u6ce8\u610f\u3002<\/p>\n<p>A more common problem occurs when the error-handling path throws an error during the reexecution of the pipeline. Imagine that there\u2019s a bug in the code that generates the menu at the top of the page in a Razor Pages app:<br \/>\n\u5f53\u9519\u8bef\u5904\u7406\u8def\u5f84\u5728\u91cd\u65b0\u6267\u884c\u7ba1\u9053\u671f\u95f4\u5f15\u53d1\u9519\u8bef\u65f6\uff0c\u4f1a\u51fa\u73b0\u66f4\u5e38\u89c1\u7684\u95ee\u9898\u3002\u5047\u8bbe\u5728 Razor Pages \u5e94\u7528\u7a0b\u5e8f\u4e2d\u751f\u6210\u9875\u9762\u9876\u90e8\u83dc\u5355\u7684\u4ee3\u7801\u4e2d\u5b58\u5728\u4e00\u4e2a bug\uff1a<\/p>\n<ol>\n<li>\n<p>When the user reaches your home page, the code for generating the menu bar throws an exception.<br \/>\n\u5f53\u7528\u6237\u8bbf\u95ee\u60a8\u7684\u4e3b\u9875\u65f6\uff0c\u7528\u4e8e\u751f\u6210\u83dc\u5355\u680f\u7684\u4ee3\u7801\u4f1a\u5f15\u53d1\u5f02\u5e38\u3002<\/p>\n<\/li>\n<li>\n<p>The exception propagates up the middleware pipeline.<br \/>\n\u5f02\u5e38\u6cbf\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5411\u4e0a\u4f20\u64ad\u3002<\/p>\n<\/li>\n<li>\n<p>When reached, ExceptionHandlerMiddleware captures it, and the pipe is reexecuted, using the error-handling path.<br \/>\n\u5230\u8fbe\u65f6\uff0cExceptionHandlerMiddleware \u4f1a\u6355\u83b7\u5b83\uff0c\u5e76\u4f7f\u7528\u9519\u8bef\u5904\u7406\u8def\u5f84\u91cd\u65b0\u6267\u884c\u7ba1\u9053\u3002<\/p>\n<\/li>\n<li>\n<p>When the error page executes, it attempts to generate the menu bar for your app, which again throws an exception.<br \/>\n\u5f53\u9519\u8bef\u9875\u9762\u6267\u884c\u65f6\uff0c\u5b83\u4f1a\u5c1d\u8bd5\u4e3a\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u751f\u6210\u83dc\u5355\u680f\uff0c\u8fd9\u518d\u6b21\u5f15\u53d1\u5f02\u5e38\u3002<\/p>\n<\/li>\n<li>\n<p>The exception propagates up the middleware pipeline.<br \/>\n\u5f02\u5e38\u6cbf\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5411\u4e0a\u4f20\u64ad\u3002<\/p>\n<\/li>\n<li>\n<p>ExceptionHandlerMiddleware has already tried to intercept a request, so it lets the error propagate all the way to the top of the middleware pipeline.<br \/>\nExceptionHandlerMiddleware \u5df2\u7ecf\u5c1d\u8bd5\u62e6\u622a\u4e00\u4e2a\u8bf7\u6c42\uff0c\u6240\u4ee5\u5b83\u5141\u8bb8\u9519\u8bef\u4e00\u76f4\u4f20\u64ad\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u9876\u90e8\u3002<\/p>\n<\/li>\n<li>\n<p>The web server returns a raw 500 error, as though there were no error-handling middleware at all.<br \/>\nWeb \u670d\u52a1\u5668\u8fd4\u56de\u539f\u59cb 500 \u9519\u8bef\uff0c\u5c31\u597d\u50cf\u6839\u672c\u6ca1\u6709\u9519\u8bef\u5904\u7406\u4e2d\u95f4\u4ef6\u4e00\u6837\u3002<\/p>\n<\/li>\n<\/ol>\n<p>Thanks to this problem, it\u2019s often good practice to make your error-handling pages as simple as possible to reduce the possibility that errors will occur.<br \/>\n\u7531\u4e8e\u8fd9\u4e2a\u95ee\u9898\uff0c\u901a\u5e38\u6700\u597d\u8ba9\u4f60\u7684\u9519\u8bef\u5904\u7406\u9875\u9762\u5c3d\u53ef\u80fd\u7b80\u5355\uff0c\u4ee5\u51cf\u5c11\u53d1\u751f\u9519\u8bef\u7684\u53ef\u80fd\u6027\u3002<\/p>\n<p><strong>Warning<\/strong> If your error-handling path generates an error, the user will see a generic browser error. It\u2019s often better to use a static error page that always works than a dynamic page that risks throwing more errors. You can see an alternative approach using a custom error handling function in this post: <a href=\"http:\/\/mng.bz\/0Kmx\">http:\/\/mng.bz\/0Kmx<\/a>.<br \/>\n<strong>\u8b66\u544a<\/strong> \u5982\u679c\u9519\u8bef\u5904\u7406\u8def\u5f84\u751f\u6210\u9519\u8bef\uff0c\u5219\u7528\u6237\u5c06\u770b\u5230\u901a\u7528\u6d4f\u89c8\u5668\u9519\u8bef\u3002\u4f7f\u7528\u59cb\u7ec8\u6709\u6548\u7684\u9759\u6001\u9519\u8bef\u9875\u9762\u901a\u5e38\u6bd4\u4f7f\u7528\u52a8\u6001\u9875\u9762\u3002\u60a8\u53ef\u4ee5\u5728\u8fd9\u7bc7\u6587\u7ae0\u4e2d\u770b\u5230\u4f7f\u7528\u81ea\u5b9a\u4e49\u9519\u8bef\u5904\u7406\u51fd\u6570\u7684\u66ff\u4ee3\u65b9\u6cd5\uff1a<a href=\"http:\/\/mng.bz\/0Kmx\">http:\/\/mng.bz\/0Kmx<\/a>\u3002<\/p>\n<p>Another consideration when building minimal API applications is that you generally don\u2019t want to return HTML. Returning an HTML page to an application that\u2019s expecting JSON could easily break it. Instead, the HTTP 500 status code and a JSON body describing the error are more useful to a consuming application. Luckily, ASP.NET Core allows you to do exactly this when you create minimal APIs and web API controllers.<\/p>\n<p>\u6784\u5efa\u6700\u5c0f API \u5e94\u7528\u7a0b\u5e8f\u65f6\u7684\u53e6\u4e00\u4e2a\u6ce8\u610f\u4e8b\u9879\u662f\uff0c\u60a8\u901a\u5e38\u4e0d\u5e0c\u671b\u8fd4\u56de HTML\u3002 \u5c06 HTML \u9875\u9762\u8fd4\u56de\u5230\u9700\u8981 JSON \u7684\u5e94\u7528\u7a0b\u5e8f\u5f88\u5bb9\u6613\u7834\u574f\u5b83\u3002\u76f8\u53cd\uff0cHTTP 500 \u72b6\u6001\u4ee3\u7801\u548c\u63cf\u8ff0\u9519\u8bef\u7684 JSON \u6b63\u6587\u5bf9\u4e8e\u4f7f\u7528\u5e94\u7528\u7a0b\u5e8f\u66f4\u6709\u7528\u3002\u5e78\u8fd0\u7684\u662f\uff0cASP.NET Core \u5141\u8bb8\u60a8\u5728\u521b\u5efa\u6700\u5c0f API \u548c Web API \u63a7\u5236\u5668\u65f6\u6267\u884c\u6b64\u4f5c\u3002<\/p>\n<p><strong>Note<\/strong> I discuss how to add this functionality with minimal APIs in chapter 5 and with web APIs in chapter 20.<br \/>\n<strong>\u6ce8\u610f\uff1a<\/strong>\u6211\u5728\u7b2c 5 \u7ae0\u4e2d\u8ba8\u8bba\u4e86\u5982\u4f55\u4f7f\u7528\u6700\u5c11\u7684 API \u6dfb\u52a0\u6b64\u529f\u80fd\uff0c\u5728\u7b2c 20 \u7ae0\u4e2d\u8ba8\u8bba\u4e86\u5982\u4f55\u4f7f\u7528 Web API \u6dfb\u52a0\u6b64\u529f\u80fd\u3002<\/p>\n<p>That brings us to the end of middleware in ASP.NET Core for now. You\u2019ve seen how to use and compose middleware to form a pipeline, as well as how to handle exceptions in your application. This information will get you a long way when you start building your first ASP.NET Core applications. Later, you\u2019ll learn how to build your own custom middleware, as well as how to perform complex operations on the middleware pipeline, such as forking it in response to specific requests. In chapter 5, you\u2019ll look in depth at minimal APIs and at how they can be used to build JSON APIs.<\/p>\n<p>\u73b0\u5728\uff0c\u6211\u4eec\u6765\u5230\u4e86 ASP.NET Core \u4e2d\u4e2d\u95f4\u4ef6\u7684\u7ed3\u5c3e\u3002\u60a8\u5df2\u7ecf\u4e86\u89e3\u4e86\u5982\u4f55\u4f7f\u7528\u548c\u7ec4\u5408\u4e2d\u95f4\u4ef6\u6765\u5f62\u6210\u7ba1\u9053\uff0c\u4ee5\u53ca\u5982\u4f55\u5904\u7406\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u5f02\u5e38\u3002\u5f53\u60a8\u5f00\u59cb\u6784\u5efa\u60a8\u7684\u7b2c\u4e00\u4e2a ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u65f6\uff0c\u6b64\u4fe1\u606f\u5c06\u5bf9\u60a8\u6709\u6240\u5e2e\u52a9\u3002\u7a0d\u540e\uff0c\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u6784\u5efa\u81ea\u5df1\u7684\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6\uff0c\u4ee5\u53ca\u5982\u4f55\u5728\u4e2d\u95f4\u4ef6\u7ba1\u9053\u4e0a\u6267\u884c\u590d\u6742\u7684\u4f5c\uff0c\u4f8b\u5982\u4e3a\u54cd\u5e94\u7279\u5b9a\u8bf7\u6c42\u800c\u5206\u53c9\u3002\u5728\u7b2c 5 \u7ae0\u4e2d\uff0c\u60a8\u5c06\u6df1\u5165\u4e86\u89e3\u6700\u5c0f\u7684 API \u4ee5\u53ca\u5982\u4f55\u4f7f\u7528\u5b83\u4eec\u6765\u6784\u5efa JSON API\u3002<\/p>\n<h3>4.4 Summary<\/h3>\n<h3>4.4 \u603b\u7ed3<\/h3>\n<ul>\n<li>Middleware has a similar role to HTTP modules and handlers in ASP.NET but is easier to reason about.<br \/>\n\u4e2d\u95f4\u4ef6\u7684\u4f5c\u7528\u4e0e ASP.NET \u4e2d\u7684 HTTP \u6a21\u5757\u548c\u5904\u7406\u7a0b\u5e8f\u7c7b\u4f3c\uff0c\u4f46\u66f4\u5bb9\u6613\u63a8\u7406\u3002<\/li>\n<li>Middleware is composed in a pipeline, with the output of one middleware passing to the input of the next.<br \/>\n\u4e2d\u95f4\u4ef6\u7531\u7ba1\u9053\u7ec4\u6210\uff0c\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u7684\u8f93\u51fa\u4f20\u9012\u5230\u4e0b\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u7684\u8f93\u5165\u3002<\/li>\n<li>The middleware pipeline is two-way: requests pass through each middleware on the way in, and responses pass back through in reverse order on the way out.<br \/>\n\u4e2d\u95f4\u4ef6\u7ba1\u9053\u662f\u53cc\u5411\u7684\uff1a\u8bf7\u6c42\u5728\u4f20\u5165\u65f6\u901a\u8fc7\u6bcf\u4e2a\u4e2d\u95f4\u4ef6\uff0c\u54cd\u5e94\u5728\u4f20\u51fa\u65f6\u4ee5\u76f8\u53cd\u7684\u987a\u5e8f\u4f20\u56de\u3002<\/li>\n<li>Middleware can short-circuit the pipeline by handling a request and returning a response, or it can pass the request on to the next middleware in the pipeline.<br \/>\n\u4e2d\u95f4\u4ef6\u53ef\u4ee5\u901a\u8fc7\u5904\u7406\u8bf7\u6c42\u5e76\u8fd4\u56de\u54cd\u5e94\u6765\u4f7f\u7ba1\u9053\u77ed\u8def\uff0c\u4e5f\u53ef\u4ee5\u5c06\u8bf7\u6c42\u4f20\u9012\u7ed9\u7ba1\u9053\u4e2d\u7684\u4e0b\u4e00\u4e2a\u4e2d\u95f4\u4ef6\u3002<\/li>\n<li>Middleware can modify a request by adding data to or changing the HttpContext object.<br \/>\n\u4e2d\u95f4\u4ef6\u53ef\u4ee5\u901a\u8fc7\u5411 HttpContext \u5bf9\u8c61\u6dfb\u52a0\u6570\u636e\u6216\u66f4\u6539 HttpContext \u5bf9\u8c61\u6765\u4fee\u6539\u8bf7\u6c42\u3002<\/li>\n<li>If an earlier middleware short-circuits the pipeline, not all middleware will execute for all requests.<br \/>\n\u5982\u679c\u8f83\u65e9\u7684\u4e2d\u95f4\u4ef6\u4f7f\u7ba1\u9053\u77ed\u8def\uff0c\u5219\u5e76\u975e\u6240\u6709\u4e2d\u95f4\u4ef6\u90fd\u4f1a\u9488\u5bf9\u6240\u6709\u8bf7\u6c42\u6267\u884c\u3002<\/li>\n<li>If a request isn\u2019t handled, the middleware pipeline returns a 404 status code.<br \/>\n\u5982\u679c\u672a\u5904\u7406\u8bf7\u6c42\uff0c\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5c06\u8fd4\u56de 404 \u72b6\u6001\u4ee3\u7801\u3002<\/li>\n<li>The order in which middleware is added to WebApplication defines the order in which middleware will execute in the pipeline.<br \/>\n\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230 WebApplication \u7684\u987a\u5e8f\u5b9a\u4e49\u4e86\u4e2d\u95f4\u4ef6\u5728\u7ba1\u9053\u4e2d\u7684\u6267\u884c\u987a\u5e8f\u3002<\/li>\n<li>The middleware pipeline can be reexecuted as long as a response\u2019s headers haven\u2019t been sent.<br \/>\n\u53ea\u8981\u5c1a\u672a\u53d1\u9001\u54cd\u5e94\u7684\u6807\u5934\uff0c\u5c31\u53ef\u4ee5\u91cd\u65b0\u6267\u884c\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002<\/li>\n<li>When it\u2019s added to a middleware pipeline, StaticFileMiddleware serves any requested files found in the wwwroot folder of your application.<br \/>\n\u5f53\u5b83\u88ab\u6dfb\u52a0\u5230\u4e2d\u95f4\u4ef6\u7ba1\u9053\u65f6\uff0cStaticFileMiddleware \u4f1a\u63d0\u4f9b\u5728\u5e94\u7528\u7a0b\u5e8f\u7684 wwwroot \u6587\u4ef6\u5939\u4e2d\u627e\u5230\u7684\u4efb\u4f55\u8bf7\u6c42\u6587\u4ef6\u3002<\/li>\n<li>DeveloperExceptionPageMiddleware provides a lot of information about errors during development, but it should never be used in production.<br \/>\nDeveloperExceptionPageMiddleware \u5728\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u63d0\u4f9b\u4e86\u5927\u91cf\u6709\u5173\u9519\u8bef\u7684\u4fe1\u606f\uff0c\u4f46\u7edd\u4e0d\u5e94\u8be5\u5728\u751f\u4ea7\u4e2d\u4f7f\u7528\u3002<\/li>\n<li>ExceptionHandlerMiddleware lets you provide user-friendly custom error-handling messages when an exception occurs in the pipeline. It\u2019s safe for use in production, as it doesn\u2019t expose sensitive details about your application.<br \/>\nExceptionHandlerMiddleware \u5141\u8bb8\u60a8\u5728\u7ba1\u9053\u4e2d\u53d1\u751f\u5f02\u5e38\u65f6\u63d0\u4f9b\u7528\u6237\u53cb\u597d\u7684\u81ea\u5b9a\u4e49\u9519\u8bef\u5904\u7406\u6d88\u606f\u3002\u5b83\u53ef\u4ee5\u5b89\u5168\u5730\u7528\u4e8e\u751f\u4ea7\u73af\u5883\uff0c\u56e0\u4e3a\u5b83\u4e0d\u4f1a\u66b4\u9732\u6709\u5173\u5e94\u7528\u7a0b\u5e8f\u7684\u654f\u611f\u8be6\u7ec6\u4fe1\u606f\u3002<\/li>\n<li>Microsoft provides some common middleware, and many third-party options are available on NuGet and GitHub.<br \/>\nMicrosoft \u63d0\u4f9b\u4e86\u4e00\u4e9b\u5e38\u89c1\u7684\u4e2d\u95f4\u4ef6\uff0cNuGet \u548c GitHub \u4e0a\u63d0\u4f9b\u4e86\u8bb8\u591a\u7b2c\u4e09\u65b9\u9009\u9879\u3002<\/li>\n<\/ul>\n<hr \/>\n<p>[1] Technically, middleware needs to be a function, as you\u2019ll see in chapter 31, but it\u2019s common to implement middleware as a C# class with a single method.<br \/>\n\u4ece\u6280\u672f\u4e0a\u8bb2\uff0c\u4e2d\u95f4\u4ef6\u9700\u8981\u662f\u4e00\u4e2a\u51fd\u6570\uff0c\u5982\u7b2c 31 \u7ae0\u6240\u793a\uff0c\u4f46\u901a\u5e38\u4f7f\u7528\u5355\u4e2a\u65b9\u6cd5\u5c06\u4e2d\u95f4\u4ef6\u5b9e\u73b0\u4e3a C# \u7c7b\u3002<\/p>\n<p>[2] The downside to this approach is that it can hide exactly which middleware is being added to the pipeline. When the answer isn\u2019t clear, I typically search for the source code of the extension method directly in GitHub (<a href=\"https:\/\/github.com\/aspnet\/aspnetcore\">https:\/\/github.com\/aspnet\/aspnetcore<\/a>).<br \/>\n\u8fd9\u79cd\u65b9\u6cd5\u7684\u7f3a\u70b9\u662f\u5b83\u53ef\u4ee5\u51c6\u786e\u9690\u85cf\u8981\u6dfb\u52a0\u5230\u7ba1\u9053\u7684\u4e2d\u95f4\u4ef6\u3002\u5f53\u7b54\u6848\u4e0d\u660e\u786e\u65f6\uff0c\u6211\u901a\u5e38\u4f1a\u76f4\u63a5\u5728 GitHub \uff08<a href=\"https:\/\/github.com\/aspnet\/aspnetcore\">https:\/\/github.com\/aspnet\/aspnetcore<\/a>\uff09 \u4e2d\u641c\u7d22\u6269\u5c55\u65b9\u6cd5\u7684\u6e90\u4ee3\u7801\u3002<\/p>\n<p>[3] C# 8.0 introduced non-nullable reference types, which provide a way to handle null values more clearly, with the promise of finally ridding .NET of NullReferenceExceptions! The ASP.NET Core framework libraries in .NET 7 have fully embraced nullable reference types. See the documentation to learn more: <a href=\"http:\/\/mng.bz\/7V0g\">http:\/\/mng.bz\/7V0g<\/a>.<br \/>\nC# 8.0 \u5f15\u5165\u4e86\u4e0d\u53ef\u4e3a null \u7684\u5f15\u7528\u7c7b\u578b\uff0c\u5b83\u63d0\u4f9b\u4e86\u4e00\u79cd\u66f4\u6e05\u6670\u5730\u5904\u7406 null \u503c\u7684\u65b9\u6cd5\uff0c\u5e76\u6709\u671b\u6700\u7ec8\u6d88\u9664 .NET \u7684 NullReferenceExceptions\uff01.NET 7 \u4e2d\u7684 ASP.NET Core \u6846\u67b6\u5e93\u5df2\u5b8c\u5168\u91c7\u7528\u53ef\u4e3a null \u7684\u5f15\u7528\u7c7b\u578b\u3002\u8bf7\u53c2\u9605\u6587\u6863\u4ee5\u4e86\u89e3\u66f4\u591a\u4fe1\u606f\uff1ahttp:\/\/ mng.bz\/7V0g\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>4 Handling requests with the middleware pipeline \u4f7f\u7528\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5904\u7406\u8bf7\u6c42 This chapter covers \u672c\u7ae0\u6db5\u76d6 Understanding middleware \u4e86\u89e3\u4e2d\u95f4\u4ef6 Serving static files using middleware \u4f7f\u7528\u4e2d\u95f4\u4ef6\u63d0\u4f9b\u9759\u6001\u6587\u4ef6 Adding functionality using middleware \u4f7f\u7528\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u529f\u80fd Combining middleware to form a pipeline \u7ec4\u5408\u4e2d\u95f4\u4ef6\u5f62\u6210\u7ba1\u9053 Handling exceptions and errors with middleware \u4f7f\u7528\u4e2d\u95f4\u4ef6\u5904\u7406\u5f02\u5e38\u548c\u9519\u8bef In chapter 3 you had a whistle-stop tour of a complete ASP.NET Core application to [&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":[19],"class_list":["post-576","post","type-post","status-publish","format-standard","hentry","category-csharp","tag-asp-net-core-in-action"],"_links":{"self":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/576","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=576"}],"version-history":[{"count":0,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/576\/revisions"}],"wp:attachment":[{"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=576"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=576"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=576"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}