{"id":631,"date":"2025-04-05T11:43:25","date_gmt":"2025-04-05T03:43:25","guid":{"rendered":"https:\/\/www.hyy.net\/?p=631"},"modified":"2025-04-05T11:43:25","modified_gmt":"2025-04-05T03:43:25","slug":"asp-net-core-in-action-30-uilding-asp-net-core-apps-with-the-generic-host-and-startup","status":"publish","type":"post","link":"https:\/\/diji.net\/?p=631","title":{"rendered":"ASP.NET Core in Action 30 Building ASP.NET Core apps with the generic host and Startup"},"content":{"rendered":"<h1>Part 5 Going further with ASP.NET Core\u200c<\/h1>\n<p>\u7b2c 5 \u90e8\u5206\uff1a\u8fdb\u4e00\u6b65\u4e86\u89e3 ASP.NET Core<\/p>\n<p>Parts 1 through 4 of this book touched on all the aspects of ASP.NET Core you need to learn to build an HTTP application, whether that\u2019s server-rendered applications using Razor Pages or JavaScript Object Notation (JSON) APIs using minimal APIs. In part 5 we look at four topics that build on what you\u2019ve learned so far: customizing ASP.NET Core to your needs, interacting with third-party HTTP APIs, background services, and testing.<br \/>\n\u672c\u4e66\u7684\u7b2c 1 \u90e8\u5206\u5230\u7b2c 4 \u90e8\u5206\u4ecb\u7ecd\u4e86\u6784\u5efa HTTP \u5e94\u7528\u7a0b\u5e8f\u9700\u8981\u5b66\u4e60\u7684 ASP.NET Core \u7684\u6240\u6709\u65b9\u9762\uff0c\u65e0\u8bba\u662f\u4f7f\u7528 Razor Pages \u7684\u670d\u52a1\u5668\u5448\u73b0\u7684\u5e94\u7528\u7a0b\u5e8f\uff0c\u8fd8\u662f\u4f7f\u7528\u6700\u5c11 API \u7684 JavaScript \u5bf9\u8c61\u8868\u793a\u6cd5 \uff08JSON\uff09 API\u3002\u5728\u7b2c 5 \u90e8\u5206\u4e2d\uff0c\u6211\u4eec\u5c06\u4ecb\u7ecd\u57fa\u4e8e\u60a8\u76ee\u524d\u6240\u5b66\u77e5\u8bc6\u7684\u56db\u4e2a\u4e3b\u9898\uff1a\u6839\u636e\u60a8\u7684\u9700\u6c42\u81ea\u5b9a\u4e49 ASP.NET Core\u3001\u4e0e\u7b2c\u4e09\u65b9 HTTP API \u4ea4\u4e92\u3001\u540e\u53f0\u670d\u52a1\u548c\u6d4b\u8bd5\u3002<\/p>\n<p>In chapter 30 we start by looking at an alternative way to bootstrap your ASP.NET Core applications, using the generic host instead of the WebApplication approach you\u2019ve seen so far in the book. The generic host was the standard way to bootstrap apps before .NET 6 (and is the approach you\u2019ll \ufb01nd in previous editions of this book), so it\u2019s useful to recognize the pattern, but it also comes in handy for building non-HTTP applications, as you\u2019ll see in chapter 34.<br \/>\n\u5728\u7b2c 30 \u7ae0\u4e2d\uff0c\u6211\u4eec\u9996\u5148\u7814\u7a76\u4e86\u4e00\u79cd\u66ff\u4ee3\u65b9\u6cd5\u6765\u5f15\u5bfc ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\uff0c\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u800c\u4e0d\u662f\u60a8\u5728\u672c\u4e66\u4e2d\u5230\u76ee\u524d\u4e3a\u6b62\u770b\u5230\u7684 WebApplication \u65b9\u6cd5\u3002\u5728 .NET 6 \u4e4b\u524d\uff0c\u6cdb\u578b\u4e3b\u673a\u662f\u5f15\u5bfc\u5e94\u7528\u7a0b\u5e8f\u7684\u6807\u51c6\u65b9\u6cd5\uff08\u60a8\u5c06\u5728\u672c\u4e66\u7684\u524d\u51e0\u4e2a\u7248\u672c\u4e2d\u627e\u5230\u8be5\u65b9\u6cd5\uff09\uff0c\u56e0\u6b64\u8bc6\u522b\u6a21\u5f0f\u5f88\u6709\u7528\uff0c\u4f46\u5b83\u5728\u6784\u5efa\u975e HTTP \u5e94\u7528\u7a0b\u5e8f\u65f6\u4e5f\u5f88\u65b9\u4fbf\uff0c\u5982\u7b2c 34 \u7ae0\u6240\u793a\u3002<\/p>\n<p>In part 1 you learned about the middleware pipeline, and you saw how it is fundamental to all ASP.NET Core applications. In chapter 31 you\u2019ll learn how to take full advantage of the pipeline, creating branching middleware pipelines, custom middleware, and simple middleware- based endpoints. You\u2019ll also learn how to handle some complex chicken-and-egg con\ufb01guration issues that often arise in real-life applications. Finally, you\u2019ll learn how to replace the built-in dependency injection container with a third-party alternative.<br \/>\n\u5728\u7b2c 1 \u90e8\u5206\u4e2d\uff0c\u60a8\u4e86\u89e3\u4e86\u4e2d\u95f4\u4ef6\u7ba1\u9053\uff0c\u5e76\u4e86\u89e3\u4e86\u5b83\u5982\u4f55\u6210\u4e3a\u6240\u6709 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u7684\u57fa\u7840\u3002\u5728\u7b2c 31 \u7ae0\u4e2d\uff0c\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u5145\u5206\u5229\u7528\u7ba1\u9053\uff0c\u521b\u5efa\u5206\u652f\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3001\u81ea\u5b9a\u4e49\u4e2d\u95f4\u4ef6\u548c\u57fa\u4e8e\u4e2d\u95f4\u4ef6\u7684\u7b80\u5355\u7aef\u70b9\u3002\u60a8\u8fd8\u5c06\u5b66\u4e60\u5982\u4f55\u5904\u7406\u5b9e\u9645\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7ecf\u5e38\u51fa\u73b0\u7684\u4e00\u4e9b\u590d\u6742\u7684\u5148\u6709\u9e21\u8fd8\u662f\u5148\u6709\u86cb\u7684\u914d\u7f6e\u95ee\u9898\u3002\u6700\u540e\uff0c\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u5c06\u5185\u7f6e\u7684\u4f9d\u8d56\u9879\u6ce8\u5165\u5bb9\u5668\u66ff\u6362\u4e3a\u7b2c\u4e09\u65b9\u66ff\u4ee3\u65b9\u6848\u3002<\/p>\n<p>In chapter 32 you\u2019ll learn how to create custom components for working with Razor Pages and API controllers. You\u2019ll learn how to create custom Tag Helpers and validation attributes, and I\u2019ll introduce a new component\u2014view components\u2014for encapsulating logic with Razor view rendering. You\u2019ll also learn how to replace the attribute-based validation framework used by default in ASP.NET Core with an alternative.<br \/>\n\u5728\u7b2c 32 \u7ae0\u4e2d\uff0c\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u521b\u5efa\u81ea\u5b9a\u4e49\u7ec4\u4ef6\u4ee5\u4f7f\u7528 Razor Pages \u548c API \u63a7\u5236\u5668\u3002\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u521b\u5efa\u81ea\u5b9a\u4e49\u6807\u8bb0\u5e2e\u52a9\u7a0b\u5e8f\u548c\u9a8c\u8bc1\u5c5e\u6027\uff0c\u5e76\u4e14\u6211\u5c06\u4ecb\u7ecd\u4e00\u4e2a\u65b0\u7ec4\u4ef6 \u2014 \u89c6\u56fe\u7ec4\u4ef6 \u2014 \u7528\u4e8e\u4f7f\u7528 Razor \u89c6\u56fe\u6e32\u67d3\u5c01\u88c5\u903b\u8f91\u3002\u60a8\u8fd8\u5c06\u4e86\u89e3\u5982\u4f55\u5c06 ASP.NET Core \u4e2d\u9ed8\u8ba4\u4f7f\u7528\u7684\u57fa\u4e8e\u5c5e\u6027\u7684\u9a8c\u8bc1\u6846\u67b6\u66ff\u6362\u4e3a\u66ff\u4ee3\u6846\u67b6\u3002<\/p>\n<p>Most apps you build aren\u2019t designed to stand on their own. It\u2019s common for your app to need to interact with APIs, whether those are APIs for sending emails, taking payments, or interacting with your own internal applications. In chapter 33 you\u2019ll learn how to call these APIs using the IHttpClientFactory abstraction to simplify con\ufb01guration, add transient fault handling, and avoid common pitfalls.<br \/>\n\u60a8\u6784\u5efa\u7684\u5927\u591a\u6570\u5e94\u7528\u7a0b\u5e8f\u90fd\u4e0d\u662f\u4e3a\u4e86\u72ec\u7acb\u800c\u6784\u5efa\u7684\u3002\u60a8\u7684\u5e94\u7528\u901a\u5e38\u9700\u8981\u4e0e API \u4ea4\u4e92\uff0c\u65e0\u8bba\u8fd9\u4e9b API \u662f\u7528\u4e8e\u53d1\u9001\u7535\u5b50\u90ae\u4ef6\u3001\u6536\u6b3e\u8fd8\u662f\u4e0e\u60a8\u81ea\u5df1\u7684\u5185\u90e8\u5e94\u7528\u7a0b\u5e8f\u4ea4\u4e92\u7684 API\u3002\u5728\u7b2c 33 \u7ae0\u4e2d\uff0c\u60a8\u5c06\u5b66\u4e60\u5982\u4f55\u4f7f\u7528 IHttpClientFactory \u62bd\u8c61\u8c03\u7528\u8fd9\u4e9b API\uff0c\u4ee5\u7b80\u5316\u914d\u7f6e\u3001\u6dfb\u52a0\u77ac\u6001\u6545\u969c\u5904\u7406\u5e76\u907f\u514d\u5e38\u89c1\u9677\u9631\u3002<\/p>\n<p>This book deals primarily with serving HTTP tra\ufb03c, both server-rendered web pages using Razor Pages and web APIs commonly used by mobile and single-page applications.<br \/>\n\u672c\u4e66\u4e3b\u8981\u4ecb\u7ecd\u63d0\u4f9b HTTP \u6d41\u91cf\uff0c\u5305\u62ec\u4f7f\u7528 Razor Pages \u7684\u670d\u52a1\u5668\u5448\u73b0\u7684\u7f51\u9875\uff0c\u4ee5\u53ca\u79fb\u52a8\u548c\u5355\u9875\u5e94\u7528\u7a0b\u5e8f\u5e38\u7528\u7684 Web API\u3002<\/p>\n<p>However, many apps require long-running background tasks that execute jobs on a schedule or that process items from a queue. In chapter 34 I\u2019ll show how you can create these long-running background tasks in your ASP.NET Core applications. I\u2019ll also show how to create standalone services that have only background tasks, without any HTTP handling, and how to install them as a Windows Service or as a Linux systemd daemon.<br \/>\n\u4f46\u662f\uff0c\u8bb8\u591a\u5e94\u7528\u7a0b\u5e8f\u9700\u8981\u957f\u65f6\u95f4\u8fd0\u884c\u7684\u540e\u53f0\u4efb\u52a1\uff0c\u8fd9\u4e9b\u4efb\u52a1\u6309\u8ba1\u5212\u6267\u884c\u4f5c\u4e1a\u6216\u5904\u7406\u961f\u5217\u4e2d\u7684\u9879\u76ee\u3002\u5728\u7b2c 34 \u7ae0\u4e2d\uff0c\u6211\u5c06\u5c55\u793a\u5982\u4f55\u5728 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u4e2d\u521b\u5efa\u8fd9\u4e9b\u957f\u65f6\u95f4\u8fd0\u884c\u7684\u540e\u53f0\u4efb\u52a1\u3002\u6211\u8fd8\u5c06\u5c55\u793a\u5982\u4f55\u521b\u5efa\u4ec5\u5305\u542b\u540e\u53f0\u4efb\u52a1\u800c\u6ca1\u6709\u4efb\u4f55 HTTP \u5904\u7406\u7684\u72ec\u7acb\u670d\u52a1\uff0c\u4ee5\u53ca\u5982\u4f55\u5c06\u5b83\u4eec\u5b89\u88c5\u4e3a Windows \u670d\u52a1\u6216 Linux systemd \u5b88\u62a4\u7a0b\u5e8f\u3002<\/p>\n<p>Chapters 35 and 36, the \ufb01nal chapters, cover testing your application. The exact role of testing in application development can lead to philosophical arguments, but in these chapters I stick to the practicalities of testing your app with the xUnit test framework. You\u2019ll see how to create unit tests for your apps, test code that\u2019s dependent on EF Core using an in-memory database provider, and write integration tests that can test multiple aspects of your application at the same time.<br \/>\n\u7b2c 35 \u7ae0\u548c\u7b2c 36 \u7ae0\u662f\u6700\u540e\u51e0\u7ae0\uff0c\u6db5\u76d6\u4e86\u6d4b\u8bd5\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u3002\u6d4b\u8bd5\u5728\u5e94\u7528\u7a0b\u5e8f\u5f00\u53d1\u4e2d\u7684\u786e\u5207\u4f5c\u7528\u53ef\u80fd\u4f1a\u5bfc\u81f4\u54f2\u5b66\u4e89\u8bba\uff0c\u4f46\u5728\u8fd9\u4e9b\u7ae0\u8282\u4e2d\uff0c\u6211\u5c06\u91cd\u70b9\u4ecb\u7ecd\u4f7f\u7528 xUnit \u6d4b\u8bd5\u6846\u67b6\u6d4b\u8bd5\u5e94\u7528\u7a0b\u5e8f\u7684\u5b9e\u7528\u6027\u3002\u4f60\u5c06\u4e86\u89e3\u5982\u4f55\u4e3a\u5e94\u7528\u521b\u5efa\u5355\u5143\u6d4b\u8bd5\uff0c\u4f7f\u7528\u5185\u5b58\u4e2d\u6570\u636e\u5e93\u63d0\u4f9b\u7a0b\u5e8f\u6d4b\u8bd5\u4f9d\u8d56\u4e8e EF Core \u7684\u4ee3\u7801\uff0c\u4ee5\u53ca\u7f16\u5199\u53ef\u4ee5\u540c\u65f6\u6d4b\u8bd5\u5e94\u7528\u7a0b\u5e8f\u591a\u4e2a\u65b9\u9762\u7684\u96c6\u6210\u6d4b\u8bd5\u3002<\/p>\n<p>In the fast-paced world of web development there\u2019s always more to learn, but by the end of part 5 you should have everything you need to build applications with ASP.NET Core, whether they be server-rendered page-based applications, APIs, or background services.<br \/>\n\u5728\u5feb\u8282\u594f\u7684 Web \u5f00\u53d1\u4e16\u754c\u4e2d\uff0c\u603b\u662f\u6709\u66f4\u591a\u7684\u4e1c\u897f\u9700\u8981\u5b66\u4e60\uff0c\u4f46\u5728\u7b2c 5 \u90e8\u5206\u7ed3\u675f\u65f6\uff0c\u60a8\u5e94\u8be5\u62e5\u6709\u4f7f\u7528 ASP.NET Core \u6784\u5efa\u5e94\u7528\u7a0b\u5e8f\u6240\u9700\u7684\u4e00\u5207\uff0c\u65e0\u8bba\u5b83\u4eec\u662f\u670d\u52a1\u5668\u6e32\u67d3\u7684\u57fa\u4e8e\u9875\u9762\u7684\u5e94\u7528\u7a0b\u5e8f\u3001API \u8fd8\u662f\u540e\u53f0\u670d\u52a1\u3002<\/p>\n<p>In the appendices for this book, I provide some background and resources about .NET. Appendix A describes how to prepare your development environment by installing .NET 7 and an IDE or editor. In appendix B you\u2019ll \ufb01nd a list of resources I use to learn more about ASP.NET Core and to stay up to date with the latest features.<br \/>\n\u5728\u672c\u4e66\u7684\u9644\u5f55\u4e2d\uff0c\u6211\u63d0\u4f9b\u4e86\u4e00\u4e9b\u6709\u5173 .NET \u7684\u80cc\u666f\u548c\u8d44\u6e90\u3002\u9644\u5f55 A \u4ecb\u7ecd\u4e86\u5982\u4f55\u901a\u8fc7\u5b89\u88c5 .NET 7 \u548c IDE \u6216\u7f16\u8f91\u5668\u6765\u51c6\u5907\u5f00\u53d1\u73af\u5883\u3002\u5728\u9644\u5f55 B \u4e2d\uff0c\u60a8\u5c06\u627e\u5230\u6211\u7528\u6765\u4e86\u89e3\u6709\u5173 ASP.NET Core \u7684\u66f4\u591a\u4fe1\u606f\u5e76\u4e86\u89e3\u6700\u65b0\u529f\u80fd\u7684\u8d44\u6e90\u5217\u8868\u3002<\/p>\n<h1>30 Building ASP.NET Core apps with the generic host and Startup<\/h1>\n<p>30 \u4f7f\u7528\u901a\u7528\u4e3b\u673a\u6784\u5efa ASP.NET Core \u5e94\u7528\u7a0b\u5e8f \u548c Startup<\/p>\n<p>This chapter covers<br \/>\n\u672c\u7ae0\u6db5\u76d6<\/p>\n<p>\u2022  Using the generic host and a Startup class to bootstrap your ASP.NET Core app<br \/>\n\u4f7f\u7528\u6cdb\u578b\u4e3b\u673a\u548c Startup \u7c7b\u5f15\u5bfc ASP.NET Core \u5e94\u7528\u7a0b\u5e8f<\/p>\n<p>\u2022  Understanding how the generic host di\ufb00ers from WebApplication<br \/>\n\u4e86\u89e3\u901a\u7528\u4e3b\u673a\u4e0e WebApplication \u7684\u533a\u522b<\/p>\n<p>\u2022  Building a custom generic IHostBuilder<br \/>\n\u6784\u5efa\u81ea\u5b9a\u4e49\u901a\u7528 IHostBuilder<\/p>\n<p>\u2022  Choosing between the generic host and minimal hosting<br \/>\n\u5728\u901a\u7528\u4e3b\u673a\u548c\u6700\u5c0f\u4e3b\u673a\u4e4b\u95f4\u8fdb\u884c\u9009\u62e9<\/p>\n<p>Some of the biggest changes introduced in ASP.NET Core in .NET 6 were the minimal hosting APIs, namely the WebApplication and WebApplicationBuilder types you\u2019ve seen throughout this book. These were introduced to dramatically reduce the amount of code needed to get started with ASP.NET Core and are now the default way to build ASP.NET Core apps.\u200c<br \/>\n\u5728 .NET 6 \u4e2d\u5f15\u5165 ASP.NET Core \u7684\u4e00\u4e9b\u6700\u5927\u53d8\u5316\u662f\u6700\u5c0f\u7684\u6258\u7ba1 API\uff0c\u5373\u60a8\u5728\u672c\u4e66\u4e2d\u770b\u5230\u7684 WebApplication \u548c WebApplicationBuilder \u7c7b\u578b\u3002\u5f15\u5165\u8fd9\u4e9b\u5e94\u7528\u7a0b\u5e8f\u662f\u4e3a\u4e86\u663e\u8457\u51cf\u5c11\u5f00\u59cb\u4f7f\u7528 ASP.NET Core \u6240\u9700\u7684\u4ee3\u7801\u91cf\uff0c\u73b0\u5728\u662f\u6784\u5efa ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u7684\u9ed8\u8ba4\u65b9\u5f0f\u3002<\/p>\n<p>Before .NET 6, ASP.NET Core used a di\ufb00erent approach to bootstrap your app: the generic host, IHost, IHostBuilder, and a Startup class. Even though this approach is not the default in .NET 7, it\u2019s still valid, so it\u2019s important that you\u2019re aware of it, even if you don\u2019t need to use it yourself. In this chapter I introduce the generic host and show how it relates to the minimal hosting APIs you\u2019re already familiar with. In chapter 34 you\u2019ll learn how to use the generic host approach to build nonweb apps too.<br \/>\n\u5728 .NET 6 \u4e4b\u524d\uff0cASP.NET Core \u4f7f\u7528\u4e0d\u540c\u7684\u65b9\u6cd5\u6765\u542f\u52a8\u5e94\u7528\u7a0b\u5e8f\uff1a\u6cdb\u578b\u4e3b\u673a\u3001IHost\u3001IHostBuilder \u548c Startup \u7c7b\u3002\u5373\u4f7f\u6b64\u65b9\u6cd5\u4e0d\u662f .NET 7 \u4e2d\u7684\u9ed8\u8ba4\u65b9\u6cd5\uff0c\u5b83\u4ecd\u7136\u6709\u6548\uff0c\u56e0\u6b64\u5373\u4f7f\u60a8\u81ea\u5df1\u4e0d\u9700\u8981\u4f7f\u7528\u5b83\uff0c\u4e86\u89e3\u5b83\u4e5f\u5f88\u91cd\u8981\u3002\u5728\u672c\u7ae0\u4e2d\uff0c\u6211\u5c06\u4ecb\u7ecd\u901a\u7528\u4e3b\u673a\uff0c\u5e76\u5c55\u793a\u5b83\u4e0e\u60a8\u5df2\u7ecf\u719f\u6089\u7684\u6700\u5c0f\u6258\u7ba1 API \u7684\u5173\u7cfb\u3002\u5728\u7b2c 34 \u7ae0\u4e2d\uff0c\u4f60\u4e5f\u5c06\u5b66\u4e60\u5982\u4f55\u4f7f\u7528\u901a\u7528\u7684 host \u65b9\u6cd5\u6765\u6784\u5efa\u975e Web \u5e94\u7528\u7a0b\u5e8f\u3002<\/p>\n<p>I start by introducing the two main concepts: the generic host components (IHostBuilder and IHost) and the Startup class. These split your app bootstrapping code between two \ufb01les, Program.cs and Startup.cs, handling di\ufb00erent aspects of your app\u2019s con\ufb01guration. You\u2019ll learn why this split was introduced, where each component is con\ufb01gured, and how it compares with minimal hosting using WebApplication.<br \/>\n\u9996\u5148\uff0c\u6211\u5c06\u4ecb\u7ecd\u4e24\u4e2a\u4e3b\u8981\u6982\u5ff5\uff1a\u901a\u7528\u4e3b\u673a\u7ec4\u4ef6\uff08IHostBuilder \u548c IHost\uff09\u548c Startup \u7c7b\u3002\u8fd9\u4e9b\u9009\u9879\u5c06\u4f60\u7684\u5e94\u7528\u7a0b\u5e8f\u5f15\u5bfc\u4ee3\u7801\u62c6\u5206\u4e3a\u4e24\u4e2a\u6587\u4ef6\uff08Program.cs \u548c Startup.cs\uff09\uff0c\u5904\u7406\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\u7684\u4e0d\u540c\u65b9\u9762\u3002\u60a8\u5c06\u4e86\u89e3\u5f15\u5165\u6b64\u62c6\u5206\u7684\u539f\u56e0\u3001\u6bcf\u4e2a\u7ec4\u4ef6\u7684\u914d\u7f6e\u4f4d\u7f6e\uff0c\u4ee5\u53ca\u5b83\u4e0e\u4f7f\u7528 WebApplication \u7684\u6700\u5c0f\u6258\u7ba1\u7684\u6bd4\u8f83\u3002<\/p>\n<p>In section 30.4 you\u2019ll learn how the helper function Host.CreateDefaultBuilder() works and use this knowledge to customize the IHostBuilder instance. This can give you greater control than minimal hosting, which may be useful in some situations.<br \/>\n\u5728\u7b2c 30.4 \u8282\u4e2d\uff0c\u60a8\u5c06\u4e86\u89e3\u5e2e\u52a9\u7a0b\u5e8f\u51fd\u6570 Host.CreateDefaultBuilder\uff08\uff09 \u7684\u5de5\u4f5c\u539f\u7406\uff0c\u5e76\u5229\u7528\u8fd9\u4e9b\u77e5\u8bc6\u81ea\u5b9a\u4e49 IHostBuilder \u5b9e\u4f8b\u3002\u8fd9\u53ef\u4ee5\u4e3a\u60a8\u63d0\u4f9b\u6bd4\u6700\u5c0f\u6258\u7ba1\u66f4\u5927\u7684\u63a7\u5236\u6743\uff0c\u8fd9\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\u53ef\u80fd\u5f88\u6709\u7528\u3002<\/p>\n<p>In section 30.5 we take a step back and look at some of the drawbacks in the generic host bootstrapping code we\u2019ve explored, particularly its apparent complexity compared to minimal hosting with WebApplication.<br \/>\n\u5728 Section 30.5 \u4e2d\uff0c\u6211\u4eec\u9000\u540e\u4e00\u6b65\uff0c\u770b\u770b\u6211\u4eec\u63a2\u7d22\u8fc7\u7684\u901a\u7528\u4e3b\u673a\u5f15\u5bfc\u4ee3\u7801\u4e2d\u7684\u4e00\u4e9b\u7f3a\u70b9\uff0c\u7279\u522b\u662f\u4e0e\u4f7f\u7528 WebApplication \u8fdb\u884c\u6700\u5c0f\u6258\u7ba1\u76f8\u6bd4\uff0c\u5b83\u660e\u663e\u7684\u590d\u6742\u6027\u3002<\/p>\n<p>Finally, in section 30.6 I discuss some of the reasons you might nevertheless choose to use the generic host instead of minimal hosting in your .NET 7 app. In most cases I suggest using minimal hosting with WebApplication, but there are valid cases in which the generic host makes sense.<br \/>\n\u6700\u540e\uff0c\u5728\u7b2c 30.6 \u8282\u4e2d\uff0c\u6211\u5c06\u8ba8\u8bba\u4e00\u4e9b\u539f\u56e0\uff0c\u60a8\u53ef\u80fd\u4ecd\u7136\u9009\u62e9\u5728 .NET 7 \u5e94\u7528\u7a0b\u5e8f\u4e2d\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u800c\u4e0d\u662f\u6700\u5c0f\u6258\u7ba1\u3002\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u6211\u5efa\u8bae\u5bf9 WebApplication \u4f7f\u7528\u6700\u5c0f\u6258\u7ba1\uff0c\u4f46\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u901a\u7528\u4e3b\u673a\u662f\u6709\u610f\u4e49\u7684\u3002<\/p>\n<h2>30.1 Separating concerns between two \ufb01les\u200c<\/h2>\n<p>30.1 \u5728\u4e24\u4e2a\u6587\u4ef6\u4e4b\u95f4\u5206\u79bb\u5173\u6ce8\u70b9<\/p>\n<p>As you\u2019ve seen throughout this book, the standard way to create an ASP.NET Core application in .NET 7 is with the WebApplicationBuilder and WebApplication classes inside Program.cs, using top-level statements. Before .NET 6, however, ASP.NET Core used a di\ufb00erent approach, which you can still use in .NET 7 if you wish.\u200c\u200c<br \/>\n\u6b63\u5982\u60a8\u5728\u672c\u4e66\u4e2d\u6240\u770b\u5230\u7684\uff0c\u5728 .NET 7 \u4e2d\u521b\u5efa ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u7684\u6807\u51c6\u65b9\u6cd5\u662f\u4f7f\u7528\u9876\u7ea7\u8bed\u53e5\u5728 Program.cs \u4e2d\u4f7f\u7528 WebApplicationBuilder \u548c WebApplication \u7c7b\u3002\u4f46\u662f\uff0c\u5728 .NET 6 \u4e4b\u524d\uff0cASP.NET Core \u4f7f\u7528\u4e0d\u540c\u7684\u65b9\u6cd5\uff0c\u5982\u679c\u60a8\u613f\u610f\uff0c\u60a8\u4ecd\u7136\u53ef\u4ee5\u5728 .NET 7 \u4e2d\u4f7f\u7528\u8be5\u65b9\u6cd5\u3002<\/p>\n<p>This approach typically uses a traditional static void Main() entry point (although top-level statements are supported) and splits its bootstrapping code across two \ufb01les, as shown in \ufb01gure 30.1:<br \/>\n\u8fd9\u79cd\u65b9\u6cd5\u901a\u5e38\u4f7f\u7528\u4f20\u7edf\u7684\u9759\u6001 void Main\uff08\uff09 \u5165\u53e3\u70b9\uff08\u5c3d\u7ba1\u652f\u6301\u9876\u7ea7\u8bed\u53e5\uff09\uff0c\u5e76\u5c06\u5176\u5f15\u5bfc\u4ee3\u7801\u62c6\u5206\u4e3a\u4e24\u4e2a\u6587\u4ef6\uff0c\u5982\u56fe 30.1 \u6240\u793a\uff1a<\/p>\n<p>\u2022  Program.cs\u2014This contains the entry point for the application, which bootstraps a host object. This is where you con\ufb01gure the infrastructure of your application, such as Kestrel, integration with Internet Information Services (IIS), and con\ufb01guration sources.<br \/>\nProgram.cs - \u5305\u542b\u5e94\u7528\u7a0b\u5e8f\u7684\u5165\u53e3\u70b9\uff0c\u7528\u4e8e\u5f15\u5bfc\u4e3b\u673a\u5bf9\u8c61\u3002\u60a8\u53ef\u4ee5\u5728\u6b64\u5904\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u7684\u57fa\u7840\u7ed3\u6784\uff0c\u4f8b\u5982 Kestrel\u3001\u4e0e Internet Information Services \uff08IIS\uff09 \u7684\u96c6\u6210\u4ee5\u53ca\u914d\u7f6e\u6e90\u3002<\/p>\n<p>\u2022  Startup.cs\u2014The Startup class is where you con\ufb01gure your dependency injection (DI) container, your middleware pipeline, and your application\u2019s endpoints.<br \/>\nStartup.cs - Startup \u7c7b\u7528\u4e8e\u914d\u7f6e\u4f9d\u8d56\u5173\u7cfb\u6ce8\u5165 \uff08DI\uff09 \u5bb9\u5668\u3001\u4e2d\u95f4\u4ef6\u7ba1\u9053\u548c\u5e94\u7528\u7a0b\u5e8f\u7684\u7aef\u70b9\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/3001.jpg\" alt=\"alt text\" \/><\/p>\n<p>Figure 30.1 The di\ufb00erent responsibilities of the Program and Startup classes in an ASP.NET Core app that uses the generic host instead of WebApplication<br \/>\n\u56fe 30.1 \u4f7f\u7528\u6cdb\u578b\u4e3b\u673a\u800c\u4e0d\u662f WebApplication \u7684 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u4e2d Program \u548c Startup \u7c7b\u7684\u4e0d\u540c\u804c\u8d23<\/p>\n<p>We\u2019ll look at each of these \ufb01les in turn in section 30.2 and 30.3 to see how they might look for a typical Razor Pages app. I discuss the generic host at the center of this setup and compare the approach with the newer WebApplication APIs you\u2019ve used so far throughout the book.<br \/>\n\u6211\u4eec\u5c06\u5728\u7b2c 30.2 \u8282\u548c\u7b2c 30.3 \u8282\u4e2d\u4f9d\u6b21\u67e5\u770b\u8fd9\u4e9b\u6587\u4ef6\uff0c\u4ee5\u4e86\u89e3\u5b83\u4eec\u5728\u5178\u578b Razor Pages \u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u5916\u89c2\u3002\u6211\u5c06\u8ba8\u8bba\u6b64\u8bbe\u7f6e\u4e2d\u5fc3\u7684\u901a\u7528\u4e3b\u673a\uff0c\u5e76\u5c06\u8be5\u65b9\u6cd5\u4e0e\u60a8\u5728\u672c\u4e66\u4e2d\u5230\u76ee\u524d\u4e3a\u6b62\u4f7f\u7528\u7684\u8f83\u65b0\u7684 WebApplication API \u8fdb\u884c\u6bd4\u8f83\u3002<\/p>\n<h2>30.2 The Program class: Building a Web Host\u200c<\/h2>\n<p>30.2 Program \u7c7b\uff1a\u6784\u5efa Web \u4e3b\u673a<\/p>\n<p>All ASP.NET Core apps are fundamentally console applications. With the Startup-based hosting model, the Main entry point builds and runs an IHost instance, as shown in the following listing, which shows a typical Program.cs \ufb01le. The IHost is the core of your ASP.NET Core application: it contains the HTTP server (Kestrel) for handling requests, along with all the necessary services and con\ufb01guration to generate responses.\u200c\u200c<br \/>\n\u6240\u6709 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u57fa\u672c\u4e0a\u90fd\u662f\u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u3002\u4f7f\u7528\u57fa\u4e8e\u542f\u52a8\u7684\u6258\u7ba1\u6a21\u578b\uff0cMain \u5165\u53e3\u70b9\u6784\u5efa\u5e76\u8fd0\u884c IHost \u5b9e\u4f8b\uff0c\u5982\u4e0b\u9762\u7684\u6e05\u5355\u6240\u793a\uff0c\u5176\u4e2d\u663e\u793a\u4e86\u4e00\u4e2a\u5178\u578b\u7684 Program.cs \u6587\u4ef6\u3002IHost \u662f ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u7684\u6838\u5fc3\uff1a\u5b83\u5305\u542b\u7528\u4e8e\u5904\u7406\u8bf7\u6c42\u7684 HTTP \u670d\u52a1\u5668 \uff08Kestrel\uff09\uff0c\u4ee5\u53ca\u7528\u4e8e\u751f\u6210\u54cd\u5e94\u7684\u6240\u6709\u5fc5\u8981\u670d\u52a1\u548c\u914d\u7f6e\u3002<\/p>\n<p>Listing 30.1 The Program.cs \ufb01le con\ufb01gures and runs an IHost<br \/>\n\u6e05\u5355 30.1 Program.cs \u6587\u4ef6\u914d\u7f6e\u5e76\u8fd0\u884c IHost<\/p>\n<pre><code>public class Program\n{\npublic static void Main(string[] args)\n{\nCreateHostBuilder(args) \u2776\n.Build() \u2777\n.Run(); \u2778\n}\npublic static IHostBuilder CreateHostBuilder(string[] args) =&gt;\nHost.CreateDefaultBuilder(args) \u2779\n.ConfigureWebHostDefaults(webBuilder =&gt; \u277a\n{\nwebBuilder.UseStartup&lt;Startup&gt;(); \u277b\n});\n}<\/code><\/pre>\n<p>\u2776 Creates an IHostBuilder using the CreateHostBuilder method<br \/>\n\u4f7f\u7528 CreateHostBuilder \u65b9\u6cd5\u521b\u5efa IHostBuilder<\/p>\n<p>\u2777 Builds and returns an instance of IHost from the IHostBuilder<br \/>\n\u4ece IHostBuilder\u6784\u5efa\u5e76\u8fd4\u56de IHost \u7684\u5b9e\u4f8b<\/p>\n<p>\u2778 Runs the IHost and starts listening for requests and generating responses<br \/>\n\u8fd0\u884c IHost \u5e76\u5f00\u59cb\u4fa6\u542c\u8bf7\u6c42\u5e76\u751f\u6210\u54cd\u5e94<\/p>\n<p>\u2779 Creates an IHostBuilder using the default configuration<br \/>\n\u4f7f\u7528\u9ed8\u8ba4\u914d\u7f6e\u521b\u5efa IHostBuilder<\/p>\n<p>\u277a Configures the application to use Kestrel and listen to HTTP requests<br \/>\n\u5c06\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\u4e3a\u4f7f\u7528 Kestrel \u5e76\u4fa6\u542c HTTP \u8bf7\u6c42<\/p>\n<p>\u277b The Startup class defines most of your application\u2019s configuration.<br \/>\nStartup \u7c7b\u5b9a\u4e49\u4e86\u5e94\u7528\u7a0b\u5e8f\u7684\u5927\u90e8\u5206\u914d\u7f6e\u3002<\/p>\n<p>The Main function contains all the basic initialization code required to create a web server and to start listening for requests. It uses an IHostBuilder, created by the call to CreateDefaultBuilder, to de\ufb01ne how the generic IHost is con\ufb01gured, before instantiating the IHost with a call to Build().<br \/>\nMain \u51fd\u6570\u5305\u542b\u521b\u5efa Web \u670d\u52a1\u5668\u548c\u5f00\u59cb\u4fa6\u542c\u8bf7\u6c42\u6240\u9700\u7684\u6240\u6709\u57fa\u672c\u521d\u59cb\u5316\u4ee3\u7801\u3002\u5b83\u4f7f\u7528\u901a\u8fc7\u8c03\u7528 CreateDefaultBuilder \u521b\u5efa\u7684 IHostBuilder \u6765\u5b9a\u4e49\u6cdb\u578b IHost \u7684\u914d\u7f6e\u65b9\u5f0f\uff0c\u7136\u540e\u518d\u901a\u8fc7\u8c03\u7528 Build\uff08\uff09 \u5b9e\u4f8b\u5316 IHost\u3002<\/p>\n<p><b>TIP<\/b>  The IHost object represents your built application. The WebApplication type you\u2019ve used throughout the book also implements IHost.<br \/>\n\u63d0\u793a:IHost \u5bf9\u8c61\u8868\u793a\u60a8\u6784\u5efa\u7684\u5e94\u7528\u7a0b\u5e8f\u3002\u60a8\u5728\u672c\u4e66\u4e2d\u4ecb\u7ecd\u7684 WebApplication \u7c7b\u578b\u4e5f\u5b9e\u73b0\u4e86 IHost\u3002<\/p>\n<p>Much of your app\u2019s con\ufb01guration takes place in the IHostBuilder created by the call to CreateDefaultBuilder, but it delegates some responsibility to a separate class, Startup. The Startup class referenced in the generic UseStartup&lt;&gt; method is where you con\ufb01gure your app\u2019s services and de\ufb01ne your middleware pipeline.<br \/>\n\u5e94\u7528\u7a0b\u5e8f\u7684\u5927\u90e8\u5206\u914d\u7f6e\u90fd\u53d1\u751f\u5728\u7531\u8c03\u7528 CreateDefaultBuilder \u521b\u5efa\u7684 IHostBuilder \u4e2d\uff0c\u4f46\u5b83\u5c06\u4e00\u4e9b\u8d23\u4efb\u59d4\u6258\u7ed9\u5355\u72ec\u7684\u7c7b Startup\u3002\u6cdb\u578b UseStartup&lt;&gt; \u65b9\u6cd5\u4e2d\u5f15\u7528\u7684 Startup \u7c7b\u662f\u60a8\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u670d\u52a1\u548c\u5b9a\u4e49\u4e2d\u95f4\u4ef6\u7ba1\u9053\u7684\u4f4d\u7f6e\u3002<\/p>\n<p><b>NOTE<\/b>  The code to build the IHostBuilder is extracted to a helper method called CreateHostBuilder. The name of this method is historically important, as it was used implicitly by tooling such as the Entity Framework Core (EF Core) tools, as I discuss in section 30.5.\u200c<br \/>\n\u6ce8\u610f:\u7528\u4e8e\u6784\u5efa IHostBuilder \u7684\u4ee3\u7801\u88ab\u63d0\u53d6\u5230\u540d\u4e3a CreateHostBuilder \u7684\u5e2e\u52a9\u7a0b\u5e8f\u65b9\u6cd5\u4e2d\u3002\u6b64\u65b9\u6cd5\u7684\u540d\u79f0\u5728\u5386\u53f2\u4e0a\u5f88\u91cd\u8981\uff0c\u56e0\u4e3a\u5b83\u7531 Entity Framework Core \uff08EF Core\uff09 \u5de5\u5177\u7b49\u5de5\u5177\u9690\u5f0f\u4f7f\u7528\uff0c\u5982\u6211\u5728\u7b2c 30.5 \u8282\u4e2d\u8ba8\u8bba\u7684\u90a3\u6837\u3002<\/p>\n<p>You may be wondering why you need two classes for con\ufb01guration: Program and Startup. Why not include all your app\u2019s con\ufb01guration in one class or the other? The idea is to separate code that changes often from code that rarely changes.<br \/>\n\u60a8\u53ef\u80fd\u60f3\u77e5\u9053\u4e3a\u4ec0\u4e48\u9700\u8981\u4e24\u4e2a\u7c7b\u8fdb\u884c\u914d\u7f6e\uff1aProgram \u548c Startup\u3002\u4e3a\u4ec0\u4e48\u4e0d\u5c06\u5e94\u7528\u7a0b\u5e8f\u7684\u6240\u6709\u914d\u7f6e\u90fd\u5305\u542b\u5728\u4e00\u4e2a\u7c7b\u6216\u53e6\u4e00\u4e2a\u7c7b\u4e2d\u5462\uff1f\u8fd9\u4e2a\u60f3\u6cd5\u662f\u5c06\u7ecf\u5e38\u66f4\u6539\u7684\u4ee3\u7801\u4e0e\u5f88\u5c11\u66f4\u6539\u7684\u4ee3\u7801\u5206\u5f00\u3002<\/p>\n<p>The Program class for two di\ufb00erent ASP.NET Core applications typically look similar, but the Startup classes often di\ufb00er signi\ufb01cantly (though they all follow the same basic pattern, as you\u2019ll see in section 30.3). You\u2019ll rarely \ufb01nd that you need to modify Program as your application grows, whereas you\u2019ll normally update Startup whenever you add additional features. For example, if you add a new NuGet dependency to your project, you\u2019ll normally need to update Startup to make use of it.<br \/>\n\u4e24\u4e2a\u4e0d\u540c\u7684 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u7684 Program \u7c7b\u901a\u5e38\u770b\u8d77\u6765\u76f8\u4f3c\uff0c\u4f46 Startup \u7c7b\u901a\u5e38\u6709\u5f88\u5927\u4e0d\u540c\uff08\u5c3d\u7ba1\u5b83\u4eec\u90fd\u9075\u5faa\u76f8\u540c\u7684\u57fa\u672c\u6a21\u5f0f\uff0c\u5982\u60a8\u5c06\u5728\u7b2c 30.3 \u8282\u4e2d\u770b\u5230\u7684\u90a3\u6837\uff09\u3002\u60a8\u5f88\u5c11\u4f1a\u53d1\u73b0\u9700\u8981\u968f\u7740\u5e94\u7528\u7a0b\u5e8f\u7684\u589e\u957f\u800c\u4fee\u6539 Program\uff0c\u800c\u60a8\u901a\u5e38\u4f1a\u5728\u6dfb\u52a0\u5176\u4ed6\u529f\u80fd\u65f6\u66f4\u65b0 Startup\u3002\u4f8b\u5982\uff0c\u5982\u679c\u5411\u9879\u76ee\u6dfb\u52a0\u65b0\u7684 NuGet \u4f9d\u8d56\u9879\uff0c\u5219\u901a\u5e38\u9700\u8981\u66f4\u65b0 Startup \u624d\u80fd\u4f7f\u7528\u5b83\u3002<\/p>\n<p>The Program class is where a lot of app con\ufb01guration takes place, but this is mostly hidden inside the Host.CreateDefaultBuilder method.<br \/>\nProgram \u7c7b\u662f\u8fdb\u884c\u5927\u91cf\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\u7684\u5730\u65b9\uff0c\u4f46\u8fd9\u4e3b\u8981\u9690\u85cf\u5728 Host.CreateDefaultBuilder \u65b9\u6cd5\u4e2d\u3002<\/p>\n<p>CreateDefaultBuilder is a static helper method that simpli\ufb01es the bootstrapping of your app by creating an IHostBuilder with some common con\ufb01guration. This is similar to the way you\u2019ve used WebApplication.CreateDefaultBuilder() throughout the book.<br \/>\nCreateDefaultBuilder \u662f\u4e00\u79cd\u9759\u6001\u5e2e\u52a9\u7a0b\u5e8f\u65b9\u6cd5\uff0c\u5b83\u901a\u8fc7\u521b\u5efa\u5177\u6709\u4e00\u4e9b\u5e38\u89c1\u914d\u7f6e\u7684 IHostBuilder \u6765\u7b80\u5316\u5e94\u7528\u7a0b\u5e8f\u7684\u542f\u52a8\u3002\u8fd9\u7c7b\u4f3c\u4e8e\u60a8\u5728\u6574\u672c\u4e66\u4e2d\u4f7f\u7528 WebApplication.CreateDefaultBuilder\uff08\uff09 \u7684\u65b9\u5f0f\u3002<\/p>\n<p><b>NOTE<\/b>  You can create custom HostBuilder instances if you want to customize the default setup and create a completely custom IHost instance, as you\u2019ll see in section 30.4. This is di\ufb00erent from WebApplicationBuilder, which always uses the same defaults.<br \/>\n\u6ce8\u610f:\u5982\u679c\u60a8\u60f3\u81ea\u5b9a\u4e49\u9ed8\u8ba4\u8bbe\u7f6e\u5e76\u521b\u5efa\u5b8c\u5168\u81ea\u5b9a\u4e49\u7684 IHost \u5b9e\u4f8b\uff0c\u5219\u53ef\u4ee5\u521b\u5efa\u81ea\u5b9a\u4e49 HostBuilder \u5b9e\u4f8b\uff0c\u5982\u7b2c 30.4 \u8282\u6240\u793a\u3002\u8fd9\u4e0e WebApplicationBuilder \u4e0d\u540c\uff0c\u540e\u8005\u59cb\u7ec8\u4f7f\u7528\u76f8\u540c\u7684\u9ed8\u8ba4\u503c\u3002<\/p>\n<p>The other helper method used by default is ConfigureWebHostDefaults. This uses a WebHostBuilder object to con\ufb01gure Kestrel to listen for HTTP requests.\u200c<br \/>\n\u9ed8\u8ba4\u60c5\u51b5\u4e0b\u4f7f\u7528\u7684\u53e6\u4e00\u4e2a\u5e2e\u52a9\u7a0b\u5e8f\u65b9\u6cd5\u662f ConfigureWebHostDefaults\u3002\u8fd9\u4f7f\u7528 WebHostBuilder \u5bf9\u8c61\u5c06 Kestrel \u914d\u7f6e\u4e3a\u4fa6\u542c HTTP \u8bf7\u6c42\u3002<\/p>\n<blockquote>\n<p>Creating services with the generic host<br \/>\n\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u521b\u5efa\u670d\u52a1<\/p>\n<p>It might seem strange that you must call ConfigureWebHostDefaults as well as CreateDefaultBuilder. Couldn\u2019t we have one method? Isn\u2019t handling HTTP requests the whole point of ASP.NET Core?<br \/>\n\u60a8\u5fc5\u987b\u8c03\u7528 ConfigureWebHostDefaults \u548c CreateDefaultBuilder \u4f3c\u4e4e\u5f88\u5947\u602a\u3002\u6211\u4eec\u4e0d\u80fd\u6709\u4e00\u79cd\u65b9\u6cd5\u5417\uff1f\u5904\u7406 HTTP \u8bf7\u6c42\u4e0d\u662f ASP.NET Core \u7684\u5168\u90e8\u610f\u4e49\u6240\u5728\u5417\uff1f<\/p>\n<p>Well, yes and no! ASP.NET Core 3.0 introduced the concept of a generic host. This allows you to use much of the same framework as ASP.NET Core applications to write non-HTTP applications. These apps can run as console apps or can be installed as Windows services (or as systemd daemons in Linux) to run background tasks or read from message queues, for example.<br \/>\n\u55ef\uff0c\u662f\u7684\uff0c\u4e5f\u4e0d\u662f\uff01ASP.NET Core 3.0 \u5f15\u5165\u4e86\u901a\u7528\u4e3b\u673a\u7684\u6982\u5ff5\u3002\u8fd9\u5141\u8bb8\u60a8\u4f7f\u7528\u4e0e ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u76f8\u540c\u7684\u6846\u67b6\u6765\u7f16\u5199\u975e HTTP \u5e94\u7528\u7a0b\u5e8f\u3002\u4f8b\u5982\uff0c\u8fd9\u4e9b\u5e94\u7528\u7a0b\u5e8f\u53ef\u4ee5\u4f5c\u4e3a\u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u8fd0\u884c\uff0c\u4e5f\u53ef\u4ee5\u4f5c\u4e3a Windows \u670d\u52a1\uff08\u6216 Linux \u4e2d\u7684 systemd \u5b88\u62a4\u7a0b\u5e8f\uff09\u5b89\u88c5\uff0c\u4ee5\u8fd0\u884c\u540e\u53f0\u4efb\u52a1\u6216\u4ece\u6d88\u606f\u961f\u5217\u4e2d\u8bfb\u53d6\u6570\u636e\u3002<\/p>\n<p>Kestrel and the web framework of ASP.NET Core build on top of the generic host functionality introduced in ASP.NET Core 3.0. To con\ufb01gure a typical ASP.NET Core app, you con\ufb01gure the generic host features that are common across all apps\u2014features such as con\ufb01guration, logging, and dependency services. For web applications, you then also con\ufb01gure the services, such as Kestrel, that are necessary to handle web requests. In chapter 34 you\u2019ll see how to build applications using the generic host to run scheduled tasks and build background services.<br \/>\nKestrel \u548c ASP.NET Core \u7684 Web \u6846\u67b6\u6784\u5efa\u5728 ASP.NET Core 3.0 \u4e2d\u5f15\u5165\u7684\u901a\u7528\u4e3b\u673a\u529f\u80fd\u4e4b\u4e0a\u3002\u8981\u914d\u7f6e\u5178\u578b\u7684 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\uff0c\u60a8\u9700\u8981\u914d\u7f6e\u6240\u6709\u5e94\u7528\u7a0b\u5e8f\u4e2d\u901a\u7528\u7684\u901a\u7528\u4e3b\u673a\u529f\u80fd\uff0c\u4f8b\u5982\u914d\u7f6e\u3001\u65e5\u5fd7\u8bb0\u5f55\u548c\u4f9d\u8d56\u9879\u670d\u52a1\u7b49\u529f\u80fd\u3002\u5bf9\u4e8e Web \u5e94\u7528\u7a0b\u5e8f\uff0c\u60a8\u8fd8\u53ef\u4ee5\u914d\u7f6e\u5904\u7406 Web \u8bf7\u6c42\u6240\u9700\u7684\u670d\u52a1\uff0c\u4f8b\u5982 Kestrel\u3002\u5728\u7b2c 34 \u7ae0\u4e2d\uff0c\u60a8\u5c06\u770b\u5230\u5982\u4f55\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u6784\u5efa\u5e94\u7528\u7a0b\u5e8f\u6765\u8fd0\u884c\u8ba1\u5212\u4efb\u52a1\u548c\u6784\u5efa\u540e\u53f0\u670d\u52a1\u3002<\/p>\n<p>Even in .NET 7, WebApplication and WebApplicationBuilder use the generic host behind the scenes. You can read more about the evolution of ASP.NET Core\u2019s bootstrapping code and the relationship between IHost and WebApplication on my blog at <a href=\"https:\/\/andrewlock.net\/exploring-dotnet-6-part-2-comparing-webapplicationbuilder-to-the-generic-host\/\">https:\/\/andrewlock.net\/exploring-dotnet-6-part-2-comparing-webapplicationbuilder-to-the-generic-host\/<\/a>.<br \/>\n\u5373\u4f7f\u5728 .NET 7 \u4e2d\uff0cWebApplication \u548c WebApplicationBuilder \u4e5f\u5728\u540e\u53f0\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u3002\u60a8\u53ef\u4ee5\u5728\u6211\u7684\u535a\u5ba2 <a href=\"https:\/\/andrewlock.net\/exploring-dotnet-6-part-2-comparing-webapplicationbuilder-to-the-generic-host\/\">https:\/\/andrewlock.net\/exploring-dotnet-6-part-2-comparing-webapplicationbuilder-to-the-generic-host\/<\/a> \u4e0a\u9605\u8bfb\u6709\u5173 ASP.NET Core \u5f15\u5bfc\u4ee3\u7801\u7684\u6f14\u53d8\u4ee5\u53ca IHost \u548c WebApplication \u4e4b\u95f4\u7684\u5173\u7cfb\u7684\u66f4\u591a\u4fe1\u606f\u3002<\/p>\n<\/blockquote>\n<p>Once the con\ufb01guration of the IHostBuilder is complete, the call to Build produces the IHost instance, but the application still isn\u2019t handling HTTP requests yet. It\u2019s the call to Run() that starts the HTTP server listening. At this point, your application is fully operational and can respond to its \ufb01rst request from a remote browser.<br \/>\nIHostBuilder \u7684\u914d\u7f6e\u5b8c\u6210\u540e\uff0c\u5bf9 Build \u7684\u8c03\u7528\u5c06\u751f\u6210 IHost \u5b9e\u4f8b\uff0c\u4f46\u5e94\u7528\u7a0b\u5e8f\u4ecd\u672a\u5904\u7406 HTTP \u8bf7\u6c42\u3002\u5bf9 Run\uff08\uff09 \u7684\u8c03\u7528\u5c06\u542f\u52a8 HTTP \u670d\u52a1\u5668\u4fa6\u542c\u3002\u6b64\u65f6\uff0c\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u5df2\u5b8c\u5168\u8fd0\u884c\uff0c\u5e76\u4e14\u53ef\u4ee5\u54cd\u5e94\u6765\u81ea\u8fdc\u7a0b\u6d4f\u89c8\u5668\u7684\u7b2c\u4e00\u4e2a\u8bf7\u6c42\u3002<\/p>\n<h2>30.3 The Startup class: Con\ufb01guring your application\u200c<\/h2>\n<p>30.3 Startup \u7c7b\uff1a\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f<\/p>\n<p>As you\u2019ve seen, Program is responsible for con\ufb01guring a lot of the infrastructure for your app, but you con\ufb01gure some of your app\u2019s behavior in Startup. The Startup class is responsible for con\ufb01guring two main aspects of your application:<br \/>\n\u5982\u4f60\u6240\u89c1\uff0cProgram \u8d1f\u8d23\u4e3a\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\u5927\u91cf\u57fa\u7840\u7ed3\u6784\uff0c\u4f46\u4f60\u5728 Startup \u4e2d\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u7684\u4e00\u4e9b\u884c\u4e3a\u3002Startup \u7c7b\u8d1f\u8d23\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u7684\u4e24\u4e2a\u4e3b\u8981\u65b9\u9762\uff1a<\/p>\n<p>\u2022  DI container service registration<br \/>\nDI \u96c6\u88c5\u7bb1\u670d\u52a1\u6ce8\u518c<\/p>\n<p>\u2022  Middleware con\ufb01guration and mapping of endpoints<br \/>\n\u4e2d\u95f4\u4ef6\u914d\u7f6e\u548c\u7aef\u70b9\u6620\u5c04<\/p>\n<p>You con\ufb01gure each of these aspects in its own method in Startup: service registration in ConfigureServices and middleware\/endpoint con\ufb01guration in Configure. A typical outline of Startup is shown in the following listing.<br \/>\n\u60a8\u53ef\u4ee5\u5728 Startup \u4e2d\u5728\u5176\u81ea\u5df1\u7684\u65b9\u6cd5\u4e2d\u914d\u7f6e\u6bcf\u4e2a\u65b9\u9762\uff1aConfigureServices \u4e2d\u7684\u670d\u52a1\u6ce8\u518c\u548c Configure \u4e2d\u7684\u4e2d\u95f4\u4ef6\/\u7ec8\u7aef\u8282\u70b9\u914d\u7f6e\u3002\u4e0b\u9762\u7684\u6e05\u5355\u663e\u793a\u4e86 Startup \u7684\u5178\u578b\u8f6e\u5ed3\u3002<\/p>\n<p>Listing 30.2 An outline of Startup.cs showing how each aspect is con\ufb01gured<br \/>\n\u6e05\u5355 30.2 Startup.cs\u6982\u8ff0\uff0c\u663e\u793a\u6bcf\u4e2a aspect \u662f\u5982\u4f55\u914d\u7f6e\u7684<\/p>\n<pre><code>public class Startup\n{\npublic void ConfigureServices(IServiceCollection services) \u2776\n{\n\/\/ method details\n}\npublic void Configure(IApplicationBuilder app) \u2777\n{\n\/\/ method details\n}\n}<\/code><\/pre>\n<p>\u2776 Configures services by registering them with the IServiceCollection<br \/>\n\u901a\u8fc7\u5728 IServiceCollection\u4e2d\u6ce8\u518c\u670d\u52a1\u6765\u914d\u7f6e\u670d\u52a1<br \/>\n\u2777 Configures the middleware pipeline for handling HTTP requests<br \/>\n\u914d\u7f6e\u7528\u4e8e\u5904\u7406 HTTP \u8bf7\u6c42\u7684\u4e2d\u95f4\u4ef6\u7ba1\u9053<\/p>\n<p>The IHostBuilder created in Program automatically calls ConfigureServices and then Configure, as shown in \ufb01gure 30.2. Each call con\ufb01gures a di\ufb00erent part of your application, making it available for subsequent method calls. Any services registered in the ConfigureServices method are available to the Configure method. Once con\ufb01guration is complete, you create an IHost by calling Build() on the IHostBuilder.<br \/>\n\u5728 Program \u4e2d\u521b\u5efa\u7684 IHostBuilder \u4f1a\u81ea\u52a8\u8c03\u7528 ConfigureServices\uff0c\u7136\u540e\u8c03\u7528 Configure\uff0c\u5982\u56fe 30.2 \u6240\u793a\u3002\u6bcf\u6b21\u8c03\u7528\u90fd\u4f1a\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u7684\u4e0d\u540c\u90e8\u5206\uff0c\u4f7f\u5176\u53ef\u7528\u4e8e\u540e\u7eed\u65b9\u6cd5\u8c03\u7528\u3002\u5728 ConfigureServices \u65b9\u6cd5\u4e2d\u6ce8\u518c\u7684\u4efb\u4f55\u670d\u52a1\u90fd\u53ef\u7528\u4e8e Configure \u65b9\u6cd5\u3002\u914d\u7f6e\u5b8c\u6210\u540e\uff0c\u60a8\u53ef\u4ee5\u901a\u8fc7\u5728 IHostBuilder \u4e0a\u8c03\u7528 Build\uff08\uff09 \u6765\u521b\u5efa IHost\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/images\/aspnetcoreinaction\/3002.jpg\" alt=\"alt text\" \/><\/p>\n<p>Figure 30.2 The IHostBuilder is created in Program.cs and calls methods on Startup to con\ufb01gure the application\u2019s services and middleware pipeline. Once con\ufb01guration is complete, the IHost is created by calling Build() on the IHostBuilder.<br \/>\n\u56fe 30.2 IHostBuilder \u662f\u5728 Program.cs\u4e2d\u521b\u5efa\u7684\uff0c\u5e76\u5728\u542f\u52a8\u65f6\u8c03\u7528\u65b9\u6cd5\u6765\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u7684\u670d\u52a1\u548c\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002\u914d\u7f6e\u5b8c\u6210\u540e\uff0c\u901a\u8fc7\u5728 IHostBuilder \u4e0a\u8c03\u7528 Build\uff08\uff09 \u6765\u521b\u5efa IHost\u3002<\/p>\n<p>An interesting point about the Startup class is that it doesn\u2019t implement an interface as such. Instead, the methods are invoked by using re\ufb02ection to \ufb01nd methods with the prede\ufb01ned names of Configure and ConfigureServices. This makes the class more \ufb02exible and enables you to modify the signature of the Configure method to inject any services you registered in ConfigureServices using DI.<br \/>\n\u5173\u4e8e Startup \u7c7b\u7684\u4e00\u4e2a\u6709\u8da3\u4e4b\u5904\u5728\u4e8e\uff0c\u5b83\u6ca1\u6709\u5b9e\u73b0\u8fd9\u6837\u7684\u63a5\u53e3\u3002\u76f8\u53cd\uff0c\u901a\u8fc7\u4f7f\u7528\u53cd\u5c04\u6765\u67e5\u627e\u5177\u6709\u9884\u5b9a\u4e49\u540d\u79f0 Configure \u548c ConfigureServices \u7684\u65b9\u6cd5\uff0c\u4ece\u800c\u8c03\u7528\u8fd9\u4e9b\u65b9\u6cd5\u3002\u8fd9\u4f7f\u5f97\u8be5\u7c7b\u66f4\u52a0\u7075\u6d3b\uff0c\u5e76\u4f7f\u60a8\u80fd\u591f\u4fee\u6539 Configure \u65b9\u6cd5\u7684\u7b7e\u540d\uff0c\u4ee5\u6ce8\u5165\u60a8\u4f7f\u7528 DI \u5728 ConfigureServices \u4e2d\u6ce8\u518c\u7684\u4efb\u4f55\u670d\u52a1\u3002<\/p>\n<p><b>TIP<\/b>  If you\u2019re not a fan of the \ufb02exible re\ufb02ection approach, you can implement the IStartup interface or derive from the StartupBase class, which provide the method signatures shown previously in listing 30.2. If you take this approach, you won\u2019t be able to use DI to inject services into the Configure() method.\u200c\u200c<br \/>\n\u63d0\u793a:\u5982\u679c\u60a8\u4e0d\u559c\u6b22\u7075\u6d3b\u7684\u53cd\u5c04\u65b9\u6cd5\uff0c\u5219\u53ef\u4ee5\u5b9e\u73b0 IStartup \u63a5\u53e3\u6216\u4ece StartupBase \u7c7b\u6d3e\u751f\uff0c\u8fd9\u4e9b\u7c7b\u63d0\u4f9b\u524d\u9762\u6e05\u5355 30.2 \u4e2d\u6240\u793a\u7684\u65b9\u6cd5\u7b7e\u540d\u3002\u5982\u679c\u91c7\u7528\u6b64\u65b9\u6cd5\uff0c\u5219\u65e0\u6cd5\u4f7f\u7528 DI \u5c06\u670d\u52a1\u6ce8\u5165 Configure\uff08\uff09 \u65b9\u6cd5\u3002<\/p>\n<p>ConfigureServices is where you add all your required and custom services to the DI container, exactly as you do with WebApplicationBuilder.Services in a typical .NET 7 ASP.NET Core app. The following listing shows how you might con\ufb01gure all the services for the Razor Pages recipe app you\u2019ve seen throughout this book. This listing also shows how you can access the IConfiguration for your app: by injecting into the Startup constructor. You\u2019ll see how to customize your app\u2019s con\ufb01guration in section 30.4.<br \/>\n\u5728 ConfigureServices \u4e2d\uff0c\u60a8\u53ef\u4ee5\u5c06\u6240\u6709\u5fc5\u9700\u7684\u81ea\u5b9a\u4e49\u670d\u52a1\u6dfb\u52a0\u5230 DI \u5bb9\u5668\u4e2d\uff0c\u5c31\u50cf\u5728\u5178\u578b\u7684 .NET 7 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u4e2d\u4f7f\u7528 WebApplicationBuilder.Services \u4e00\u6837\u3002\u4ee5\u4e0b\u6e05\u5355\u663e\u793a\u4e86\u5982\u4f55\u4e3a\u672c\u4e66\u4e2d\u4ecb\u7ecd\u7684 Razor Pages \u914d\u65b9\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\u6240\u6709\u670d\u52a1\u3002\u6b64\u6e05\u5355\u8fd8\u663e\u793a\u4e86\u5982\u4f55\u8bbf\u95ee\u5e94\u7528\u7a0b\u5e8f\u7684 IConfiguration\uff1a\u901a\u8fc7\u6ce8\u5165 Startup \u6784\u9020\u51fd\u6570\u3002\u60a8\u5c06\u5728 Section 30.4 \u4e2d\u770b\u5230\u5982\u4f55\u81ea\u5b9a\u4e49\u5e94\u7528\u7a0b\u5e8f\u7684\u914d\u7f6e\u3002<\/p>\n<p>Listing 30.3 Registering services with DI in ConfigureServices<br \/>\n\u6e05\u5355 30.3 \u5728 ConfigureServices \u4e2d\u5411 DI \u6ce8\u518c\u670d\u52a1<\/p>\n<pre><code>public class Startup\n{\npublic IConfiguration Configuration { get; } \u2776\npublic Startup(IConfiguration configuration) \u2776\n{\nConfiguration = configuration;\n}\npublic void ConfigureServices(IServiceCollection services) \u2777\n{\nvar conn = Configuration.GetConnectionString(&quot;DefaultConnection&quot;);\nservices.AddDbContext&lt;AppDbContext&gt;(options =&gt; \u2778\noptions.UseSqlite(conn)); \u2778\nservices.AddDefaultIdentity&lt;ApplicationUser&gt;(options =&gt; \u2778\noptions.SignIn.RequireConfirmedAccount = true) \u2778\n.AddEntityFrameworkStores&lt;AppDbContext&gt;(); \u2778\nservices.AddScoped&lt;RecipeService&gt;(); \u2779\nservices.AddRazorPages(); \u277a\nservices.AddScoped&lt;IAuthorizationHandler, IsRecipeOwnerHandler&gt;();\nservices.AddAuthorizationBuilder()\n.AddPolicy(&quot;CanManageRecipe&quot;,\np =&gt; p.AddRequirements(new IsRecipeOwnerRequirement()));\n}\npublic void Configure(IApplicationBuilder app) =&gt; { \/* Not shown *\/ }\n}<\/code><\/pre>\n<p>\u2776 The IConfiguration for the app is injected into the constructor.<br \/>\n\u5e94\u7528\u7a0b\u5e8f\u7684 IConfiguration \u88ab\u6ce8\u5165\u5230\u6784\u9020\u51fd\u6570\u4e2d\u3002<\/p>\n<p>\u2777 You must register your services against the provided IServiceCollection.<br \/>\n\u60a8\u5fc5\u987b\u9488\u5bf9\u63d0\u4f9b\u7684 IServiceCollection \u6ce8\u518c\u60a8\u7684\u670d\u52a1\u3002<\/p>\n<p>\u2778 Registers all the EF Core and ASP.NET Core Identity services<br \/>\n\u6ce8\u518c\u6240\u6709 EF Core \u548c ASP.NET Core Identity \u670d\u52a1<\/p>\n<p>\u2779 Registers the custom service implementations<br \/>\n\u6ce8\u518c\u81ea\u5b9a\u4e49\u670d\u52a1\u5b9e\u73b0<\/p>\n<p>\u277a Registers the framework services<br \/>\n\u6ce8\u518c\u6846\u67b6\u670d\u52a1<\/p>\n<p>After con\ufb01guring all your services, you need to set up your middleware pipeline and map your endpoints. The process is similar to con\ufb01guring your middleware pipeline using WebApplication:<br \/>\n\u914d\u7f6e\u5b8c\u6240\u6709\u670d\u52a1\u540e\uff0c\u60a8\u9700\u8981\u8bbe\u7f6e\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5e76\u6620\u5c04\u7ec8\u7aef\u8282\u70b9\u3002\u8be5\u8fc7\u7a0b\u7c7b\u4f3c\u4e8e\u4f7f\u7528 WebApplication \u914d\u7f6e\u4e2d\u95f4\u4ef6\u7ba1\u9053\uff1a<\/p>\n<p>\u2022  You add middleware to the pipeline by calling Use<em> extension methods on an IApplicationBuilder instance.<br \/>\n\u901a\u8fc7\u5728 IApplicationBuilder \u5b9e\u4f8b\u4e0a\u8c03\u7528 Use<\/em> \u6269\u5c55\u65b9\u6cd5\uff0c\u5c06\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u7ba1\u9053\u4e2d\u3002<\/p>\n<p>\u2022  The order in which you add the middleware to the pipeline is important and de\ufb01nes the \ufb01nal pipeline order.<br \/>\n\u5c06\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u7ba1\u9053\u7684\u987a\u5e8f\u975e\u5e38\u91cd\u8981\uff0c\u5b83\u5b9a\u4e49\u4e86\u6700\u7ec8\u7684\u7ba1\u9053\u987a\u5e8f\u3002<\/p>\n<p>\u2022  You can add middleware conditionally based on the environment.<br \/>\n\u60a8\u53ef\u4ee5\u6839\u636e\u73af\u5883\u6709\u6761\u4ef6\u5730\u6dfb\u52a0\u4e2d\u95f4\u4ef6\u3002<\/p>\n<p>However, there are some important di\ufb00erences between the WebApplication approach you\u2019ve seen so far and the Startup approach:<br \/>\n\u4f46\u662f\uff0c\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u60a8\u770b\u5230\u7684 WebApplication \u65b9\u6cd5\u4e0e Startup \u65b9\u6cd5\u4e4b\u95f4\u5b58\u5728\u4e00\u4e9b\u91cd\u8981\u5dee\u5f02\uff1a<\/p>\n<p>\u2022  The IWebHostEnvironment for your app is exposed directly on WebApplication.Environment. To access this information inside Startup, you must inject it into the constructor or the Configure method using DI.<br \/>\n\u5e94\u7528\u7a0b\u5e8f\u7684 IWebHostEnvironment \u76f4\u63a5\u5728 WebApplication.Environment \u4e0a\u516c\u5f00\u3002\u8981\u5728 Startup \u4e2d\u8bbf\u95ee\u6b64\u4fe1\u606f\uff0c\u60a8\u5fc5\u987b\u4f7f\u7528 DI \u5c06\u5176\u6ce8\u5165\u5230\u6784\u9020\u51fd\u6570\u6216 Configure \u65b9\u6cd5\u4e2d\u3002<\/p>\n<p>\u2022  As you saw in chapter 4, WebApplication automatically adds a lot of middleware to your pipeline, such as routing middleware, endpoint middleware, and the authentication middleware. You must add this middleware manually when using the Startup approach.<br \/>\n\u5982\u7b2c 4 \u7ae0\u6240\u793a\uff0cWebApplication \u4f1a\u81ea\u52a8\u5411\u7ba1\u9053\u4e2d\u6dfb\u52a0\u5927\u91cf\u4e2d\u95f4\u4ef6\uff0c\u4f8b\u5982\u8def\u7531\u4e2d\u95f4\u4ef6\u3001\u7aef\u70b9\u4e2d\u95f4\u4ef6\u548c\u8eab\u4efd\u9a8c\u8bc1\u4e2d\u95f4\u4ef6\u3002\u4f7f\u7528 Startup \u65b9\u6cd5\u65f6\uff0c\u5fc5\u987b\u624b\u52a8\u6dfb\u52a0\u6b64\u4e2d\u95f4\u4ef6\u3002<\/p>\n<p>\u2022  WebApplication implements both IApplicationBuilder and IEndpointRouteBuilder, so you can add endpoints directly to WebApplication, by calling MapGet() or MapRazorPages(), for example.When using the Startup approach, you must call UseEndpoints() and map all your endpoints in a lambda method instead.<br \/>\nWebApplication \u540c\u65f6\u5b9e\u73b0 IApplicationBuilder \u548c IEndpointRouteBuilder\uff0c\u56e0\u6b64\u60a8\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528 MapGet\uff08\uff09 \u6216 MapRazorPages\uff08\uff09 \u7b49\u65b9\u5f0f\u5c06\u7aef\u70b9\u76f4\u63a5\u6dfb\u52a0\u5230 WebApplication\u3002\u4f7f\u7528 Startup \u65b9\u6cd5\u65f6\uff0c\u60a8\u5fc5\u987b\u8c03\u7528 UseEndpoints\uff08\uff09 \u5e76\u6539\u4e3a\u5728 lambda \u65b9\u6cd5\u4e2d\u6620\u5c04\u6240\u6709\u7ec8\u7aef\u8282\u70b9\u3002<\/p>\n<p>\u2022  The Configure method is not async, so it\u2019s cumbersome to do async tasks. By contrast, when using WebApplication, you\u2019re free to use async methods between any of your general bootstrapping code.<br \/>\nConfigure \u65b9\u6cd5\u4e0d\u662f\u5f02\u6b65\u7684\uff0c\u56e0\u6b64\u6267\u884c\u5f02\u6b65\u4efb\u52a1\u5f88\u9ebb\u70e6\u3002\u76f8\u6bd4\u4e4b\u4e0b\uff0c\u5728\u4f7f\u7528 WebApplication \u65f6\uff0c\u60a8\u53ef\u4ee5\u5728\u4efb\u4f55\u5e38\u89c4\u5f15\u5bfc\u4ee3\u7801\u4e4b\u95f4\u81ea\u7531\u4f7f\u7528\u5f02\u6b65\u65b9\u6cd5\u3002<\/p>\n<p>Despite these caveats, in many cases your Startup.Configure method will look almost identical to the way you con\ufb01gure the pipeline on WebApplication. The following listing shows how the Configure() method for the Razor Pages recipe app might look.\u200c\u5c3d\u7ba1\u6709\u8fd9\u4e9b\u6ce8\u610f\u4e8b\u9879\uff0c\u4f46\u5728\u8bb8\u591a\u60c5\u51b5\u4e0b\uff0c\u60a8\u7684 Startup.Configure \u65b9\u6cd5\u770b\u8d77\u6765\u4e0e\u60a8\u5728 WebApplication \u4e0a\u914d\u7f6e\u7ba1\u9053\u7684\u65b9\u5f0f\u51e0\u4e4e\u76f8\u540c\u3002\u4ee5\u4e0b\u6e05\u5355\u663e\u793a\u4e86 Razor Pages \u914d\u65b9\u5e94\u7528\u7684 Configure\uff08\uff09 \u65b9\u6cd5\u7684\u5916\u89c2\u3002<\/p>\n<p>Listing 30.4 Startup.Con\ufb01gure() for a Razor Pages application<br \/>\n\u5217\u8868 30.4 Razor Pages \u5e94\u7528\u7a0b\u5e8f\u7684 Startup.Configure\uff08\uff09<\/p>\n<pre><code>public class Startup\n{\npublic void Configure(\nIApplicationBuilder app, \u2776\nIWebHostEnvironment env) \u2777\n{\nif (env.IsDevelopment()) \u2778\n{\napp.UseDeveloperExceptionPage(); \u2779\n}\nelse\n{\napp.UseExceptionHandler(&quot;\/Error&quot;);\napp.UseHsts();\n}\napp.UseHttpsRedirection();\napp.UseStaticFiles();\napp.UseRouting(); \u277a\napp.UseAuthentication();\napp.UseAuthorization(); \u277b\napp.UseEndpoints(endpoints =&gt; \u277c\n{\nendpoints.MapRazorPages(); \u277d\n});\n}\n}<\/code><\/pre>\n<p>\u2776 IApplicationBuilder is used to build the middleware pipeline.<br \/>\nIApplicationBuilder \u7528\u4e8e\u6784\u5efa\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002<\/p>\n<p>\u2777 Other services can be accepted as parameters.<br \/>\n\u5176\u4ed6\u670d\u52a1\u53ef\u4ee5\u4f5c\u4e3a\u53c2\u6570\u63a5\u53d7\u3002<\/p>\n<p>\u2778 Different behavior when in development or production<br \/>\n\u5f00\u53d1\u6216\u751f\u4ea7\u65f6\u7684\u884c\u4e3a\u4e0d\u540c<\/p>\n<p>\u2779 WebApplication adds this automatically. You must explicitly add it when using Startup.<br \/>\nWebApplication \u4f1a\u81ea\u52a8\u6dfb\u52a0\u6b64\u5185\u5bb9\u3002\u60a8\u5fc5\u987b\u5728\u4f7f\u7528Startup \u65f6\u663e\u5f0f\u6dfb\u52a0\u5b83\u3002<\/p>\n<p>\u277a Similarly, you must explicitly call UseRouting.<br \/>\n\u540c\u6837\uff0c\u60a8\u5fc5\u987b\u663e\u5f0f\u8c03\u7528 UseRouting\u3002<\/p>\n<p>\u277b Must always be placed between the call to UseRouting and UseEndpoints<br \/>\n\u5fc5\u987b\u59cb\u7ec8\u653e\u7f6e\u5728\u5bf9 UseRouting \u548c UseEndpoints\u7684\u8c03\u7528\u4e4b\u95f4<\/p>\n<p>\u277c Adds the endpoint middleware, which executes the endpoints<br \/>\n\u6dfb\u52a0\u6267\u884c\u7ec8\u7ed3\u70b9\u7684\u7ec8\u7ed3\u70b9\u4e2d\u95f4\u4ef6<\/p>\n<p>\u277d Maps the Razor Pages endpoints<br \/>\n\u6620\u5c04 Razor Pages \u7ec8\u7ed3\u70b9<\/p>\n<p>In this example, the IWebHostEnvironment object is injected into the Configure() method using DI so that you can con\ufb01gure the middleware pipeline di\ufb00erently in development and production. In this case, we add the DeveloperExceptionPageMiddleware to the pipeline when we\u2019re running in development.\u200c<br \/>\n\u5728\u6b64\u793a\u4f8b\u4e2d\uff0c\u4f7f\u7528 DI \u5c06 IWebHostEnvironment \u5bf9\u8c61\u6ce8\u5165\u5230 Configure\uff08\uff09 \u65b9\u6cd5\u4e2d\uff0c\u4ee5\u4fbf\u60a8\u53ef\u4ee5\u5728\u5f00\u53d1\u548c\u751f\u4ea7\u4e2d\u4ee5\u4e0d\u540c\u7684\u65b9\u5f0f\u914d\u7f6e\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002\u5728\u672c\u4f8b\u4e2d\uff0c\u6211\u4eec\u5728\u5f00\u53d1\u4e2d\u8fd0\u884c\u65f6\u5c06 DeveloperExceptionPageMiddleware \u6dfb\u52a0\u5230\u7ba1\u9053\u4e2d\u3002<\/p>\n<p><b>NOTE<\/b>  Remember that WebApplication adds this middleware automatically, but with Startup you must add it manually. The same goes for all the other automatically added middleware.<br \/>\n\u6ce8\u610f:\u8bf7\u8bb0\u4f4f\uff0cWebApplication \u4f1a\u81ea\u52a8\u6dfb\u52a0\u6b64\u4e2d\u95f4\u4ef6\uff0c\u4f46\u4f7f\u7528 Startup \u65f6\uff0c\u60a8\u5fc5\u987b\u624b\u52a8\u6dfb\u52a0\u5b83\u3002\u6240\u6709\u5176\u4ed6\u81ea\u52a8\u6dfb\u52a0\u7684 middleware \u4e5f\u662f\u5982\u6b64\u3002<\/p>\n<p>After adding all the middleware to the pipeline, you come to the UseEndpoints() call, which adds the EndpointMiddleware to the pipeline. When you use WebApplication, you rarely need to call this, as WebApplication automatically adds it at the end of the pipeline, but when you use Startup, you should add it at the end of your pipeline.<br \/>\n\u5c06\u6240\u6709\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u7ba1\u9053\u540e\uff0c\u60a8\u5c06\u8f6c\u5230 UseEndpoints\uff08\uff09 \u8c03\u7528\uff0c\u8be5\u8c03\u7528\u5c06 EndpointMiddleware \u6dfb\u52a0\u5230\u7ba1\u9053\u4e2d\u3002\u5f53\u60a8\u4f7f\u7528 WebApplication \u65f6\uff0c\u60a8\u5f88\u5c11\u9700\u8981\u8c03\u7528\u5b83\uff0c\u56e0\u4e3a WebApplication \u4f1a\u81ea\u52a8\u5c06\u5176\u6dfb\u52a0\u5230\u7ba1\u9053\u7684\u672b\u5c3e\uff0c\u4f46\u662f\u5f53\u60a8\u4f7f\u7528 Startup \u65f6\uff0c\u60a8\u5e94\u8be5\u5c06\u5176\u6dfb\u52a0\u5230\u7ba1\u9053\u7684\u672b\u5c3e\u3002<\/p>\n<p>Note as well that the call to UseEndpoints() is where you de\ufb01ne all the endpoints in your application. Whether they\u2019re Razor Pages, Model-View-Controller (MVC) controllers, or minimal APIs, you must register them in the UseEndpoints() lambda.<br \/>\n\u53e6\u8bf7\u6ce8\u610f\uff0c\u5bf9 UseEndpoints\uff08\uff09 \u7684\u8c03\u7528\u662f\u5b9a\u4e49\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u6240\u6709\u7ec8\u7ed3\u70b9\u7684\u4f4d\u7f6e\u3002\u65e0\u8bba\u5b83\u4eec\u662f Razor Pages\u3001Model-View-Controller \uff08MVC\uff09 \u63a7\u5236\u5668\u8fd8\u662f\u6700\u5c0f API\uff0c\u90fd\u5fc5\u987b\u5728 UseEndpoints\uff08\uff09 lambda \u4e2d\u6ce8\u518c\u5b83\u4eec\u3002<\/p>\n<p><b>NOTE<\/b>  Endpoints must be registered inside the call to UseEndpoints() using the IEndpointRouteBuilder instance from the lambda method.<br \/>\n\u6ce8\u610f:\u5fc5\u987b\u4f7f\u7528 lambda \u65b9\u6cd5\u4e2d\u7684 IEndpointRouteBuilder \u5b9e\u4f8b\u5728\u5bf9 UseEndpoints\uff08\uff09 \u7684\u8c03\u7528\u4e2d\u6ce8\u518c\u7ec8\u7aef\u8282\u70b9\u3002<\/p>\n<p>Other than the noted di\ufb00erences, moving your service, middleware, and endpoint con\ufb01guration between a Startup-based approach and WebApplication should be relatively simple, which may lead you to wonder whether there\u2019s any good reason to choose the Startup approach over WebApplication. As always, the answer is \u201cIt depends,\u201d but one possible reason is so that you can customize your IHostBuilder.<br \/>\n\u9664\u4e86\u4e0a\u8ff0\u5dee\u5f02\u4e4b\u5916\uff0c\u5728\u57fa\u4e8e Startup \u7684\u65b9\u6cd5\u548c WebApplication \u4e4b\u95f4\u79fb\u52a8\u670d\u52a1\u3001\u4e2d\u95f4\u4ef6\u548c\u7aef\u70b9\u914d\u7f6e\u5e94\u8be5\u76f8\u5bf9\u7b80\u5355\uff0c\u8fd9\u53ef\u80fd\u4f1a\u8ba9\u60a8\u6000\u7591\u662f\u5426\u6709\u4efb\u4f55\u5145\u5206\u7684\u7406\u7531\u9009\u62e9 Startup \u65b9\u6cd5\u800c\u4e0d\u662f WebApplication\u3002\u4e0e\u5f80\u5e38\u4e00\u6837\uff0c\u7b54\u6848\u662f\u201c\u89c6\u60c5\u51b5\u800c\u5b9a\u201d\uff0c\u4f46\u4e00\u4e2a\u53ef\u80fd\u7684\u539f\u56e0\u662f\u60a8\u53ef\u4ee5\u81ea\u5b9a\u4e49 IHostBuilder\u3002<\/p>\n<h2>30.4 Creating a custom IHostBuilder\u200c<\/h2>\n<p>30.4 \u521b\u5efa\u81ea\u5b9a\u4e49 IHostBuilder<\/p>\n<p>As you saw in section 30.2, the default way to work with a Startup class in ASP.NET Core is to use the Host.CreateDefaultBuilder() method. This opinionated helper method sets up many defaults for your app. It is analogous to the WebApplication\u200c.CreateBuilder() method in that way.<br \/>\n\u5982\u60a8\u5728\u7b2c 30.2 \u8282\u4e2d\u6240\u89c1\uff0c\u5728 ASP.NET Core \u4e2d\u4f7f\u7528 Startup \u7c7b\u7684\u9ed8\u8ba4\u65b9\u6cd5\u662f\u4f7f\u7528 Host.CreateDefaultBuilder\uff08\uff09 \u65b9\u6cd5\u3002\u8fd9\u4e2a\u56fa\u6267\u5df1\u89c1\u7684 helper \u65b9\u6cd5\u4e3a\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u8bbe\u7f6e\u4e86\u8bb8\u591a\u9ed8\u8ba4\u503c\u3002\u5b83\u7c7b\u4f3c\u4e8e WebApplication \u3002CreateBuilder\uff08\uff09 \u65b9\u6cd5\u3002<\/p>\n<p>However, you don\u2019t have to use the CreateDefaultBuilder method to create an IHostBuilder instance: you can directly create a HostBuilder instance and customize it from scratch if you prefer. Before you start doing that, though, it\u2019s worth seeing some of the things the CreateDefaultBuilder method gives you and what they\u2019re used for. You may then consider customizing the default HostBuilder instance instead of creating a completely bespoke instance.\u200c<br \/>\n\u4f46\u662f\uff0c\u60a8\u4e0d\u5fc5\u4f7f\u7528 CreateDefaultBuilder \u65b9\u6cd5\u521b\u5efa IHostBuilder \u5b9e\u4f8b\uff1a\u5982\u679c\u60a8\u613f\u610f\uff0c\u53ef\u4ee5\u76f4\u63a5\u521b\u5efa HostBuilder \u5b9e\u4f8b\u5e76\u4ece\u5934\u5f00\u59cb\u81ea\u5b9a\u4e49\u5b83\u3002\u4e0d\u8fc7\uff0c\u5728\u5f00\u59cb\u6267\u884c\u6b64\u4f5c\u4e4b\u524d\uff0c\u6709\u5fc5\u8981\u4e86\u89e3 CreateDefaultBuilder \u65b9\u6cd5\u4e3a\u60a8\u63d0\u4f9b\u7684\u4e00\u4e9b\u529f\u80fd\u4ee5\u53ca\u5b83\u4eec\u7684\u7528\u9014\u3002\u7136\u540e\uff0c\u60a8\u53ef\u4ee5\u8003\u8651\u81ea\u5b9a\u4e49\u9ed8\u8ba4\u7684 HostBuilder \u5b9e\u4f8b\uff0c\u800c\u4e0d\u662f\u521b\u5efa\u5b8c\u5168\u5b9a\u5236\u7684\u5b9e\u4f8b\u3002<\/p>\n<p><b>NOTE<\/b>  You can use Host.CreateDefaultBuilder() in .NET 7 even if you\u2019re not using ASP.NET Core by installing the Microsoft.Extensions.Hosting package. You\u2019ll learn how to create non-HTTP applications using the generic host in chapter 34.<br \/>\n\u6ce8\u610f:\u5373\u4f7f\u60a8\u6ca1\u6709\u4f7f\u7528 ASP.NET Core\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7\u5b89\u88c5 Microsoft.Extensions.Hosting \u5305\u5728 .NET 7 \u4e2d\u4f7f\u7528 Host.CreateDefaultBuilder\uff08\uff09\u3002\u60a8\u5c06\u5728\u7b2c 34 \u7ae0\u4e2d\u5b66\u4e60\u5982\u4f55\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u521b\u5efa\u975e HTTP \u5e94\u7528\u7a0b\u5e8f\u3002<\/p>\n<p>The defaults chosen by CreateDefaultBuilder are ideal when you\u2019re initially setting up an app, but as your application grows, you may \ufb01nd you need to break it apart and tinker with some of the internals. The following listing shows a rough overview of the CreateDefaultBuilder method, so you can see how the HostBuilder is constructed. It\u2019s not exhaustive or complete, but it should give you an idea of the amount of work the CreateDefaultBuilder method does for you!<br \/>\nCreateDefaultBuilder \u9009\u62e9\u7684\u9ed8\u8ba4\u503c\u5728\u60a8\u6700\u521d\u8bbe\u7f6e\u5e94\u7528\u7a0b\u5e8f\u65f6\u662f\u7406\u60f3\u7684\uff0c\u4f46\u968f\u7740\u5e94\u7528\u7a0b\u5e8f\u7684\u589e\u957f\uff0c\u60a8\u53ef\u80fd\u4f1a\u53d1\u73b0\u9700\u8981\u5c06\u5176\u5206\u89e3\u5e76\u4fee\u6539\u4e00\u4e9b\u5185\u90e8\u7ed3\u6784\u3002\u4e0b\u9762\u7684\u6e05\u5355\u663e\u793a\u4e86 CreateDefaultBuilder \u65b9\u6cd5\u7684\u7c97\u7565\u6982\u8ff0\uff0c\u56e0\u6b64\u4f60\u53ef\u4ee5\u770b\u5230 HostBuilder \u662f\u5982\u4f55\u6784\u9020\u7684\u3002\u5b83\u5e76\u4e0d\u8be6\u5c3d\u6216\u5b8c\u6574\uff0c\u4f46\u5b83\u5e94\u8be5\u8ba9\u60a8\u4e86\u89e3 CreateDefaultBuilder \u65b9\u6cd5\u4e3a\u60a8\u5b8c\u6210\u7684\u5de5\u4f5c\u91cf\uff01<\/p>\n<p>Listing 30.5 The Host.CreateDefaultBuilder method<br \/>\n\u6e05\u5355 30.5 Host.CreateDefaultBuilder \u65b9\u6cd5<\/p>\n<pre><code>public static IHostBuilder CreateDefaultBuilder(string[] args)\n{\nvar builder = new HostBuilder() \u2776\n.UseContentRoot(Directory.GetCurrentDirectory()) \u2777\n.ConfigureHostConfiguration(IConfigurationBuilder config =&gt; \u2778\n{ \u2778\nconfig.AddEnvironmentVariables(&quot;DOTNET_&quot;); \u2778\nconfig.AddCommandLine(args); \u2778\n}) \u2778\n.ConfigureAppConfiguration((hostingContext, config) =&gt; \u2779\n{ \u2779\nIHostEnvironment env = hostingContext.HostingEnvironment; \u2779\nconfig \u2779\n.AddJsonFile(&quot;appsettings.json&quot;) \u2779\n.AddJsonFile($&quot;appsettings.{env.EnvironmentName}.json&quot;); \u2779\nif (env.IsDevelopment()) \u2779\n{ \u2779\nconfig.AddUserSecrets(); \u2779\n} \u2779\nconfig \u2779\n.AddEnvironmentVariables() \u2779\n.AddCommandLine(); \u2779\n}) \u2779\n.ConfigureLogging((hostingContext, logging) =&gt; \u277a\n{ \u277a\nlogging.AddConfiguration( \u277a\nhostingContext.Configuration.GetSection(&quot;Logging&quot;)); \u277a\nlogging.AddConsole(); \u277a\nlogging.AddDebug(); \u277a\nlogging.AddEventSourceLogger(); \u277a\nlogging.AddEventLog(); \u277a\n}) \u277a\n.UseDefaultServiceProvider((context, options) =&gt; \u277b\n{ \u277b\nvar isDevelopment = context.HostingEnvironment \u277b\n.IsDevelopment(); \u277b\noptions.ValidateScopes = isDevelopment; \u277b\noptions.ValidateOnBuild = isDevelopment; \u277b\n}); \u277b\nreturn builder; \u277c\n}<\/code><\/pre>\n<p>\u2776 Creates an instance of HostBuilder<br \/>\n\u521b\u5efa HostBuilder\u7684\u5b9e\u4f8b<\/p>\n<p>\u2777 The content root defines the directory where configuration files can be found.<br \/>\n\u5185\u5bb9\u6839\u5b9a\u4e49\u53ef\u4ee5\u627e\u5230\u914d\u7f6e\u6587\u4ef6\u7684\u76ee\u5f55\u3002<\/p>\n<p>\u2778 Configures hosting settings such as determining the hosting environment<br \/>\n\u914d\u7f6e\u6258\u7ba1\u8bbe\u7f6e\uff0c\u4f8b\u5982\u786e\u5b9a\u6258\u7ba1\u73af\u5883<\/p>\n<p>\u2779 Configures application settings<br \/>\n\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u8bbe\u7f6e<\/p>\n<p>\u277a Sets up the logging infrastructure<br \/>\n\u8bbe\u7f6e\u65e5\u5fd7\u8bb0\u5f55\u57fa\u7840\u8bbe\u65bd<\/p>\n<p>\u277b Configures the DI container, optionally enabling verification settings<br \/>\n\u914d\u7f6e DI \u5bb9\u5668\uff0c\u53ef\u9009\u62e9\u542f\u7528\u9a8c\u8bc1\u8bbe\u7f6e<\/p>\n<p>\u277c Returns HostBuilder for further configuration by calling extra methods before calling Build()<br \/>\n\u901a\u8fc7\u5728\u8c03\u7528 Build\uff08\uff09 \u4e4b\u524d\u8c03\u7528\u989d\u5916\u7684\u65b9\u6cd5\u8fd4\u56de HostBuilder \u4ee5\u8fdb\u884c\u8fdb\u4e00\u6b65\u914d\u7f6e<\/p>\n<p>The \ufb01rst method called on HostBuilder is UseContentRoot(). This tells the application in which directory it can \ufb01nd any con\ufb01guration or Razor \ufb01les it needs later. This is typically the folder in which the application is running, hence the call to GetCurrentDirectory.<br \/>\n\u5728 HostBuilder \u4e0a\u8c03\u7528\u7684\u7b2c\u4e00\u4e2a\u65b9\u6cd5\u662f UseContentRoot\uff08\uff09\u3002\u8fd9\u4f1a\u544a\u77e5\u5e94\u7528\u7a0b\u5e8f\u7a0d\u540e\u53ef\u4ee5\u5728\u54ea\u4e2a\u76ee\u5f55\u4e2d\u627e\u5230\u6240\u9700\u7684\u4efb\u4f55\u914d\u7f6e\u6216 Razor \u6587\u4ef6\u3002\u8fd9\u901a\u5e38\u662f\u8fd0\u884c\u5e94\u7528\u7a0b\u5e8f\u7684\u6587\u4ef6\u5939\uff0c\u56e0\u6b64\u8c03\u7528 GetCurrentDirectory\u3002<\/p>\n<p><b>TIP<\/b>  Remember that ContentRoot is not where you store static \ufb01les that the browser can access directly. That\u2019s the WebRoot, typically wwwroot.<br \/>\n\u63d0\u793a:\u8bf7\u8bb0\u4f4f\uff0cContentRoot \u4e0d\u662f\u5b58\u50a8\u6d4f\u89c8\u5668\u53ef\u4ee5\u76f4\u63a5\u8bbf\u95ee\u7684\u9759\u6001\u6587\u4ef6\u7684\u4f4d\u7f6e\u3002\u8fd9\u5c31\u662f WebRoot\uff0c\u901a\u5e38\u662f wwwroot\u3002<\/p>\n<p>The ConfigureHostingConfiguration() method is where your application determines which HostingEnvironment it\u2019s currently running in. The framework looks for environment variables that start with &quot;DOTNET_&quot; (such as the DOTNET<em>ENVIRONMENT variable you learned about in chapter 10) and command-line arguments to determine whether it\u2019s running in a development or production environment. This is used to populate the IWebHostEnvironment object that\u2019s used throughout your app.\u200c<br \/>\nConfigureHostingConfiguration\uff08\uff09 \u65b9\u6cd5\u662f\u5e94\u7528\u7a0b\u5e8f\u786e\u5b9a\u5b83\u5f53\u524d\u5728\u54ea\u4e2a HostingEnvironment \u4e2d\u8fd0\u884c\u7684\u4f4d\u7f6e\u3002\u6846\u67b6\u4f1a\u67e5\u627e\u4ee5 \u201cDOTNET<\/em>\u201d \u5f00\u5934\u7684\u73af\u5883\u53d8\u91cf\uff08\u4f8b\u5982\u60a8\u5728\u7b2c 10 \u7ae0\u4e2d\u5b66\u5230\u7684 DOTNET_ENVIRONMENT \u53d8\u91cf\uff09\u548c\u547d\u4ee4\u884c\u53c2\u6570\uff0c\u4ee5\u786e\u5b9a\u5b83\u662f\u5728\u5f00\u53d1\u73af\u5883\u4e2d\u8fd0\u884c\u8fd8\u662f\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u8fd0\u884c\u3002\u8fd9\u7528\u4e8e\u586b\u5145\u6574\u4e2a\u5e94\u7528\u7a0b\u5e8f\u4e2d\u4f7f\u7528\u7684 IWebHostEnvironment \u5bf9\u8c61\u3002<\/p>\n<p>The ConfigureAppConfiguration() method is where you con\ufb01gure the main IConfiguration object for your app, populating it from appsettings.json \ufb01les, environment variables, and User Secrets, for example. The default builder populates the con\ufb01guration using all the sources shown in listing 30.5, which is similar to the con\ufb01guration WebApplicationBuilder uses.\u200c<br \/>\nConfigureAppConfiguration\uff08\uff09 \u65b9\u6cd5\u662f\u4e3a\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\u4e3b IConfiguration \u5bf9\u8c61\u7684\u5730\u65b9\uff0c\u4f8b\u5982\uff0c\u4ece appsettings.json \u6587\u4ef6\u3001\u73af\u5883\u53d8\u91cf\u548c\u7528\u6237\u5bc6\u94a5\u4e2d\u586b\u5145\u5b83\u3002\u9ed8\u8ba4\u6784\u5efa\u5668\u4f7f\u7528\u6e05\u5355 30.5 \u4e2d\u6240\u793a\u7684\u6240\u6709\u6e90\u586b\u5145\u914d\u7f6e\uff0c\u8fd9\u7c7b\u4f3c\u4e8e WebApplicationBuilder \u4f7f\u7528\u7684\u914d\u7f6e\u3002<\/p>\n<p><b>TIP<\/b>  There are some important di\ufb00erences in how the IConfiguration object is built using the default builder and the approach used by WebApplicationBuilder. You can read about these di\ufb00erences on my blog at <a href=\"http:\/\/mng.bz\/e11V\">http:\/\/mng.bz\/e11V<\/a>.<br \/>\n\u63d0\u793a:\u4f7f\u7528\u9ed8\u8ba4\u751f\u6210\u5668\u548c WebApplicationBuilder \u4f7f\u7528\u7684\u65b9\u6cd5\u6784\u5efa IConfiguration \u5bf9\u8c61\u7684\u65b9\u5f0f\u5b58\u5728\u4e00\u4e9b\u91cd\u8981\u5dee\u5f02\u3002\u60a8\u53ef\u4ee5\u5728\u6211\u7684\u535a\u5ba2 <a href=\"http:\/\/mng.bz\/e11V\">http:\/\/mng.bz\/e11V<\/a> \u4e0a\u9605\u8bfb\u8fd9\u4e9b\u5dee\u5f02\u3002<\/p>\n<p>Next up after app con\ufb01guration comes ConfigureLogging(). ConfigureLogging is where you specify the logging settings and providers for your application, which you learned about in chapter 26. In addition to setting up the default ILoggerProviders, this method sets up log \ufb01ltering, using the IConfiguration prepared in ConfigureAppConfiguration().<br \/>\n\u63a5\u4e0b\u6765\uff0c\u5728\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\u4e4b\u540e\u662f ConfigureLogging\uff08\uff09\u3002ConfigureLogging \u662f\u6307\u5b9a\u5e94\u7528\u7a0b\u5e8f\u7684\u65e5\u5fd7\u8bb0\u5f55\u8bbe\u7f6e\u548c\u63d0\u4f9b\u7a0b\u5e8f\u7684\u5730\u65b9\uff0c\u60a8\u5728\u7b2c 26 \u7ae0\u4e2d\u4e86\u89e3\u4e86\u8fd9\u4e00\u70b9\u3002\u9664\u4e86\u8bbe\u7f6e\u9ed8\u8ba4 ILoggerProviders \u4e4b\u5916\uff0c\u6b64\u65b9\u6cd5\u8fd8\u4f7f\u7528 ConfigureAppConfiguration\uff08\uff09 \u4e2d\u51c6\u5907\u7684 IConfiguration \u8bbe\u7f6e\u65e5\u5fd7\u7b5b\u9009\u3002<\/p>\n<p>The last method call shown in listing 30.5, UseDefaultServiceProvider, con\ufb01gures your app to use the built-in DI container. It also sets the ValidateScopes and ValidateOnBuild options based on the current HostingEnvironment. This ensures that when running the application in the development environment, the container automatically checks for captured dependencies, which you learned about in chapter 9.\u200c\u200c<br \/>\n\u6e05\u5355 30.5 \u4e2d\u663e\u793a\u7684\u6700\u540e\u4e00\u4e2a\u65b9\u6cd5\u8c03\u7528 UseDefaultServiceProvider \u5c06\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\u4e3a\u4f7f\u7528\u5185\u7f6e\u7684 DI \u5bb9\u5668\u3002\u5b83\u8fd8\u6839\u636e\u5f53\u524d HostingEnvironment \u8bbe\u7f6e ValidateScopes \u548c ValidateOnBuild \u9009\u9879\u3002\u8fd9\u53ef\u786e\u4fdd\u5728\u5f00\u53d1\u73af\u5883\u4e2d\u8fd0\u884c\u5e94\u7528\u7a0b\u5e8f\u65f6\uff0c\u5bb9\u5668\u4f1a\u81ea\u52a8\u68c0\u67e5\u6355\u83b7\u7684\u4f9d\u8d56\u9879\uff0c\u60a8\u5728\u7b2c 9 \u7ae0\u4e2d\u5b66\u5230\u4e86\u8fd9\u4e00\u70b9\u3002<\/p>\n<p>As you can see, CreateDefaultBuilder does a lot for you. In many cases, these defaults are exactly what you need, but if they\u2019re not, the default builder is optional. You could call new HostBuilder() and start customizing it from there, but you\u2019d need to set up everything that CreateHostBuilder does: logging, hosting con\ufb01guration, and service provider con\ufb01guration, as well as your app con\ufb01guration.<br \/>\n\u5982\u60a8\u6240\u89c1\uff0cCreateDefaultBuilder \u4e3a\u60a8\u505a\u4e86\u5f88\u591a\u4e8b\u60c5\u3002\u5728\u8bb8\u591a\u60c5\u51b5\u4e0b\uff0c\u8fd9\u4e9b\u9ed8\u8ba4\u503c\u6b63\u662f\u60a8\u6240\u9700\u8981\u7684\uff0c\u4f46\u5982\u679c\u5b83\u4eec\u4e0d\u662f\uff0c\u5219\u9ed8\u8ba4\u6784\u5efa\u5668\u662f\u53ef\u9009\u7684\u3002\u60a8\u53ef\u4ee5\u8c03\u7528\u65b0\u7684 HostBuilder\uff08\uff09 \u5e76\u4ece\u90a3\u91cc\u5f00\u59cb\u81ea\u5b9a\u4e49\u5b83\uff0c\u4f46\u60a8\u9700\u8981\u8bbe\u7f6e CreateHostBuilder \u6267\u884c\u7684\u6240\u6709\u4f5c\uff1a\u65e5\u5fd7\u8bb0\u5f55\u3001\u6258\u7ba1\u914d\u7f6e\u548c\u670d\u52a1\u63d0\u4f9b\u5546\u914d\u7f6e\uff0c\u4ee5\u53ca\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\u3002<\/p>\n<p>An alternative approach is to layer additional con\ufb01guration on top of the existing defaults. In the following listing, I show how to add a Seq logging provider to the con\ufb01gured providers using ConfigureLogging(), as well as how to recon\ufb01gure the app con\ufb01guration to load only from the appsettings.json provider by clearing the default providers.<br \/>\n\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u5728\u73b0\u6709\u9ed8\u8ba4\u503c\u4e4b\u4e0a\u5bf9\u5176\u4ed6\u914d\u7f6e\u8fdb\u884c\u5206\u5c42\u3002\u5728\u4e0b\u9762\u7684\u6e05\u5355\u4e2d\uff0c\u6211\u5c06\u5c55\u793a\u5982\u4f55\u4f7f\u7528 ConfigureLogging\uff08\uff09 \u5c06 Seq \u65e5\u5fd7\u8bb0\u5f55\u63d0\u4f9b\u7a0b\u5e8f\u6dfb\u52a0\u5230\u914d\u7f6e\u7684\u63d0\u4f9b\u7a0b\u5e8f\u4e2d\uff0c\u4ee5\u53ca\u5982\u4f55\u901a\u8fc7\u6e05\u9664\u9ed8\u8ba4\u63d0\u4f9b\u7a0b\u5e8f\u6765\u91cd\u65b0\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\u4ee5\u4ec5\u4ece appsettings.json \u63d0\u4f9b\u7a0b\u5e8f\u52a0\u8f7d\u3002<\/p>\n<p>Listing 30.6 Customizing the default HostBuilder<br \/>\n\u6e05\u5355 30.6 \u81ea\u5b9a\u4e49\u9ed8\u8ba4\u7684 HostBuilder<\/p>\n<pre><code>public class Program\n{\npublic static void Main(string[] args)\n{\nCreateHostBuilder(args).Build().Run();\n}\npublic static IHostBuilder CreateHostBuilder(string[] args) =&gt;\nHost.CreateDefaultBuilder(args)\n.ConfigureLogging(logBuilder =&gt; logBuilder.AddSeq()) \u2776\n.ConfigureAppConfiguration((hostContext, config) =&gt; \u2777\n{\nconfig.Sources.Clear(); \u2778\nconfig.AddJsonFile(&quot;appsettings.json&quot;); \u2779\n}\n.ConfigureWebHostDefaults(webBuilder =&gt;\n{\nwebBuilder.UseStartup&lt;Startup&gt;();\n});\n}<\/code><\/pre>\n<p>\u2776 Adds the Seq logging provider to the configuration<br \/>\n\u5c06 Seq \u65e5\u5fd7\u8bb0\u5f55\u63d0\u4f9b\u7a0b\u5e8f\u6dfb\u52a0\u5230\u914d\u7f6e\u4e2d<\/p>\n<p>\u2777 HostBuilder provides a hosting context and an instance of ConfigurationBuilder.<br \/>\nHostBuilder \u63d0\u4f9b\u6258\u7ba1\u4e0a\u4e0b\u6587\u548c ConfigurationBuilder \u5b9e\u4f8b\u3002<\/p>\n<p>\u2778 Clears the providers configured by default in CreateDefaultBuilder<br \/>\n\u6e05\u9664 CreateDefaultBuilder\u4e2d\u9ed8\u8ba4\u914d\u7f6e\u7684\u63d0\u4f9b\u7a0b\u5e8f<\/p>\n<p>\u2779 Adds a JSON configuration provider, providing the filename of the configuration file<br \/>\n\u6dfb\u52a0 JSON \u914d\u7f6e\u63d0\u4f9b\u7a0b\u5e8f\uff0c\u63d0\u4f9b\u914d\u7f6e\u6587\u4ef6\u7684\u6587\u4ef6\u540d<\/p>\n<p>A new HostBuilder is created in CreateDefaultBuilder() and executes all the con\ufb01guration methods you saw in listing 30.5. Next, the HostBuilder invokes the extra ConfigureLogging() and ConfigureAppConfiguration() methods added in listing 30.6. You can call any of the other con\ufb01guration methods on HostBuilder to further customize the instance before calling Build().\u200c<br \/>\n\u5728 CreateDefaultBuilder\uff08\uff09 \u4e2d\u521b\u5efa\u4e00\u4e2a\u65b0\u7684 HostBuilder\uff0c\u5e76\u6267\u884c\u60a8\u5728\u6e05\u5355 30.5 \u4e2d\u770b\u5230\u7684\u6240\u6709\u914d\u7f6e\u65b9\u6cd5\u3002\u63a5\u4e0b\u6765\uff0cHostBuilder \u8c03\u7528\u6e05\u5355 30.6 \u4e2d\u6dfb\u52a0\u7684\u989d\u5916 ConfigureLogging\uff08\uff09 \u548c ConfigureAppConfiguration\uff08\uff09 \u65b9\u6cd5\u3002\u5728\u8c03\u7528 Build\uff08\uff09 \u4e4b\u524d\uff0c\u60a8\u53ef\u4ee5\u5728 HostBuilder \u4e0a\u8c03\u7528\u4efb\u4f55\u5176\u4ed6\u914d\u7f6e\u65b9\u6cd5\u4ee5\u8fdb\u4e00\u6b65\u81ea\u5b9a\u4e49\u5b9e\u4f8b\u3002<\/p>\n<p><b>NOTE<\/b>  Each call to a Configure<em>() method on HostBuilder adds an extra con\ufb01guration function to the setup code; these calls don\u2019t replace existing Configure<\/em> () calls. The con\ufb01guration methods are executed in the same order in which they\u2019re added to the HostBuilder, so they execute after the CreateDefaultBuilder() con\ufb01guration methods.<br \/>\n\u6ce8\u610f:\u5bf9 HostBuilder \u4e0a\u7684 Configure\uff08\uff09 \u65b9\u6cd5\u7684\u6bcf\u6b21\u8c03\u7528\u90fd\u4f1a\u5411\u8bbe\u7f6e\u4ee3\u7801\u6dfb\u52a0\u4e00\u4e2a\u989d\u5916\u7684\u914d\u7f6e\u51fd\u6570;\u8fd9\u4e9b\u8c03\u7528\u4e0d\u4f1a\u66ff\u6362\u73b0\u6709\u7684 Configure \uff08\uff09 \u8c03\u7528\u3002\u914d\u7f6e\u65b9\u6cd5\u7684\u6267\u884c\u987a\u5e8f\u4e0e\u6dfb\u52a0\u5230 HostBuilder \u7684\u987a\u5e8f\u76f8\u540c\uff0c\u56e0\u6b64\u5b83\u4eec\u5728 CreateDefaultBuilder\uff08\uff09 \u914d\u7f6e\u65b9\u6cd5\u4e4b\u540e\u6267\u884c\u3002<\/p>\n<p>One of the criticisms of early ASP.NET Core apps was that they were quite complex to understand when you\u2019re getting started, and after working your way through this chapter, you might well be able to see why! In the next section we compare the generic host and Startup approach with the newer minimal hosting WebApplication approach and discuss when you might want to use one over the other.\u200c<br \/>\n\u5bf9\u65e9\u671f ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u7684\u6279\u8bc4\u4e4b\u4e00\u662f\uff0c\u5f53\u60a8\u5f00\u59cb\u65f6\uff0c\u5b83\u4eec\u975e\u5e38\u96be\u4ee5\u7406\u89e3\uff0c\u5728\u5b8c\u6210\u672c\u7ae0\u4e4b\u540e\uff0c\u60a8\u5f88\u53ef\u80fd\u80fd\u591f\u660e\u767d\u4e3a\u4ec0\u4e48\uff01\u5728\u4e0b\u4e00\u8282\u4e2d\uff0c\u6211\u4eec\u5c06\u901a\u7528 host \u548c Startup \u65b9\u6cd5\u4e0e\u8f83\u65b0\u7684\u6700\u5c0f\u6258\u7ba1 WebApplication \u65b9\u6cd5\u8fdb\u884c\u6bd4\u8f83\uff0c\u5e76\u8ba8\u8bba\u4f55\u65f6\u53ef\u80fd\u9700\u8981\u4f7f\u7528\u5176\u4e2d\u4e00\u79cd\u65b9\u6cd5\u3002<\/p>\n<h2>30.5 Understanding the complexity of the generic host\u200c<\/h2>\n<p>30.5 \u4e86\u89e3\u6cdb\u578b\u4e3b\u673a\u7684\u590d\u6742\u6027<\/p>\n<p>Before .NET 6, all ASP.NET Core apps used the generic host and Startup approach. Many people liked the consistent structure this added, but it also has some drawbacks and complexity:<br \/>\n\u5728 .NET 6 \u4e4b\u524d\uff0c\u6240\u6709 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u90fd\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u548c\u542f\u52a8\u65b9\u6cd5\u3002\u8bb8\u591a\u4eba\u559c\u6b22\u5b83\u6dfb\u52a0\u7684\u4e00\u81f4\u7ed3\u6784\uff0c\u4f46\u5b83\u4e5f\u6709\u4e00\u4e9b\u7f3a\u70b9\u548c\u590d\u6742\u6027\uff1a<\/p>\n<p>\u2022  Con\ufb01guration is split between two \ufb01les.<br \/>\n\u914d\u7f6e\u5728\u4e24\u4e2a\u6587\u4ef6\u4e4b\u95f4\u62c6\u5206\u3002<\/p>\n<p>\u2022  The separation between Program.cs and Startup is somewhat arbitrary.<br \/>\nProgram.cs \u548c Startup \u4e4b\u95f4\u7684\u5212\u5206\u6709\u4e9b\u6b66\u65ad\u3002<\/p>\n<p>\u2022  The generic IHostBuilder exposes newcomers to legacy decisions.<br \/>\n\u901a\u7528 IHostBuilder \u4f7f\u65b0\u4eba\u80fd\u591f\u63a5\u89e6\u5230\u4f20\u7edf\u51b3\u7b56\u3002<\/p>\n<p>\u2022  The lambda-based con\ufb01guration can be hard to follow and reason about.<br \/>\n\u57fa\u4e8e lambda \u7684\u914d\u7f6e\u53ef\u80fd\u96be\u4ee5\u9075\u5faa\u548c\u63a8\u7406\u3002<\/p>\n<p>\u2022  The pattern-based conventions of Startup may be hard to discover.<br \/>\nStartup \u7684\u57fa\u4e8e\u6a21\u5f0f\u7684\u7ea6\u5b9a\u53ef\u80fd\u5f88\u96be\u53d1\u73b0\u3002<\/p>\n<p>\u2022  Tooling historically relies on your de\ufb01ning a CreateHostBuilder method in Program.cs.<br \/>\n\u5de5\u5177\u4ee5\u524d\u4f9d\u8d56\u4e8e\u60a8\u5728 Program.cs \u4e2d\u5b9a\u4e49 CreateHostBuilder \u65b9\u6cd5\u3002<\/p>\n<p>I\u2019ll address each of these problems in turn and afterward discuss how WebApplication attempted to improve the situation.<br \/>\n\u6211\u5c06\u4f9d\u6b21\u89e3\u51b3\u8fd9\u4e9b\u95ee\u9898\u4e2d\u7684\u6bcf\u4e00\u4e2a\uff0c\u7136\u540e\u8ba8\u8bba WebApplication \u5982\u4f55\u5c1d\u8bd5\u6539\u5584\u8fd9\u79cd\u60c5\u51b5\u3002<\/p>\n<p>Points 1 and 2 in the preceding list deal with the separation between Program.cs and Startup. As you saw in section 30.1, theoretically the intention is that Program.cs de\ufb01nes the host and rarely changes, whereas Startup de\ufb01nes the app features (services, middleware, and endpoints). This seems like a reasonable decision, but one inevitable downside is that you need to \ufb02ick back and forth between at least two \ufb01les to understand all your bootstrapping code.<br \/>\n\u524d\u9762\u5217\u8868\u4e2d\u7684\u7b2c 1 \u70b9\u548c\u7b2c 2 \u70b9\u6d89\u53ca Program.cs \u548c Startup \u4e4b\u95f4\u7684\u5206\u79bb\u3002\u6b63\u5982\u60a8\u5728 Section 30.1 \u4e2d\u770b\u5230\u7684\uff0c\u7406\u8bba\u4e0a\u7684\u76ee\u7684\u662f Program.cs \u5b9a\u4e49\u4e3b\u673a\u5e76\u4e14\u5f88\u5c11\u66f4\u6539\uff0c\u800c Startup \u5b9a\u4e49\u5e94\u7528\u7a0b\u5e8f\u529f\u80fd\uff08\u670d\u52a1\u3001\u4e2d\u95f4\u4ef6\u548c\u7aef\u70b9\uff09\u3002\u8fd9\u4f3c\u4e4e\u662f\u4e00\u4e2a\u5408\u7406\u7684\u51b3\u5b9a\uff0c\u4f46\u4e00\u4e2a\u4e0d\u53ef\u907f\u514d\u7684\u7f3a\u70b9\u662f\uff0c\u60a8\u9700\u8981\u5728\u81f3\u5c11\u4e24\u4e2a\u6587\u4ef6\u4e4b\u95f4\u6765\u56de\u5207\u6362\u624d\u80fd\u7406\u89e3\u6240\u6709\u5f15\u5bfc\u4ee3\u7801\u3002<\/p>\n<p>On top of that, you don\u2019t necessarily need to stick to these conventions. You can register services in Program.cs by calling HostBuilder.ConfigureServices(), for example, or register middleware using WebHostBuilder.Configure(). This is relatively rare but not entirely unheard-of, further blurring the lines between the \ufb01les.<br \/>\n\u6700\u91cd\u8981\u7684\u662f\uff0c\u60a8\u4e0d\u4e00\u5b9a\u9700\u8981\u9075\u5b88\u8fd9\u4e9b\u7ea6\u5b9a\u3002\u4f8b\u5982\uff0c\u60a8\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528 HostBuilder.ConfigureServices\uff08\uff09 \u5728 Program.cs \u4e2d\u6ce8\u518c\u670d\u52a1\uff0c\u6216\u4f7f\u7528 WebHostBuilder.Configure\uff08\uff09 \u6ce8\u518c\u4e2d\u95f4\u4ef6\u3002\u8fd9\u79cd\u60c5\u51b5\u76f8\u5bf9\u7f55\u89c1\uff0c\u4f46\u5e76\u975e\u5b8c\u5168\u95fb\u6240\u672a\u95fb\uff0c\u8fdb\u4e00\u6b65\u6a21\u7cca\u4e86\u6587\u4ef6\u4e4b\u95f4\u7684\u754c\u9650\u3002<\/p>\n<p>Point 3 relates to the fact that you must call ConfigureWebHostDefaults() (which uses an IWebHostBuilder) to set up Kestrel and register your Startup class. This level of indirection (and the introduction of another builder type) is a remnant of decisions harking back to ASP.NET Core 1.0. For people familiar with ASP.NET Core, this pattern is just one of those things, but it adds confusion when you\u2019re new to it.<br \/>\n\u7b2c 3 \u70b9\u4e0e\u5fc5\u987b\u8c03\u7528 ConfigureWebHostDefaults\uff08\uff09\uff08\u4f7f\u7528 IWebHostBuilder\uff09\u6765\u8bbe\u7f6e Kestrel \u5e76\u6ce8\u518c Startup \u7c7b\u8fd9\u4e00\u4e8b\u5b9e\u6709\u5173\u3002\u8fd9\u79cd\u95f4\u63a5\u7ea7\u522b\uff08\u4ee5\u53ca\u53e6\u4e00\u79cd\u6784\u5efa\u5668\u7c7b\u578b\u7684\u5f15\u5165\uff09\u662f\u53ef\u4ee5\u8ffd\u6eaf\u5230 ASP.NET Core 1.0 \u7684\u51b3\u7b56\u7684\u6b8b\u4f59\u3002\u5bf9\u4e8e\u719f\u6089 ASP.NET Core \u7684\u4eba\u6765\u8bf4\uff0c\u8fd9\u79cd\u6a21\u5f0f\u53ea\u662f\u5176\u4e2d\u4e4b\u4e00\uff0c\u4f46\u5f53\u4f60\u521a\u63a5\u89e6\u5b83\u65f6\uff0c\u5b83\u4f1a\u589e\u52a0\u56f0\u60d1\u3002<\/p>\n<p><b>NOTE<\/b>  For a walk-through of the evolution of ASP.NET Core bootstrapping code, see my blog post at <a href=\"https:\/\/andrewlock.net\/exploring-dotnet-6-part-2-comparing-webapplicationbuilder-to-the-generic-host\/\">https:\/\/andrewlock.net\/exploring-dotnet-6-part-2-comparing-webapplicationbuilder-to-the-generic-host\/<\/a> .<br \/>\n\u6ce8\u610f\u6709\u5173 ASP.NET Core \u5f15\u5bfc\u4ee3\u7801\u6f14\u53d8\u7684\u6f14\u7ec3\uff0c\u8bf7\u53c2\u9605\u6211\u5728 <a href=\"https:\/\/andrewlock.net\/exploring-dotnet-6-part-2-comparing-webapplicationbuilder-to-the-generic-host\/\">https:\/\/andrewlock.net\/exploring-dotnet-6-part-2-comparing-webapplicationbuilder-to-the-generic-host\/<\/a> \u4e0a\u7684\u535a\u5ba2\u6587\u7ae0\u3002<\/p>\n<p>Similarly, the lambda-based con\ufb01guration mentioned in point 4 can be hard for newcomers to ASP.NET Core to follow. If you\u2019re new to .NET, lambdas are an extra concept you\u2019ll need to understand before you can understand the basics of the code. On top of that, the execution of the lambdas doesn\u2019t necessarily happen sequentially; the HostBuilder essentially queues the lambda methods so they\u2019re executed at the right time. Consider the following snippet:<br \/>\n\u540c\u6837\uff0c\u7b2c 4 \u70b9\u4e2d\u63d0\u5230\u7684\u57fa\u4e8e lambda \u7684\u914d\u7f6e\u5bf9\u4e8e ASP.NET Core \u7684\u65b0\u624b\u6765\u8bf4\u53ef\u80fd\u5f88\u96be\u7406\u89e3\u3002\u5982\u679c\u60a8\u4e0d\u719f\u6089 .NET\uff0c\u5219 lambda \u662f\u4e00\u4e2a\u989d\u5916\u7684\u6982\u5ff5\uff0c\u60a8\u9700\u8981\u5148\u4e86\u89e3\uff0c\u7136\u540e\u624d\u80fd\u4e86\u89e3\u4ee3\u7801\u7684\u57fa\u7840\u77e5\u8bc6\u3002\u6700\u91cd\u8981\u7684\u662f\uff0clambda \u7684\u6267\u884c\u4e0d\u4e00\u5b9a\u662f\u6309\u987a\u5e8f\u53d1\u751f\u7684;HostBuilder \u5b9e\u8d28\u4e0a\u662f\u5c06 lambda \u65b9\u6cd5\u6392\u961f\uff0c\u4ee5\u4fbf\u5b83\u4eec\u5728\u6b63\u786e\u7684\u65f6\u95f4\u6267\u884c\u3002\u8bf7\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\u6bb5\uff1a<\/p>\n<pre><code>public static IhostBuilder CreateHostBuilder(string[] args) =&gt;\nHost.CreateDefaultBuilder(args)\n.ConfigureLogging(logging =&gt; logging.AddSeq())\n.ConfigureAppConfiguration(config =&gt; {})\n.ConfigureServices(s =&gt; {})\n.ConfigureHostConfiguration(config =&gt; {})\n.ConfigureWebHostDefaults(webBuilder =&gt;\n{\nwebBuilder.UseStartup&lt;Startup&gt;();\n});<\/code><\/pre>\n<p>The lambdas execute in the following order:<br \/>\nlambda \u6309\u4ee5\u4e0b\u987a\u5e8f\u6267\u884c\uff1a<\/p>\n<ol>\n<li>ConfigureWebHostDefaults()<\/li>\n<li>ConfigureHostConfiguration()<\/li>\n<li>ConfigureAppConfiguration()<\/li>\n<li>ConfigureLogging()<\/li>\n<li>ConfigureServices()<\/li>\n<li>Startup.ConfigureServices()<\/li>\n<li>Startup.Configure()<\/li>\n<\/ol>\n<p>For the most part, this ordering detail shouldn\u2019t matter, but it still adds apparent complexity for those who are new to ASP.NET Core.<br \/>\n\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u8fd9\u4e2a\u6392\u5e8f\u7ec6\u8282\u5e94\u8be5\u65e0\u5173\u7d27\u8981\uff0c\u4f46\u5bf9\u4e8e\u521a\u63a5\u89e6 ASP.NET Core \u7684\u4eba\u6765\u8bf4\uff0c\u5b83\u4ecd\u7136\u589e\u52a0\u4e86\u660e\u663e\u7684\u590d\u6742\u6027\u3002<\/p>\n<p>Point 5 in the list of challenges relates to the Startup class and the default convention\/ pattern-based approach. Users coming to ASP.NET Core for the \ufb01rst time will likely be familiar with interfaces and base classes, but they may not have experienced the re\ufb02ection-based approach.<br \/>\n\u6311\u6218\u5217\u8868\u4e2d\u7684\u7b2c 5 \u70b9\u4e0e Startup \u7c7b\u548c\u9ed8\u8ba4\u7684\u7ea6\u5b9a\/\u57fa\u4e8e\u6a21\u5f0f\u7684\u65b9\u6cd5\u6709\u5173\u3002\u9996\u6b21\u4f7f\u7528 ASP.NET Core \u7684\u7528\u6237\u53ef\u80fd\u719f\u6089\u63a5\u53e3\u548c\u57fa\u7c7b\uff0c\u4f46\u4ed6\u4eec\u53ef\u80fd\u6ca1\u6709\u4f53\u9a8c\u8fc7\u57fa\u4e8e\u53cd\u5c04\u7684\u65b9\u6cd5\u3002<\/p>\n<p>Using conventions instead of an explicit interface adds \ufb02exibility but can make things harder for discoverability. There are also various caveats and edge cases to consider. For example, you can inject only IWebHostEnvironment and IConfiguration into the Startup constructor; you can\u2019t inject anything into the ConfigureServices() method, but you can inject any registered service into Configure(). These are implied rules that you discover primarily by breaking them and then having your app shout at you!\u200c<br \/>\n\u4f7f\u7528\u7ea6\u5b9a\u800c\u4e0d\u662f\u663e\u5f0f\u63a5\u53e3\u53ef\u4ee5\u589e\u52a0\u7075\u6d3b\u6027\uff0c\u4f46\u53ef\u80fd\u4f1a\u4f7f\u53ef\u53d1\u73b0\u6027\u53d8\u5f97\u66f4\u52a0\u56f0\u96be\u3002\u8fd8\u6709\u5404\u79cd\u6ce8\u610f\u4e8b\u9879\u548c\u8fb9\u7f18\u60c5\u51b5\u9700\u8981\u8003\u8651\u3002\u4f8b\u5982\uff0c\u53ea\u80fd\u5c06 IWebHostEnvironment \u548c IConfiguration \u6ce8\u5165 Startup \u6784\u9020\u51fd\u6570;\u4f60\u4e0d\u80fd\u5411 ConfigureServices\uff08\uff09 \u65b9\u6cd5\u6ce8\u5165\u4efb\u4f55\u5185\u5bb9\uff0c\u4f46\u4f60\u53ef\u4ee5\u5c06\u4efb\u4f55\u5df2\u6ce8\u518c\u7684\u670d\u52a1\u6ce8\u5165\u5230 Configure\uff08\uff09 \u4e2d\u3002\u8fd9\u4e9b\u662f\u9690\u542b\u7684\u89c4\u5219\uff0c\u60a8\u4e3b\u8981\u662f\u901a\u8fc7\u6253\u7834\u5b83\u4eec\uff0c\u7136\u540e\u8ba9\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u5bf9\u60a8\u5927\u558a\u5927\u53eb\u6765\u53d1\u73b0\u7684\uff01<\/p>\n<p><b>TIP<\/b>  The pattern-based approach allows for a lot more than DI into Configure. You can also create environment-speci\ufb01c methods, such as Configure-DevelopmentServices or ConfigureProductionServices, and ASP.NET Core invokes the correct method based on the environment. You can even create a whole StartupProduction class if you wish! For more details on these Startup conventions, see the documentation at <a href=\"http:\/\/mng.bz\/Oxxw\">http:\/\/mng.bz\/Oxxw<\/a>.<br \/>\n\u63d0\u793a:\u57fa\u4e8e\u6a21\u5f0f\u7684\u65b9\u6cd5\u5141\u8bb8\u7684\u4e0d\u4ec5\u4ec5\u662f DI \u5230 Configure \u4e2d\u3002\u60a8\u8fd8\u53ef\u4ee5\u521b\u5efa\u7279\u5b9a\u4e8e\u73af\u5883\u7684\u65b9\u6cd5\uff0c\u4f8b\u5982 Configure-DevelopmentServices \u6216 ConfigureProductionServices\uff0cASP.NET Core \u4f1a\u6839\u636e\u73af\u5883\u8c03\u7528\u6b63\u786e\u7684\u65b9\u6cd5\u3002\u5982\u679c\u60a8\u613f\u610f\uff0c\u60a8\u751a\u81f3\u53ef\u4ee5\u521b\u5efa\u6574\u4e2a StartupProduction \u7c7b\uff01\u6709\u5173\u8fd9\u4e9b Startup \u7ea6\u5b9a\u7684\u66f4\u591a\u8be6\u7ec6\u4fe1\u606f\uff0c\u8bf7\u53c2\u9605 <a href=\"http:\/\/mng.bz\/Oxxw\">http:\/\/mng.bz\/Oxxw<\/a> \u4e2d\u7684\u6587\u6863\u3002<\/p>\n<p>The Startup class isn\u2019t the only place where ASP.NET Core relies on opaque conventions. You may remember in section30.2 I mentioned that Program.cs deliberately extracts the building of the IHostBuilder to a method called CreateHostBuilder. The name of this method was historically important. Tooling such as the EF Core tools hooked into it so that they could load your application con\ufb01guration and services when running migrations and other functionality. In earlier versions of ASP.NET Core, renaming this method would break all your tooling!<br \/>\nStartup \u7c7b\u5e76\u4e0d\u662f ASP.NET Core \u4f9d\u8d56\u4e8e\u4e0d\u900f\u660e\u7ea6\u5b9a\u7684\u552f\u4e00\u4f4d\u7f6e\u3002\u4f60\u53ef\u80fd\u8fd8\u8bb0\u5f9730.2\u8282\u6211\u63d0\u5230Program.cs\u7279\u610f\u5c06 IHostBuilder \u7684\u6784\u5efa\u63d0\u53d6\u5230\u4e00\u4e2a\u540d\u4e3a CreateHostBuilder \u7684\u65b9\u6cd5\u4e2d\u3002\u8fd9\u79cd\u65b9\u6cd5\u7684\u540d\u79f0\u5728\u5386\u53f2\u4e0a\u5f88\u91cd\u8981\u3002EF Core \u5de5\u5177\u7b49\u5de5\u5177\u6302\u63a5\u5230\u5176\u4e2d\uff0c\u4ee5\u4fbf\u5b83\u4eec\u53ef\u4ee5\u5728\u8fd0\u884c\u8fc1\u79fb\u548c\u5176\u4ed6\u529f\u80fd\u65f6\u52a0\u8f7d\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e\u548c\u670d\u52a1\u3002\u5728\u65e9\u671f\u7248\u672c\u7684 ASP.NET Core \u4e2d\uff0c\u91cd\u547d\u540d\u6b64\u65b9\u6cd5\u4f1a\u7834\u574f\u60a8\u7684\u6240\u6709\u5de5\u5177\uff01<\/p>\n<p><b>NOTE<\/b>  As of .NET 6, you don\u2019t have to create a CreateHostBuilder method; you can create your whole app inside your Main function (or using top-level statements), and the EF Core tools will work without error. This was \ufb01xed partly to add support for WebApplication. If you\u2019re interested in the mechanics of how it was \ufb01xed, see my blog at <a href=\"http:\/\/mng.bz\/Y11z\">http:\/\/mng.bz\/Y11z<\/a>.<br \/>\n\u6ce8\u610f\uff1a\u4ece .NET 6 \u5f00\u59cb\uff0c\u60a8\u4e0d\u5fc5\u521b\u5efa CreateHostBuilder \u65b9\u6cd5;\u60a8\u53ef\u4ee5\u5728 Main \u51fd\u6570\u4e2d\uff08\u6216\u4f7f\u7528\u9876\u7ea7\u8bed\u53e5\uff09\u521b\u5efa\u6574\u4e2a\u5e94\u7528\u7a0b\u5e8f\uff0cEF Core \u5de5\u5177\u5c06\u6b63\u5e38\u5de5\u4f5c\u800c\u4e0d\u4f1a\u51fa\u9519\u3002\u6b64\u95ee\u9898\u5df2\u90e8\u5206\u4fee\u590d\uff0c\u4ee5\u6dfb\u52a0\u5bf9 WebApplication \u7684\u652f\u6301\u3002\u5982\u679c\u60a8\u5bf9\u4fee\u590d\u5b83\u7684\u673a\u5236\u611f\u5174\u8da3\uff0c\u8bf7\u53c2\u9605\u6211\u7684\u535a\u5ba2 <a href=\"http:\/\/mng.bz\/Y11z\">http:\/\/mng.bz\/Y11z<\/a>\u3002<\/p>\n<p>Once you\u2019re experienced with ASP.NET Core, most of these gripes become relatively minor. You quickly get used to the standard patterns and avoid the pitfalls. But for new users of ASP.NET Core, Microsoft wanted a smoother experience, closer to the experience you get in many other languages.<br \/>\n\u4e00\u65e6\u60a8\u4f53\u9a8c\u4e86 ASP.NET Core\uff0c\u8fd9\u4e9b\u62b1\u6028\u4e2d\u7684\u5927\u591a\u6570\u90fd\u4f1a\u53d8\u5f97\u76f8\u5bf9\u8f83\u5c0f\u3002\u60a8\u5f88\u5feb\u5c31\u4f1a\u4e60\u60ef\u6807\u51c6\u6a21\u5f0f\u5e76\u907f\u514d\u9677\u9631\u3002\u4f46\u5bf9\u4e8e ASP.NET Core \u7684\u65b0\u7528\u6237\uff0cMicrosoft \u5e0c\u671b\u83b7\u5f97\u66f4\u6d41\u7545\u7684\u4f53\u9a8c\uff0c\u66f4\u63a5\u8fd1\u60a8\u5728\u8bb8\u591a\u5176\u4ed6\u8bed\u8a00\u4e2d\u83b7\u5f97\u7684\u4f53\u9a8c\u3002<\/p>\n<p>The minimal hosting APIs provided by WebApplicationBuilder and WebApplication largely address these concerns. Con\ufb01guration happens all in one \ufb01le using an imperative style, with far fewer lambda-based con\ufb01guration methods or implicit convention-based setup.<br \/>\nWebApplicationBuilder \u548c WebApplication \u63d0\u4f9b\u7684\u6700\u5c0f\u6258\u7ba1 API \u5728\u5f88\u5927\u7a0b\u5ea6\u4e0a\u89e3\u51b3\u4e86\u8fd9\u4e9b\u95ee\u9898\u3002\u4f7f\u7528\u547d\u4ee4\u5f0f\u6837\u5f0f\u5728\u4e00\u4e2a\u6587\u4ef6\u4e2d\u8fdb\u884c\u914d\u7f6e\uff0c\u57fa\u4e8e lambda \u7684\u914d\u7f6e\u65b9\u6cd5\u6216\u57fa\u4e8e\u7ea6\u5b9a\u7684\u9690\u5f0f\u8bbe\u7f6e\u8981\u5c11\u5f97\u591a\u3002<\/p>\n<p>All the relevant objects like con\ufb01guration and environment are exposed as properties on the WebApplicationBuilder or WebApplication types, so they\u2019re easy to discover.\u200c<br \/>\n\u6240\u6709\u76f8\u5173\u5bf9\u8c61\uff08\u5982\u914d\u7f6e\u548c\u73af\u5883\uff09\u90fd\u4f5c\u4e3a WebApplicationBuilder \u6216 WebApplication \u7c7b\u578b\u7684\u5c5e\u6027\u516c\u5f00\uff0c\u56e0\u6b64\u5f88\u5bb9\u6613\u53d1\u73b0\u3002<\/p>\n<p>WebApplicationBuilder and WebApplication also try to hide much of the complexity and legacy decisions from you. Under the hood, WebApplication uses the generic host, but you don\u2019t need to know that to use it or be productive. As you\u2019ve seen throughout the book, WebApplication automatically adds various middleware to your pipeline, helping you avoid common pitfalls, such as incorrect middleware ordering.<br \/>\nWebApplicationBuilder \u548c WebApplication \u8fd8\u8bd5\u56fe\u5411\u60a8\u9690\u85cf\u8bb8\u591a\u590d\u6742\u6027\u548c\u9057\u7559\u51b3\u7b56\u3002\u5728\u540e\u53f0\uff0cWebApplication \u4f7f\u7528\u901a\u7528\u4e3b\u673a\uff0c\u4f46\u60a8\u65e0\u9700\u77e5\u9053\u5b83\u5373\u53ef\u4f7f\u7528\u5b83\u6216\u63d0\u9ad8\u5de5\u4f5c\u6548\u7387\u3002\u6b63\u5982\u60a8\u5728\u6574\u672c\u4e66\u4e2d\u6240\u770b\u5230\u7684\uff0cWebApplication \u4f1a\u81ea\u52a8\u5c06\u5404\u79cd\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u60a8\u7684\u7ba1\u9053\u4e2d\uff0c\u5e2e\u52a9\u60a8\u907f\u514d\u5e38\u89c1\u7684\u9677\u9631\uff0c\u4f8b\u5982\u4e2d\u95f4\u4ef6\u987a\u5e8f\u4e0d\u6b63\u786e\u3002<\/p>\n<p><b>NOTE<\/b>  If you\u2019re interested in how WebApplicationBuilder abstracts over the generic host, see my post at <a href=\"https:\/\/andrewlock.net\/exploring-dotnet-6-part-3-exploring-the-code-behind-webapplicationbuilder\/\">https:\/\/andrewlock.net\/exploring-dotnet-6-part-3-exploring-the-code-behind-webapplicationbuilder\/<\/a> .<br \/>\n\u6ce8\u610f\uff1a\u5982\u679c\u60a8\u5bf9 WebApplicationBuilder \u5982\u4f55\u5728\u901a\u7528\u4e3b\u673a\u4e0a\u8fdb\u884c\u62bd\u8c61\u611f\u5174\u8da3\uff0c\u8bf7\u53c2\u9605\u6211\u5728 <a href=\"https:\/\/andrewlock.net\/exploring-dotnet-6-part-3-exploring-the-code-behind-webapplicationbuilder\/\">https:\/\/andrewlock.net\/exploring-dotnet-6-part-3-exploring-the-code-behind-webapplicationbuilder\/<\/a> \u4e0a\u7684\u5e16\u5b50\u3002<\/p>\n<p>In most cases, minimal hosting provides an easier bootstrapping experience to the generic host and Startup, and Microsoft considers it to be the modern way to create ASP.NET Core apps. But there are cases in which you might want to consider using the generic host instead.<br \/>\n\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u6700\u5c0f\u6258\u7ba1\u4e3a\u901a\u7528\u4e3b\u673a\u548c\u542f\u52a8\u63d0\u4f9b\u4e86\u66f4\u8f7b\u677e\u7684\u5f15\u5bfc\u4f53\u9a8c\uff0cMicrosoft \u8ba4\u4e3a\u8fd9\u662f\u521b\u5efa ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u7684\u73b0\u4ee3\u65b9\u5f0f\u3002\u4f46\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u60a8\u53ef\u80fd\u9700\u8981\u8003\u8651\u6539\u7528\u901a\u7528\u4e3b\u673a\u3002<\/p>\n<h2>30.6 Choosing between the generic host and minimal hosting\u200c<\/h2>\n<p>30.6 \u5728\u901a\u7528\u4e3b\u673a\u548c\u6700\u5c0f\u4e3b\u673a\u4e4b\u95f4\u8fdb\u884c\u9009\u62e9<\/p>\n<p>The introduction of WebApplication and WebApplicationBuilder in .NET 6, also known as minimal hosting, was intended to provide a dramatically simpler \u201cgetting started\u201d experience for newcomers to .NET and ASP.NET Core. All the built-in ASP.NET Core templates use minimal hosting now, and in most cases there\u2019s little reason to look back. In this section I discuss some of the cases in which you might still want to use the generic host approach.<br \/>\n\u5728 .NET 6 \u4e2d\u5f15\u5165 WebApplication \u548c WebApplicationBuilder\uff08\u4e5f\u79f0\u4e3a\u6700\u5c0f\u6258\u7ba1\uff09\uff0c\u65e8\u5728\u4e3a .NET \u548c ASP.NET Core \u7684\u65b0\u624b\u63d0\u4f9b\u6781\u5176\u7b80\u5355\u7684\u201c\u5165\u95e8\u201d\u4f53\u9a8c\u3002\u6240\u6709\u5185\u7f6e\u7684 ASP.NET Core \u6a21\u677f\u73b0\u5728\u90fd\u4f7f\u7528\u6700\u5c11\u7684\u6258\u7ba1\uff0c\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u51e0\u4e4e\u6ca1\u6709\u7406\u7531\u56de\u987e\u8fc7\u53bb\u3002\u5728\u672c\u8282\u4e2d\uff0c\u6211\u5c06\u8ba8\u8bba\u60a8\u53ef\u80fd\u4ecd\u5e0c\u671b\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u65b9\u6cd5\u7684\u4e00\u4e9b\u60c5\u51b5\u3002<\/p>\n<p>In three main cases, you\u2019ll likely want to stick with the generic host instead of using minimal hosting with WebApplication:<br \/>\n\u5728\u4e09\u79cd\u4e3b\u8981\u60c5\u51b5\u4e0b\uff0c\u60a8\u53ef\u80fd\u5e0c\u671b\u575a\u6301\u4f7f\u7528\u901a\u7528\u4e3b\u673a\uff0c\u800c\u4e0d\u662f\u5bf9 WebApplication \u4f7f\u7528\u6700\u5c0f\u6258\u7ba1\uff1a<\/p>\n<p>\u2022  When you already have an ASP.NET Core application that uses the generic host<br \/>\n\u5f53\u60a8\u5df2\u6709\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u7684 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u65f6<\/p>\n<p>\u2022  When you need (or want) \ufb01ne control of building the IHost object<br \/>\n\u5f53\u60a8\u9700\u8981 \uff08\u6216\u60f3\u8981\uff09 \u7cbe\u7ec6\u63a7\u5236\u6784\u5efa IHost \u5bf9\u8c61\u65f6<\/p>\n<p>\u2022  When you\u2019re creating a non-HTTP application<br \/>\n\u5f53\u60a8\u521b\u5efa\u975e HTTP \u5e94\u7528\u7a0b\u5e8f\u65f6<\/p>\n<p>The \ufb01rst use case is relatively obvious: if you already have an ASP.NET Core app that uses the generic host and Startup, you don\u2019t need to change it. You can still upgrade your app to .NET 7, and you shouldn\u2019t need to change any of your startup code. The generic host and Startup are fully supported in .NET 7, but they\u2019re not the default experience.<br \/>\n\u7b2c\u4e00\u4e2a\u7528\u4f8b\u76f8\u5bf9\u660e\u663e\uff1a\u5982\u679c\u60a8\u5df2\u7ecf\u6709\u4e00\u4e2a\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u548c Startup \u7684 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\uff0c\u5219\u65e0\u9700\u66f4\u6539\u5b83\u3002\u60a8\u4ecd\u7136\u53ef\u4ee5\u5c06\u5e94\u7528\u7a0b\u5e8f\u5347\u7ea7\u5230 .NET 7\uff0c\u5e76\u4e14\u4e0d\u9700\u8981\u66f4\u6539\u4efb\u4f55\u542f\u52a8\u4ee3\u7801\u3002.NET 7 \u5b8c\u5168\u652f\u6301\u6cdb\u578b\u4e3b\u673a\u548c\u542f\u52a8\uff0c\u4f46\u5b83\u4eec\u4e0d\u662f\u9ed8\u8ba4\u4f53\u9a8c\u3002<\/p>\n<p><b>TIP<\/b>  In many cases, upgrading an existing project to .NET 7 simply requires updating the framework in the .csproj \ufb01le and updating some NuGet packages. If you\u2019re unlucky, you may \ufb01nd that some APIs have changed. Microsoft publishes upgrade guides for each major version release, so it\u2019s worth reading these before upgrading your apps: <a href=\"https:\/\/learn.microsoft.com\/zh-cn\/aspnet\/core\/migration\/60-70\">https:\/\/learn.microsoft.com\/zh-cn\/aspnet\/core\/migration\/60-70<\/a> .<br \/>\n\u63d0\u793a\u5728\u8bb8\u591a\u60c5\u51b5\u4e0b\uff0c\u5c06\u73b0\u6709\u9879\u76ee\u5347\u7ea7\u5230 .NET 7 \u53ea\u9700\u8981\u66f4\u65b0 .csproj \u6587\u4ef6\u4e2d\u7684\u6846\u67b6\u5e76\u66f4\u65b0\u4e00\u4e9b NuGet \u5305\u3002\u8fd0\u6c14\u4e0d\u597d\u7684\u8bdd\uff0c\u4f60\u53ef\u80fd\u4f1a\u53d1\u73b0\u4e00\u4e9b API \u5df2\u7ecf\u53d1\u751f\u4e86\u53d8\u5316\u3002Microsoft \u53d1\u5e03\u4e86\u6bcf\u4e2a\u4e3b\u8981\u7248\u672c\u7684\u5347\u7ea7\u6307\u5357\uff0c\u56e0\u6b64\u5728\u5347\u7ea7\u5e94\u7528\u7a0b\u5e8f\u4e4b\u524d\uff0c\u503c\u5f97\u9605\u8bfb\u8fd9\u4e9b\u6307\u5357\uff1a<a href=\"https:\/\/learn.microsoft.com\/zh-cn\/aspnet\/core\/migration\/60-70\">https:\/\/learn.microsoft.com\/zh-cn\/aspnet\/core\/migration\/60-70<\/a> \u3002<\/p>\n<p>If you\u2019re creating a new app, but for some reason you don\u2019t like the default options used by WebApplicationBuilder, using the generic host may be your best option. I generally wouldn\u2019t advise this approach, as it will likely require more maintenance than using WebApplication, but it does give you complete control of your bootstrap code if you need or want it.<br \/>\n\u5982\u679c\u60a8\u6b63\u5728\u521b\u5efa\u65b0\u5e94\u7528\u7a0b\u5e8f\uff0c\u4f46\u51fa\u4e8e\u67d0\u79cd\u539f\u56e0\u60a8\u4e0d\u559c\u6b22 WebApplicationBuilder \u4f7f\u7528\u7684\u9ed8\u8ba4\u9009\u9879\uff0c\u5219\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u53ef\u80fd\u662f\u60a8\u7684\u6700\u4f73\u9009\u62e9\u3002\u6211\u901a\u5e38\u4e0d\u5efa\u8bae\u4f7f\u7528\u8fd9\u79cd\u65b9\u6cd5\uff0c\u56e0\u4e3a\u5b83\u53ef\u80fd\u9700\u8981\u6bd4\u4f7f\u7528 WebApplication \u66f4\u591a\u7684\u7ef4\u62a4\uff0c\u4f46\u5982\u679c\u60a8\u9700\u8981\u6216\u60f3\u8981\u5b83\uff0c\u5b83\u786e\u5b9e\u53ef\u4ee5\u8ba9\u60a8\u5b8c\u5168\u63a7\u5236\u5f15\u5bfc\u4ee3\u7801\u3002<\/p>\n<p>The \ufb01nal case applies when you\u2019re building an ASP.NET Core application that primarily runs background processing services, handling messages from a queue for example, but doesn\u2019t handle HTTP requests. The minimal hosting WebApplication and WebApplicationBuilder are, as their names imply, focused on building web applications, so they don\u2019t make sense in this situation.<br \/>\n\u5f53\u60a8\u6784\u5efa\u4e3b\u8981\u8fd0\u884c\u540e\u53f0\u5904\u7406\u670d\u52a1\uff08\u4f8b\u5982\u5904\u7406\u6765\u81ea\u961f\u5217\u7684\u6d88\u606f\uff0c\u4f46\u4e0d\u5904\u7406 HTTP \u8bf7\u6c42\uff09\u7684 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u65f6\uff0c\u6700\u540e\u4e00\u79cd\u60c5\u51b5\u9002\u7528\u3002\u987e\u540d\u601d\u4e49\uff0c\u6700\u5c0f\u6258\u7ba1 WebApplication \u548c WebApplicationBuilder \u4e13\u6ce8\u4e8e\u6784\u5efa Web \u5e94\u7528\u7a0b\u5e8f\uff0c\u56e0\u6b64\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\u5b83\u4eec\u6ca1\u6709\u610f\u4e49\u3002<\/p>\n<p><b>NOTE<\/b>  You\u2019ll learn how to create background tasks and services using the generic host in chapter 34. .NET 8 introduces a non-HTTP version of the WebApplicationBuilder called HostApplicationBuilder which aims to simplify app bootstrapping for your background services.<br \/>\n\u6ce8\u610f\uff1a\u60a8\u5c06\u5728\u7b2c 34 \u7ae0\u4e2d\u5b66\u4e60\u5982\u4f55\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u521b\u5efa\u540e\u53f0\u4efb\u52a1\u548c\u670d\u52a1\u3002.NET 8 \u5f15\u5165\u4e86\u4e00\u4e2a\u540d\u4e3a HostApplicationBuilder \u7684\u975e HTTP \u7248\u672c\u7684 WebApplicationBuilder\uff0c\u65e8\u5728\u7b80\u5316\u540e\u53f0\u670d\u52a1\u7684\u5e94\u7528\u7a0b\u5e8f\u542f\u52a8\u3002<\/p>\n<p>If you\u2019re not in any of these situations, strongly consider using the minimal hosting WebApplication approach and the imperative, scriptlike bootstrapping of top-level statements.<br \/>\n\u5982\u679c\u60a8\u4e0d\u5904\u4e8e\u4e0a\u8ff0\u4efb\u4f55\u4e00\u79cd\u60c5\u51b5\uff0c\u5f3a\u70c8\u5efa\u8bae\u4f7f\u7528\u6700\u5c0f\u6258\u7ba1 WebApplication \u65b9\u6cd5\u548c\u9876\u7ea7\u8bed\u53e5\u7684\u547d\u4ee4\u5f0f\u811a\u672c\u5f0f\u5f15\u5bfc\u3002<\/p>\n<p><b>NOTE<\/b>  The fact that you\u2019re using WebApplication doesn\u2019t mean you have to dump all your service and middleware con\ufb01guration into Program.cs. For alternative approaches, such as using a Startup class you invoke manually or local functions to separate your con\ufb01guration, see my blog post at <a href=\"https:\/\/andrewlock.net\/exploring-dotnet-6-part-12-upgrading-a-dotnet-5-startup-based-app-to-dotnet-6\/\">https:\/\/andrewlock.net\/exploring-dotnet-6-part-12-upgrading-a-dotnet-5-startup-based-app-to-dotnet-6\/<\/a> .<br \/>\n\u6ce8\u610f\uff1a\u60a8\u4f7f\u7528\u7684\u662f WebApplication \u8fd9\u4e00\u4e8b\u5b9e\u5e76\u4e0d\u610f\u5473\u7740\u60a8\u5fc5\u987b\u5c06\u6240\u6709\u670d\u52a1\u548c\u4e2d\u95f4\u4ef6\u914d\u7f6e\u8f6c\u50a8\u5230 Program.cs \u4e2d\u3002\u6709\u5173\u66ff\u4ee3\u65b9\u6cd5\uff0c\u4f8b\u5982\u4f7f\u7528\u624b\u52a8\u8c03\u7528\u7684 Startup \u7c7b\u6216\u672c\u5730\u51fd\u6570\u6765\u5206\u9694\u914d\u7f6e\uff0c\u8bf7\u53c2\u9605\u6211\u5728 <a href=\"https:\/\/andrewlock.net\/exploring-dotnet-6-part-12-upgrading-a-dotnet-5-startup-based-app-to-dotnet-6\/\">https:\/\/andrewlock.net\/exploring-dotnet-6-part-12-upgrading-a-dotnet-5-startup-based-app-to-dotnet-6\/<\/a> \u4e0a\u7684\u535a\u5ba2\u6587\u7ae0\u3002<\/p>\n<p>In this chapter I provided a relatively quick overview of the generic host and Startup-based approach. If you\u2019re thinking of moving from the generic host to minimal hosting, or if you\u2019re familiar with minimal hosting but need to work with the generic host, you may \ufb01nd yourself looking around for an equivalent feature in the other hosting model. The documentation for migrating from .NET 5 to .NET 6 provides a good description of the di\ufb00erences between the two models, and how each individual feature has changed. You can \ufb01nd it at <a href=\"https:\/\/learn.microsoft.com\/zh-cn\/aspnet\/core\/migration\/50-to-60\">https:\/\/learn.microsoft.com\/zh-cn\/aspnet\/core\/migration\/50-to-60<\/a>.<br \/>\n\u5728\u672c\u7ae0\u4e2d\uff0c\u6211\u76f8\u5bf9\u5feb\u901f\u5730\u6982\u8ff0\u4e86\u901a\u7528\u4e3b\u673a\u548c\u57fa\u4e8e Startup \u7684\u65b9\u6cd5\u3002\u5982\u679c\u60a8\u6b63\u5728\u8003\u8651\u4ece\u901a\u7528\u4e3b\u673a\u8fc1\u79fb\u5230\u6700\u5c0f\u6258\u7ba1\uff0c\u6216\u8005\u5982\u679c\u60a8\u719f\u6089\u6700\u5c0f\u6258\u7ba1\u4f46\u9700\u8981\u4e0e\u901a\u7528\u4e3b\u673a\u5408\u4f5c\uff0c\u60a8\u53ef\u80fd\u4f1a\u53d1\u73b0\u81ea\u5df1\u5728\u53e6\u4e00\u79cd\u6258\u7ba1\u6a21\u578b\u4e2d\u5bfb\u627e\u7b49\u6548\u529f\u80fd\u3002\u4ece .NET 5 \u8fc1\u79fb\u5230 .NET 6 \u7684\u6587\u6863\u5f88\u597d\u5730\u63cf\u8ff0\u4e86\u4e24\u79cd\u6a21\u578b\u4e4b\u95f4\u7684\u5dee\u5f02\uff0c\u4ee5\u53ca\u6bcf\u4e2a\u5355\u72ec\u7684\u529f\u80fd\u662f\u5982\u4f55\u53d8\u5316\u7684\u3002\u60a8\u53ef\u4ee5\u5728 <a href=\"https:\/\/learn.microsoft.com\/zh-cn\/aspnet\/core\/migration\/50-to-60\">https:\/\/learn.microsoft.com\/zh-cn\/aspnet\/core\/migration\/50-to-60<\/a> \u627e\u5230\u5b83\u3002<\/p>\n<p><b>TIP<\/b>  Alternatively, David Fowler from the .NET team has a similar cheat sheet describing the migration. See <a href=\"https:\/\/gist.github.com\/davidfowl\/0e0372c3c1d895c3ce195ba983b1e03d\">https:\/\/gist.github.com\/davidfowl\/0e0372c3c1d895c3ce195ba983b1e03d<\/a> .<br \/>\n\u63d0\u793a\uff1a\u6216\u8005\uff0c\u6765\u81ea .NET \u56e2\u961f\u7684 David Fowler \u6709\u4e00\u4e2a\u7c7b\u4f3c\u7684\u5907\u5fd8\u5355\u6765\u63cf\u8ff0\u8fc1\u79fb\u3002\u8bf7\u53c2\u9605 <a href=\"https:\/\/gist.github.com\/davidfowl\/0e0372c3c1d895c3ce195ba983b1e03d\">https:\/\/gist.github.com\/davidfowl\/0e0372c3c1d895c3ce195ba983b1e03d<\/a> \u3002<\/p>\n<p>Whether you choose to use the generic host or minimal hosting, all the same ASP.NET Core concepts are there: con\ufb01guration, middleware, and DI. In the next chapter you\u2019ll learn about some more advanced uses of each of these concepts, such as creating branching middleware pipelines and custom DI containers.<br \/>\n\u65e0\u8bba\u60a8\u9009\u62e9\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u8fd8\u662f\u6700\u5c0f\u6258\u7ba1\uff0c\u6240\u6709\u76f8\u540c\u7684 ASP.NET Core \u6982\u5ff5\u90fd\u5b58\u5728\uff1a\u914d\u7f6e\u3001\u4e2d\u95f4\u4ef6\u548c DI\u3002\u5728\u4e0b\u4e00\u7ae0\u4e2d\uff0c\u60a8\u5c06\u4e86\u89e3\u8fd9\u4e9b\u6982\u5ff5\u7684\u4e00\u4e9b\u66f4\u9ad8\u7ea7\u7684\u7528\u6cd5\uff0c\u4f8b\u5982\u521b\u5efa\u5206\u652f\u4e2d\u95f4\u4ef6\u7ba1\u9053\u548c\u81ea\u5b9a\u4e49 DI \u5bb9\u5668\u3002<\/p>\n<h2>30.7 Summary<\/h2>\n<p>30.7 \u603b\u7ed3<\/p>\n<p>Before .NET 6, ASP.NET Core apps split con\ufb01guration between two \ufb01les: Program.cs and Startup.cs. Program.cs contains the entry point for the app and is used to con\ufb01gure and build a IHost object. Startup is where you con\ufb01gure the DI container, middleware pipeline, and endpoints for your app.<br \/>\n\u5728 .NET 6 \u4e4b\u524d\uff0cASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u5c06\u914d\u7f6e\u62c6\u5206\u4e3a\u4e24\u4e2a\u6587\u4ef6\uff1aProgram.cs \u548c Startup.cs\u3002Program.cs \u5305\u542b\u5e94\u7528\u7a0b\u5e8f\u7684\u5165\u53e3\u70b9\uff0c\u7528\u4e8e\u914d\u7f6e\u548c\u751f\u6210 IHost \u5bf9\u8c61\u3002Startup \uff08\u542f\u52a8\uff09 \u662f\u60a8\u4e3a\u5e94\u7528\u7a0b\u5e8f\u914d\u7f6e DI \u5bb9\u5668\u3001\u4e2d\u95f4\u4ef6\u7ba1\u9053\u548c\u7ec8\u7aef\u8282\u70b9\u7684\u5730\u65b9\u3002<\/p>\n<p>The Program class typically contains a method called CreateHostBuilder(), which creates an IHostBuilder instance. The Main entry point invokes CreateHostBuilder(), calls IHostBuilder.Build() to create an instance of IHost, and \ufb01nally runs the app by calling IHost.Run().<br \/>\nProgram \u7c7b\u901a\u5e38\u5305\u542b\u4e00\u4e2a\u540d\u4e3a CreateHostBuilder\uff08\uff09 \u7684\u65b9\u6cd5\uff0c\u8be5\u65b9\u6cd5\u521b\u5efa\u4e00\u4e2a IHostBuilder \u5b9e\u4f8b\u3002\u4e3b\u5165\u53e3\u70b9\u8c03\u7528 CreateHostBuilder\uff08\uff09\uff0c\u8c03\u7528 IHostBuilder.Build\uff08\uff09 \u6765\u521b\u5efa IHost \u7684\u5b9e\u4f8b\uff0c\u6700\u540e\u901a\u8fc7\u8c03\u7528 IHost.Run\uff08\uff09 \u8fd0\u884c\u5e94\u7528\u7a0b\u5e8f\u3002<\/p>\n<p>You can create an IHostBuilder by calling Host.CreateDefaultBuilder(). This creates a HostBuilder instance using the default con\ufb01guration, similar to the con\ufb01guration used when calling WebApplication.CreateBuilder(). The default HostBuilder uses default logging and con\ufb01guration providers, con\ufb01gures the hosting environment based on environment variables and command-line arguments, and con\ufb01gures the DI container settings.<br \/>\n\u60a8\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528 Host.CreateDefaultBuilder\uff08\uff09 \u6765\u521b\u5efa IHostBuilder\u3002\u8fd9\u5c06\u4f7f\u7528\u9ed8\u8ba4\u914d\u7f6e\u521b\u5efa\u4e00\u4e2a HostBuilder \u5b9e\u4f8b\uff0c\u7c7b\u4f3c\u4e8e\u8c03\u7528 WebApplication.CreateBuilder\uff08\uff09 \u65f6\u4f7f\u7528\u7684\u914d\u7f6e\u3002\u9ed8\u8ba4 HostBuilder \u4f7f\u7528\u9ed8\u8ba4\u65e5\u5fd7\u8bb0\u5f55\u548c\u914d\u7f6e\u63d0\u4f9b\u7a0b\u5e8f\uff0c\u6839\u636e\u73af\u5883\u53d8\u91cf\u548c\u547d\u4ee4\u884c\u53c2\u6570\u914d\u7f6e\u6258\u7ba1\u73af\u5883\uff0c\u5e76\u914d\u7f6e DI \u5bb9\u5668\u8bbe\u7f6e\u3002<\/p>\n<p>ASP.NET Core apps using the generic host typically call ConfigureWebHostDefaults(), on the HostBuilder, providing a lambda that calls <code>UseStartup&lt;Startup&gt;()<\/code> on an IWebHostBuilder instance. This tells the HostBuilder to con\ufb01gure the DI container and middleware pipeline based on the Startup class.<br \/>\n\u4f7f\u7528\u901a\u7528\u4e3b\u673a\u7684 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u901a\u5e38\u5728 HostBuilder \u4e0a\u8c03\u7528 ConfigureWebHostDefaults\uff08\uff09\uff0c\u4ece\u800c\u63d0\u4f9b\u5728 IWebHostBuilder \u5b9e\u4f8b\u4e0a\u8c03\u7528 <code>UseStartup&lt;Startup&gt;()<\/code> \u7684 lambda\u3002\u8fd9\u4f1a\u544a\u8bc9 HostBuilder \u6839\u636e Startup \u7c7b\u914d\u7f6e DI \u5bb9\u5668\u548c\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002<\/p>\n<p>Use the Startup class to register services with DI, con\ufb01gure your middleware pipeline, and register your endpoints. It is a conventional class, in that it doesn\u2019t have to implement an interface or base class. Instead, the IHostBuilder looks for speci\ufb01c named methods to invoke using re\ufb02ection.<br \/>\n\u4f7f\u7528 Startup \u7c7b\u5411 DI \u6ce8\u518c\u670d\u52a1\u3001\u914d\u7f6e\u4e2d\u95f4\u4ef6\u7ba1\u9053\u5e76\u6ce8\u518c\u7ec8\u7aef\u8282\u70b9\u3002\u5b83\u662f\u4e00\u4e2a\u7ea6\u5b9a\u4fd7\u6210\u7684\u7c7b\uff0c\u56e0\u4e3a\u5b83\u4e0d\u5fc5\u5b9e\u73b0\u63a5\u53e3\u6216\u57fa\u7c7b\u3002\u76f8\u53cd\uff0cIHostBuilder \u4f1a\u67e5\u627e\u8981\u4f7f\u7528\u53cd\u5c04\u8c03\u7528\u7684\u7279\u5b9a\u547d\u540d\u65b9\u6cd5\u3002<\/p>\n<p>Register your DI services in the ConfigureServices(IServiceCollection) method of Startup. You register services using the same Add<em> methods you use to register services on WebApplicationBuilder.Services when using minimal hosting.<br \/>\n\u5728 Startup \u7684 ConfigureServices\uff08IServiceCollection\uff09 \u65b9\u6cd5\u4e2d\u6ce8\u518c DI \u670d\u52a1\u3002\u4f7f\u7528\u6700\u5c0f\u6258\u7ba1\u65f6\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528\u5728 WebApplicationBuilder.Services \u4e0a\u6ce8\u518c\u670d\u52a1\u65f6\u4f7f\u7528\u7684\u76f8\u540c Add<\/em> \u65b9\u6cd5\u6ce8\u518c\u670d\u52a1\u3002<\/p>\n<p>If you need to access your app\u2019s IConfiguration or IWebHostEnvironment (exposed as Configuration and Environment, respectively, on WebApplicationBuilder), you can inject them into your Startup constructor.You can\u2019t inject any other services into the Startup constructor.<br \/>\n\u5982\u679c\u9700\u8981\u8bbf\u95ee\u5e94\u7528\u7a0b\u5e8f\u7684 IConfiguration \u6216 IWebHostEnvironment\uff08\u5728 WebApplicationBuilder \u4e0a\u5206\u522b\u4f5c\u4e3a Configuration \u548c Environment \u516c\u5f00\uff09\uff0c\u5219\u53ef\u4ee5\u5c06\u5b83\u4eec\u6ce8\u5165\u5230 Startup \u6784\u9020\u51fd\u6570\u4e2d\u3002\u60a8\u4e0d\u80fd\u5c06\u4efb\u4f55\u5176\u4ed6\u670d\u52a1\u6ce8\u5165 Startup \u6784\u9020\u51fd\u6570\u3002<\/p>\n<p>Register your middleware pipeline in Startup.Configure(IApplicationBuilder). Use the same Use<em> methods you use with WebApplication to add middleware to the pipeline. As for WebApplication, the order in which you add the middleware de\ufb01nes their order in the pipeline.<br \/>\n\u5728 Startup.Configure \uff08IApplicationBuilder\uff09 \u4e2d\u6ce8\u518c\u4e2d\u95f4\u4ef6\u7ba1\u9053\u3002\u4f7f\u7528\u4e0e WebApplication \u76f8\u540c\u7684 Use<\/em> \u65b9\u6cd5\u5c06\u4e2d\u95f4\u4ef6\u6dfb\u52a0\u5230\u7ba1\u9053\u4e2d\u3002\u5bf9\u4e8e WebApplication\uff0c\u60a8\u6dfb\u52a0\u4e2d\u95f4\u4ef6\u7684\u987a\u5e8f\u5b9a\u4e49\u4e86\u5b83\u4eec\u5728\u7ba1\u9053\u4e2d\u7684\u987a\u5e8f\u3002<\/p>\n<p>WebApplication automatically adds middleware such as the routing middleware and endpoint middleware to the pipeline when you\u2019re using minimal hosting. When using Startup, you must explicitly add this middleware yourself.<br \/>\n\u5f53\u60a8\u4f7f\u7528\u6700\u5c0f\u6258\u7ba1\u65f6\uff0cWebApplication \u4f1a\u81ea\u52a8\u5c06\u4e2d\u95f4\u4ef6\uff08\u5982\u8def\u7531\u4e2d\u95f4\u4ef6\u548c\u7ec8\u7aef\u8282\u70b9\u4e2d\u95f4\u4ef6\uff09\u6dfb\u52a0\u5230\u7ba1\u9053\u4e2d\u3002\u4f7f\u7528 Startup \u65f6\uff0c\u60a8\u5fc5\u987b\u81ea\u5df1\u663e\u5f0f\u6dfb\u52a0\u6b64\u4e2d\u95f4\u4ef6\u3002<\/p>\n<p>To register endpoints, call UseEndpoints(endpoints =&gt; {}) and call the appropriate Map<em> functions on the provided IEndpointRouteBuilder in the lambda function. This di\ufb00ers signi\ufb01cantly from minimal hosting, in which you can call Map<\/em> directly on the WebApplication instance.<br \/>\n\u8981\u6ce8\u518c\u7ec8\u7aef\u8282\u70b9\uff0c\u8bf7\u8c03\u7528 UseEndpoints\uff08endpoints =&gt; {}\uff09 \u5e76\u5728 lambda \u51fd\u6570\u4e2d\u63d0\u4f9b\u7684 IEndpointRouteBuilder \u4e0a\u8c03\u7528\u76f8\u5e94\u7684 Map \u51fd\u6570\u3002\u8fd9\u4e0e\u6700\u5c0f\u6258\u7ba1\u6709\u5f88\u5927\u4e0d\u540c\uff0c\u5728\u6700\u5c0f\u6258\u7ba1\u4e2d\uff0c\u60a8\u53ef\u4ee5\u76f4\u63a5\u5728 WebApplication \u5b9e\u4f8b\u4e0a\u8c03\u7528 Map\u3002<\/p>\n<p>You can customize the IHostBuilder instance by adding con\ufb01guration methods such as ConfigureLogging() or ConfigureAppConfiguration(). These methods run after any previous invocations, adding extra layers of con\ufb01guration to the IHostBuilder instance.<br \/>\n\u60a8\u53ef\u4ee5\u901a\u8fc7\u6dfb\u52a0\u914d\u7f6e\u65b9\u6cd5\uff08\u5982 ConfigureLogging\uff08\uff09 \u6216 ConfigureAppConfiguration\uff08\uff09\uff09\u6765\u81ea\u5b9a\u4e49 IHostBuilder \u5b9e\u4f8b\u3002\u8fd9\u4e9b\u65b9\u6cd5\u5728\u4e4b\u524d\u7684\u4efb\u4f55\u8c03\u7528\u4e4b\u540e\u8fd0\u884c\uff0c\u5411 IHostBuilder \u5b9e\u4f8b\u6dfb\u52a0\u989d\u5916\u7684\u914d\u7f6e\u5c42\u3002<\/p>\n<p>The generic host is \ufb02exible but has greater inherent complexity due to its deferred execution style, extensive use of lambda methods, and heavy use of convention. Minimal hosting aimed to simplify the bootstrapping code to make it more imperative, reducing much of the indirection.<br \/>\n\u6cdb\u578b\u4e3b\u673a\u5f88\u7075\u6d3b\uff0c\u4f46\u7531\u4e8e\u5176\u5ef6\u8fdf\u6267\u884c\u6837\u5f0f\u3001\u5e7f\u6cdb\u4f7f\u7528 lambda \u65b9\u6cd5\u548c\u5927\u91cf\u4f7f\u7528\u7ea6\u5b9a\uff0c\u56e0\u6b64\u5177\u6709\u66f4\u5927\u7684\u56fa\u6709\u590d\u6742\u6027\u3002\u6700\u5c0f\u6258\u7ba1\u65e8\u5728\u7b80\u5316\u5f15\u5bfc\u4ee3\u7801\uff0c\u4f7f\u5176\u66f4\u52a0\u5fc5\u8981\uff0c\u4ece\u800c\u51cf\u5c11\u5927\u90e8\u5206\u95f4\u63a5\u6027\u3002<\/p>\n<p>Minimal hosting enforces more defaults but is generally easier to work with for newcomers to ASP.NET Core.<br \/>\n\u6700\u5c0f\u6258\u7ba1\u5f3a\u5236\u5b9e\u65bd\u66f4\u591a\u9ed8\u8ba4\u503c\uff0c\u4f46\u901a\u5e38\u66f4\u5bb9\u6613\u4f7f\u7528 ASP.NET Core \u7684\u65b0\u624b\u3002<\/p>\n<p>If you already have an ASP.NET Core application using Startup and the generic host, there\u2019s no need to switch to using WebApplication and minimal hosting; the generic host is fully supported in .NET 7. Additionally, if you\u2019re creating a non- HTTP application, the generic host is currently the best option.<br \/>\n\u5982\u679c\u60a8\u5df2\u7ecf\u62e5\u6709\u4f7f\u7528 Startup \u548c\u901a\u7528\u4e3b\u673a\u7684 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\uff0c\u5219\u65e0\u9700\u5207\u6362\u5230\u4f7f\u7528 WebApplication \u548c\u6700\u5c0f\u6258\u7ba1;.NET 7 \u5b8c\u5168\u652f\u6301\u6cdb\u578b\u4e3b\u673a\u3002\u6b64\u5916\uff0c\u5982\u679c\u8981\u521b\u5efa\u975e HTTP \u5e94\u7528\u7a0b\u5e8f\uff0c\u5219\u901a\u7528\u4e3b\u673a\u662f\u5f53\u524d\u6700\u4f73\u9009\u9879\u3002<\/p>\n<p>If you\u2019re creating a new ASP.NET Core application, minimal hosting will likely provide a smoother experience. You should generally favor it over the generic host for new apps unless you need \ufb01ne control of the IHostBuilder con\ufb01guration.<br \/>\n\u5982\u679c\u60a8\u6b63\u5728\u521b\u5efa\u65b0\u7684 ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\uff0c\u6700\u5c0f\u6258\u7ba1\u53ef\u80fd\u4f1a\u63d0\u4f9b\u66f4\u6d41\u7545\u7684\u4f53\u9a8c\u3002\u5bf9\u4e8e\u65b0\u5e94\u7528\u7a0b\u5e8f\uff0c\u60a8\u901a\u5e38\u5e94\u8be5\u66f4\u559c\u6b22\u5b83\u800c\u4e0d\u662f\u901a\u7528\u4e3b\u673a\uff0c\u9664\u975e\u60a8\u9700\u8981\u5bf9 IHostBuilder \u914d\u7f6e\u8fdb\u884c\u7cbe\u7ec6\u63a7\u5236\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Part 5 Going further with ASP.NET Core\u200c \u7b2c 5 \u90e8\u5206\uff1a\u8fdb\u4e00\u6b65\u4e86\u89e3 ASP.NET Core Parts 1 through 4 of this book touched on all the aspects of ASP.NET Core you need to learn to build an HTTP application, whether that\u2019s server-rendered applications using Razor Pages or JavaScript Object Notation (JSON) APIs using minimal APIs. In part 5 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-631","post","type-post","status-publish","format-standard","hentry","category-csharp"],"_links":{"self":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/631","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=631"}],"version-history":[{"count":0,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/631\/revisions"}],"wp:attachment":[{"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=631"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=631"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=631"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}