{"id":136,"date":"2022-08-24T19:37:13","date_gmt":"2022-08-24T11:37:13","guid":{"rendered":"https:\/\/miie.net\/?p=136"},"modified":"2022-08-24T19:37:13","modified_gmt":"2022-08-24T11:37:13","slug":"ultimate-asp-net-core-web-api-chapter1-project-configuration","status":"publish","type":"post","link":"https:\/\/diji.net\/?p=136","title":{"rendered":"Chapter1:PROJECT CONFIGURATION"},"content":{"rendered":"<h1>1 PROJECT CONFIGURATION<\/h1>\n<p>Configuration in .NET Core is very different from what we\u2019re used to in .NET Framework projects. We don\u2019t use the web.config file anymore, but instead, use a built-in Configuration framework that comes out-of-the-box in .NET Core.<br \/>\n.NET Core \u4e2d\u7684\u914d\u7f6e\u4e0e\u6211\u4eec\u4e60\u60ef \u7684\u914d\u7f6e\u975e\u5e38\u4e0d\u540c.NET Framework \u9879\u76ee\u3002\u6211\u4eec\u4e0d\u518d\u4f7f\u7528 web.config \u6587\u4ef6\uff0c\u800c\u662f\u4f7f\u7528\u5728 .NET Core \u4e2d\u5f00\u7bb1\u5373\u7528\u7684\u5185\u7f6e\u914d\u7f6e\u6846\u67b6\u3002  <\/p>\n<\/p>\n<p>To be able to develop good applications, we need to understand how to configure our application and its services first.<br \/>\n\u4e3a\u4e86\u80fd\u591f\u5f00\u53d1\u826f\u597d\u7684\u5e94\u7528\u7a0b\u5e8f\uff0c\u6211\u4eec\u9700\u8981\u9996\u5148\u4e86\u89e3\u5982\u4f55\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u53ca\u5176\u670d\u52a1\u3002<\/p>\n<p>In this section, we\u2019ll learn about configuration methods in the Startup class and set up our application. We will also learn how to register different services and how to use extension methods to achieve this.<br \/>\n\u5728\u672c\u8282\u4e2d\uff0c\u6211\u4eec\u5c06\u4e86\u89e3 Startup \u7c7b\u4e2d\u7684\u914d\u7f6e\u65b9\u6cd5\u5e76\u8bbe\u7f6e\u6211\u4eec\u7684\u5e94\u7528\u7a0b\u5e8f\u3002\u6211\u4eec\u8fd8\u5c06\u5b66\u4e60\u5982\u4f55\u6ce8\u518c\u4e0d\u540c\u7684\u670d\u52a1\uff0c\u4ee5\u53ca\u5982\u4f55\u4f7f\u7528\u6269\u5c55\u65b9\u6cd5\u6765\u5b9e\u73b0\u8fd9\u4e00\u76ee\u6807\u3002<\/p>\n<p>Of course, the first thing we need to do is to create a new project, so, let\u2019s dive right into it.<br \/>\n\u5f53\u7136\uff0c\u6211\u4eec\u9700\u8981\u505a\u7684\u7b2c\u4e00\u4ef6\u4e8b\u5c31\u662f\u521b\u5efa\u4e00\u4e2a\u65b0\u9879\u76ee\uff0c\u6240\u4ee5\uff0c\u8ba9\u6211\u4eec\u6df1\u5165\u7814\u7a76\u5b83\u3002  <\/p>\n<h2>1.1 Creating a New Project<\/h2>\n<p>Let's open Visual Studio and create a new ASP.NET Core Web Application:<br \/>\n\u8ba9\u6211\u4eec\u6253\u5f00Visual Studio\u5e76\u521b\u5efa\u4e00\u4e2a\u65b0\u7684 ASP.NET \u6838\u5fc3Web\u5e94\u7528\u7a0b\u5e8f\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824ultimate-asp-net-core-web-api\/Image_1001.jpg\" alt=\"alt\" \/><\/p>\n<p>Now let\u2019s choose a name and location for our project:<br \/>\n\u73b0\u5728\uff0c\u8ba9\u6211\u4eec\u4e3a\u9879\u76ee\u9009\u62e9\u4e00\u4e2a\u540d\u79f0\u548c\u4f4d\u7f6e\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824ultimate-asp-net-core-web-api\/Image_1002.gif\" alt=\"alt\" \/><\/p>\n<p>Next, we want to choose a .NET Core and ASP.NET Core 5.0 from the dropdown lists respectively. Also, we don\u2019t want to enable OpenAPI support right now. We\u2019ll do that later in the book on our own. Now we can proceed by clicking the Create button and the project will start initializing:<br \/>\n\u63a5\u4e0b\u6765\uff0c\u6211\u4eec\u8981\u5206\u522b\u4ece\u4e0b\u62c9\u5217\u8868\u4e2d\u9009\u62e9 .NET Core \u548c ASP.NET Core 5.0\u3002\u6b64\u5916\uff0c\u6211\u4eec\u73b0\u5728\u4e0d\u60f3\u542f\u7528OpenAPI\u652f\u6301\u3002\u6211\u4eec\u5c06\u5728\u672c\u4e66\u7684\u540e\u9762\u81ea\u5df1\u505a\u8fd9\u4ef6\u4e8b\u3002\u73b0\u5728\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u5355\u51fb\u201c\u521b\u5efa\u201d\u6309\u94ae\u7ee7\u7eed\uff0c\u9879\u76ee\u5c06\u5f00\u59cb\u521d\u59cb\u5316\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824ultimate-asp-net-core-web-api\/Image_1003.jpg\" alt=\"alt\" \/><\/p>\n<h2>1.2  launchSettings.json File Configuration<\/h2>\n<p>After the project has been created, we are going to modify the <strong>launchSettings.json<\/strong> file, which can be found in the Properties section of the Solution Explorer window.<br \/>\n\u521b\u5efa\u9879\u76ee\u540e\uff0c\u6211\u4eec\u5c06\u4fee\u6539 <strong>launchSettings.json<\/strong> \u6587\u4ef6\uff0c\u8be5\u6587\u4ef6\u53ef\u5728\u201c\u89e3\u51b3\u65b9\u6848\u8d44\u6e90\u7ba1\u7406\u5668\u201d\u7a97\u53e3\u7684\u201c\u5c5e\u6027\u201d\u90e8\u5206\u4e2d\u627e\u5230\u3002<\/p>\n<p>This configuration determines the launch behavior of the ASP.NET Core applications. As we can see, it contains both configurations to launch settings for IIS and self-hosted applications (Kestrel).<br \/>\n\u6b64\u914d\u7f6e\u786e\u5b9a ASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u7684\u542f\u52a8\u884c\u4e3a\u3002\u6b63\u5982\u6211\u4eec\u6240\u770b\u5230\u7684\uff0c\u5b83\u5305\u542b\u542f\u52a8IIS\u548c\u81ea\u627f\u8f7d\u5e94\u7528\u7a0b\u5e8f\uff08Kestrel\uff09\u8bbe\u7f6e\u7684\u4e24\u79cd\u914d\u7f6e\u3002<\/p>\n<p>For now, let\u2019s change the <strong>launchBrowser<\/strong> property to false to prevent the web browser from launching on application start.<br \/>\n\u73b0\u5728\uff0c\u8ba9\u6211\u4eec\u5c06 <strong>launchBrowser<\/strong> \u5c5e\u6027\u66f4\u6539\u4e3a false\uff0c\u4ee5\u9632\u6b62 Web \u6d4f\u89c8\u5668\u5728\u5e94\u7528\u7a0b\u5e8f\u542f\u52a8\u65f6\u542f\u52a8\u3002<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n{\n  &quot;$schema&quot;: &quot;http:\/\/json.schemastore.org\/launchsettings.json&quot;,\n  &quot;iisSettings&quot;: {\n    &quot;windowsAuthentication&quot;: false,\n    &quot;anonymousAuthentication&quot;: true,\n    &quot;iisExpress&quot;: {\n      &quot;applicationUrl&quot;: &quot;http:\/\/localhost:58753&quot;,\n      &quot;sslPort&quot;: 44370\n    }\n  },\n  &quot;profiles&quot;: {\n    &quot;IIS Express&quot;: {\n      &quot;commandName&quot;: &quot;IISExpress&quot;,\n      &quot;launchBrowser&quot;: false,\n      &quot;launchUrl&quot;: &quot;weatherforecast&quot;,\n      &quot;environmentVariables&quot;: { &quot;ASPNETCORE_ENVIRONMENT&quot;: &quot;Development&quot; }\n    },\n    &quot;CompanyEmployees&quot;: {\n      &quot;commandName&quot;: &quot;Project&quot;,\n      &quot;dotnetRunMessages&quot;: &quot;true&quot;,\n      &quot;launchBrowser&quot;: false,\n      &quot;launchUrl&quot;: &quot;weatherforecast&quot;,\n      &quot;applicationUrl&quot;: &quot;https:\/\/localhost:5001;http:\/\/localhost:5000&quot;,\n      &quot;environmentVariables&quot;: { &quot;ASPNETCORE_ENVIRONMENT&quot;: &quot;Development&quot; }\n    }\n  }\n}\n<\/pre>\n<\/p>\n<p>This is convenient since we are developing a Web API project and we don\u2019t need a browser to check our API out. We will use Postman (described later) for this purpose.<br \/>\n\u8fd9\u5f88\u65b9\u4fbf\uff0c\u56e0\u4e3a\u6211\u4eec\u6b63\u5728\u5f00\u53d1\u4e00\u4e2aWeb API\u9879\u76ee\uff0c\u6211\u4eec\u4e0d\u9700\u8981\u6d4f\u89c8\u5668\u6765\u68c0\u67e5\u6211\u4eec\u7684API\u3002\u6211\u4eec\u5c06\u4f7f\u7528Postman\uff08\u7a0d\u540e\u63cf\u8ff0\uff09\u6765\u5b9e\u73b0\u6b64\u76ee\u7684\u3002<\/p>\n<p>If you\u2019ve checked Configure for HTTPS checkbox earlier in the setup phase, you will end up with two URLs in the applicationUrl section \u2014 one for HTTP, and one for HTTPS.<br \/>\n\u5982\u679c\u5728\u8bbe\u7f6e\u9636\u6bb5\u4e4b\u524d\u9009\u4e2d\u4e86\u201c\u4e3a HTTPS \u914d\u7f6e\u201d\u590d\u9009\u6846\uff0c\u5219\u6700\u7ec8\u5c06\u5728 applicationUrl \u90e8\u5206\u4e2d\u5f97\u5230\u4e24\u4e2a URL \u2014 \u4e00\u4e2a\u7528\u4e8e HTTP\uff0c\u53e6\u4e00\u4e2a\u7528\u4e8e HTTPS\u3002<\/p>\n<p>You\u2019ll also notice the <strong>sslPort<\/strong> property which indicates that our application, when running in IISExpress, will be configured for HTTPS (port 44370), too.<br \/>\n\u60a8\u8fd8\u4f1a\u6ce8\u610f\u5230 <strong>sslPort<\/strong> \u5c5e\u6027\uff0c\u8be5\u5c5e\u6027\u6307\u793a\u6211\u4eec\u7684\u5e94\u7528\u7a0b\u5e8f\u5728 IISExpress \u4e2d\u8fd0\u884c\u65f6\u4e5f\u5c06\u914d\u7f6e\u4e3a HTTPS\uff08\u7aef\u53e3 44370\uff09\u3002<\/p>\n<p>Additional info: Take note that this HTTPS configuration is only valid in the local environment. You will have to configure a valid certificate and HTTPS redirection once you deploy the application.<br \/>\n<strong>\u5176\u4ed6\u4fe1\u606f\uff1a<\/strong>\u8bf7\u6ce8\u610f\uff0c\u6b64 HTTPS \u914d\u7f6e\u4ec5\u5728\u672c\u5730\u73af\u5883\u4e2d\u6709\u6548\u3002\u90e8\u7f72\u5e94\u7528\u7a0b\u5e8f\u540e\uff0c\u5fc5\u987b\u914d\u7f6e\u6709\u6548\u7684\u8bc1\u4e66\u548c HTTPS \u91cd\u5b9a\u5411\u3002<\/p>\n<p>There is one more useful property for developing applications locally and that\u2019s the <strong>launchUrl<\/strong> property. This property determines which URL will the application navigate to initially. For <strong>launchUrl<\/strong> property to work, we need to set the launchBrowser property to true. So, for example, if we set the <strong>launchUrl<\/strong> property to weatherforecast, we will be redirected to <a href=\"https:\/\/localhost:5001\/weatherforecast\"><a href=\"https:\/\/localhost:5001\/weatherforecast\"><a href=\"https:\/\/localhost:5001\/weatherforecast\">https:\/\/localhost:5001\/weatherforecast<\/a><\/a><\/a> when we launch our application.<br \/>\n\u8fd8\u6709\u4e00\u4e2a\u7528\u4e8e\u672c\u5730\u5f00\u53d1\u5e94\u7528\u7a0b\u5e8f\u6709\u7528\u7684\u5c5e\u6027\uff0c\u90a3\u5c31\u662f <strong>launchUrl<\/strong> \u5c5e\u6027\u3002\u6b64\u5c5e\u6027\u786e\u5b9a\u5e94\u7528\u7a0b\u5e8f\u6700\u521d\u5c06\u5bfc\u822a\u5230\u54ea\u4e2a URL\u3002\u8981\u4f7f <strong>launchUrl<\/strong> \u5c5e\u6027\u6b63\u5e38\u5de5\u4f5c\uff0c\u6211\u4eec\u9700\u8981\u5c06 launchBrowser \u5c5e\u6027\u8bbe\u7f6e\u4e3a true\u3002\u56e0\u6b64\uff0c\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u5c06 <strong>launchUrl<\/strong> \u5c5e\u6027\u8bbe\u7f6e\u4e3a weatherforecast\uff0c\u5219\u5728\u542f\u52a8\u5e94\u7528\u7a0b\u5e8f\u65f6\uff0c\u6211\u4eec\u5c06\u88ab\u91cd\u5b9a\u5411\u5230 <a href=\"https:\/\/localhost:5001\/weatherforecast\"><a href=\"https:\/\/localhost:5001\/weatherforecast\"><a href=\"https:\/\/localhost:5001\/weatherforecast\">https:\/\/localhost:5001\/weatherforecast<\/a><\/a><\/a>\u3002<\/p>\n<h2>1.3 Program.cs  and  Startup.cs  Explanations<\/h2>\n<p><strong>Program.cs<\/strong> is the entry point to our application and it looks like this:<br \/>\n<strong>Program.cs<\/strong>\u662f\u6211\u4eec\u5e94\u7528\u7a0b\u5e8f\u7684\u5165\u53e3\u70b9\uff0c\u5b83\u770b\u8d77\u6765\u50cf\u8fd9\u6837\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nnamespace CompanyEmployees\n{\n    public class Program\n    {\n        public static void Main(string&#x5B;] args)\n        {\n            CreateHostBuilder(args).Build().Run();\n        }\n\n        public static IHostBuilder CreateHostBuilder(string&#x5B;] args) =&gt;\n            Host.CreateDefaultBuilder(args)\n                .ConfigureWebHostDefaults(webBuilder =&gt;\n                {\n                    webBuilder.UseStartup&lt;Startup&gt;();\n                });\n    }\n}\n<\/pre>\n<\/p>\n<p>If you are familiar with how things work in .NET Core 1.0, you will find this code considerably smaller than it used to be.<br \/>\n\u5982\u679c\u60a8\u719f\u6089 .NET Core 1.0 \u4e2d\u7684\u5de5\u4f5c\u65b9\u5f0f\uff0c\u60a8\u4f1a\u53d1\u73b0\u6b64\u4ee3\u7801\u6bd4\u4ee5\u524d\u5c0f\u5f97\u591a\u3002<\/p>\n<p>You might wonder why some parts are missing like the <strong>UseKestrel()<\/strong> or the <strong>UseIISIntegration()<\/strong>. The <strong>CreateDefaultBuilder(args)<\/strong> method encapsulates all that stuff and makes this code more readable, but it keeps all the magic present. You can still fine grain the configuration if you want to.<br \/>\n\u60a8\u53ef\u80fd\u60f3\u77e5\u9053\u4e3a\u4ec0\u4e48\u7f3a\u5c11\u67d0\u4e9b\u90e8\u5206\uff0c\u4f8b\u5982<strong>UseKestrel()<\/strong>\u6216<strong>UseIISIntegration()<\/strong> \u3002 <strong>CreateDefaultBuilder(args)<\/strong> \u65b9\u6cd5\u5c01\u88c5\u4e86\u6240\u6709\u8fd9\u4e9b\u4e1c\u897f\uff0c\u5e76\u4f7f\u6b64\u4ee3\u7801\u66f4\u5177\u53ef\u8bfb\u6027\uff0c\u4f46\u5b83\u4fdd\u7559\u4e86\u6240\u6709\u795e\u5947\u7684\u5b58\u5728\u3002\u5982\u679c\u9700\u8981\uff0c\u60a8\u4ecd\u7136\u53ef\u4ee5\u7ec6\u7c92\u5ea6\u914d\u7f6e\u3002<\/p>\n<p>The <strong>CreateDefaultBuilder(args)<\/strong> method sets the default files and variables for the project and logger configuration. The fact that the logger is configured earlier in the bootstrapping process means we can log issues that happen during bootstrapping as well, which was a bit harder in previous versions.<br \/>\n<strong>CreateDefaultBuilder(args)<\/strong> \u65b9\u6cd5\u4e3a\u9879\u76ee\u548c\u8bb0\u5f55\u5668\u914d\u7f6e\u8bbe\u7f6e\u9ed8\u8ba4\u6587\u4ef6\u548c\u53d8\u91cf\u3002\u8bb0\u5f55\u5668\u662f\u5728\u5f15\u5bfc\u8fc7\u7a0b\u7684\u65e9\u671f\u914d\u7f6e\u7684\uff0c\u8fd9\u610f\u5473\u7740\u6211\u4eec\u4e5f\u53ef\u4ee5\u8bb0\u5f55\u5728\u5f15\u5bfc\u8fc7\u7a0b\u4e2d\u53d1\u751f\u7684\u95ee\u9898\uff0c\u8fd9\u5728\u4ee5\u524d\u7684\u7248\u672c\u4e2d\u6709\u70b9\u56f0\u96be\u3002<\/p>\n<p>After that, we can call <strong>webBuilder.UseStartup<Startup>()<\/strong> to initialize the <strong>Startup<\/strong> class too. The<strong> Startup<\/strong> class is mandatory in ASP.NET Core Web API projects. In the Startup class, we configure the embedded or custom services that our application needs.<br \/>\n\u4e4b\u540e\uff0c\u6211\u4eec\u53ef\u4ee5\u8c03\u7528<strong>webBuilder.UseStartup<Startup>()<\/strong>\u6765\u521d\u59cb\u5316<strong>Startup<\/strong>\u7c7b\u3002\u542f\u52a8\u7c7b\u5728\u6838\u5fc3 Web API \u9879\u76ee\u4e2d\u662f\u5fc5\u9700\u7684 ASP.NET\u3002\u5728<strong> Startup<\/strong> \u7c7b\u4e2d\uff0c\u6211\u4eec\u914d\u7f6e\u5e94\u7528\u7a0b\u5e8f\u6240\u9700\u7684\u5d4c\u5165\u5f0f\u6216\u81ea\u5b9a\u4e49\u670d\u52a1\u3002<\/p>\n<p>When we open the Startup class, we can find the constructor and the two methods which we\u2019ll extend quite a few times during our application development.<br \/>\n\u5f53\u6211\u4eec\u6253\u5f00 Startup \u7c7b\u65f6\uff0c\u6211\u4eec\u53ef\u4ee5\u627e\u5230\u6784\u9020\u51fd\u6570\u548c\u4e24\u4e2a\u65b9\u6cd5\uff0c\u6211\u4eec\u5c06\u5728\u5e94\u7528\u7a0b\u5e8f\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u6269\u5c55\u5b83\u4eec\u5f88\u591a\u6b21\u3002<\/p>\n<p>As the method name indicates, the <strong>ConfigureServices<\/strong> method is used to do exactly that: configure our services. A service is a reusable part of the code that adds some functionality to our application.<br \/>\n\u6b63\u5982\u65b9\u6cd5\u540d\u79f0\u6240\u793a\uff0c<strong>ConfigureServices<\/strong> \u65b9\u6cd5\u6b63\u662f\u7528\u6765\u505a\u5230\u8fd9\u4e00\u70b9\u7684\uff1a\u914d\u7f6e\u6211\u4eec\u7684\u670d\u52a1\u3002\u670d\u52a1\u662f\u4ee3\u7801\u7684\u53ef\u91cd\u7528\u90e8\u5206\uff0c\u5b83\u4e3a\u6211\u4eec\u7684\u5e94\u7528\u7a0b\u5e8f\u6dfb\u52a0\u4e86\u4e00\u4e9b\u529f\u80fd\u3002<\/p>\n<p>In the <strong>Configure<\/strong> method, we are going to add different middleware components to the application\u2019s request pipeline.<br \/>\n\u5728 <strong>Configure<\/strong> \u65b9\u6cd5\u4e2d\uff0c\u6211\u4eec\u5c06\u5411\u5e94\u7528\u7a0b\u5e8f\u7684\u8bf7\u6c42\u7ba1\u9053\u6dfb\u52a0\u4e0d\u540c\u7684\u4e2d\u95f4\u4ef6\u7ec4\u4ef6\u3002<\/p>\n<p>Since larger applications could potentially contain a lot of different services, we can end up with a lot of clutter and unreadable code in the <strong>ConfigureServices<\/strong> method. To make it more readable for the next person and ourselves, we can structure the code into logical blocks and separate those blocks into extension methods.<br \/>\n\u7531\u4e8e\u8f83\u5927\u7684\u5e94\u7528\u7a0b\u5e8f\u53ef\u80fd\u5305\u542b\u8bb8\u591a\u4e0d\u540c\u7684\u670d\u52a1\uff0c\u56e0\u6b64\u6211\u4eec\u6700\u7ec8\u53ef\u80fd\u4f1a\u5728 <strong>ConfigureServices<\/strong> \u65b9\u6cd5\u4e2d\u4ea7\u751f\u5927\u91cf\u6df7\u4e71\u548c\u4e0d\u53ef\u8bfb\u7684\u4ee3\u7801 \u3002\u4e3a\u4e86\u4f7f\u4e0b\u4e00\u4e2a\u4eba\u548c\u6211\u4eec\u81ea\u5df1\u66f4\u5177\u53ef\u8bfb\u6027\uff0c\u6211\u4eec\u53ef\u4ee5\u5c06\u4ee3\u7801\u7ed3\u6784\u4e3a\u903b\u8f91\u5757\uff0c\u5e76\u5c06\u8fd9\u4e9b\u5757\u5206\u79bb\u4e3a\u6269\u5c55\u65b9\u6cd5\u3002<\/p>\n<h2>1.4 Extension Methods and CORS Configuration<\/h2>\n<p>An extension method is inherently a static method. What makes it different from other static methods is that it accepts <strong>this<\/strong> as the first parameter, and <strong>this<\/strong> represents the data type of the object which will be using that extension method. We\u2019ll see what that means in a moment.<br \/>\n\u6269\u5c55\u65b9\u6cd5\u672c\u8d28\u4e0a\u662f\u4e00\u79cd\u9759\u6001\u65b9\u6cd5\u3002\u5b83\u4e0e\u5176\u4ed6\u9759\u6001\u65b9\u6cd5\u7684\u4e0d\u540c\u4e4b\u5904\u5728\u4e8e\uff0c\u5b83\u63a5\u53d7\u6b64\u53c2\u6570\u4f5c\u4e3a\u7b2c\u4e00\u4e2a\u53c2\u6570\uff0c\u8fd9\u8868\u793a\u5c06\u4f7f\u7528\u8be5\u6269\u5c55\u65b9\u6cd5\u7684\u5bf9\u8c61\u7684\u6570\u636e\u7c7b\u578b\u3002\u6211\u4eec\u7a0d\u540e\u4f1a\u660e\u767d\u8fd9\u610f\u5473\u7740\u4ec0\u4e48\u3002<\/p>\n<p>An extension method must be defined inside a static class. This kind of method extends the behavior of a type in .NET. Once we define an extension method, it can be chained multiple times on the same type of object.<br \/>\n\u5fc5\u987b\u5728\u9759\u6001\u7c7b\u4e2d\u5b9a\u4e49\u6269\u5c55\u65b9\u6cd5\u3002\u6b64\u65b9\u6cd5\u6269\u5c55\u4e86 .NET \u4e2d\u7c7b\u578b\u7684\u884c\u4e3a\u3002\u4e00\u65e6\u6211\u4eec\u5b9a\u4e49\u4e86\u4e00\u4e2a\u6269\u5c55\u65b9\u6cd5\uff0c\u5b83\u5c31\u53ef\u4ee5\u5728\u540c\u4e00\u7c7b\u578b\u7684\u5bf9\u8c61\u4e0a\u591a\u6b21\u94fe\u63a5\u3002<\/p>\n<p>So, let\u2019s start writing some code to see how it all adds up.<br \/>\n\u6240\u4ee5\uff0c\u8ba9\u6211\u4eec\u5f00\u59cb\u7f16\u5199\u4e00\u4e9b\u4ee3\u7801\uff0c\u770b\u770b\u5b83\u4eec\u662f\u5982\u4f55\u52a0\u8d77\u6765\u7684\u3002<\/p>\n<p>We are going to create a new folder <strong>Extensions<\/strong> in the project and create a new class inside that folder named <strong>ServiceExtensions<\/strong>. The ServiceExtensions class should be static.<br \/>\n\u6211\u4eec\u5c06\u5728\u9879\u76ee\u4e2d\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u6587\u4ef6\u5939\u201c<strong>Extensions<\/strong>\u201d\uff0c\u5e76\u5728\u8be5\u6587\u4ef6\u5939\u4e2d\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a <strong>ServiceExtensions<\/strong> \u7684\u65b0\u7c7b\u3002 \u670d\u52a1\u6269\u5c55\u7c7b\u5e94\u4e3a\u9759\u6001\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nnamespace CompanyEmployees.Extensions\n{\n    public static class ServiceExtensions\n    {\n    }\n}\n<\/pre>\n<\/p>\n<p>Let\u2019s start by implementing something we need for our project immediately so we can see how extensions work.<br \/>\n\u8ba9\u6211\u4eec\u4ece\u7acb\u5373\u5b9e\u73b0\u9879\u76ee\u6240\u9700\u7684\u5185\u5bb9\u5f00\u59cb\uff0c\u4ee5\u4fbf\u6211\u4eec\u53ef\u4ee5\u770b\u5230\u6269\u5c55\u7684\u5de5\u4f5c\u539f\u7406\u3002  <\/p>\n<p>The first thing we are going to do is to configure CORS in our application. CORS (Cross-Origin Resource Sharing) is a mechanism to give or restrict access rights to applications from different domains.<br \/>\n\u6211\u4eec\u8981\u505a\u7684\u7b2c\u4e00\u4ef6\u4e8b\u662f\u5728\u6211\u4eec\u7684\u5e94\u7528\u7a0b\u5e8f\u4e2d\u914d\u7f6e CORS\u3002CORS\uff08\u8de8\u57df\u8d44\u6e90\u5171\u4eab\uff09\u662f\u4e00\u79cd\u5411\u6765\u81ea\u4e0d\u540c\u57df\u7684\u5e94\u7528\u7a0b\u5e8f\u6388\u4e88\u6216\u9650\u5236\u8bbf\u95ee\u6743\u9650\u7684\u673a\u5236\u3002<\/p>\n<p>If we want to send requests from a different domain to our application, configuring CORS is mandatory. So, to start off, we\u2019ll add a code that allows all requests from all origins to be sent to our API:<br \/>\n\u5982\u679c\u6211\u4eec\u8981\u5c06\u8bf7\u6c42\u4ece\u5176\u4ed6\u57df\u53d1\u9001\u5230\u6211\u4eec\u7684\u5e94\u7528\u7a0b\u5e8f\uff0c\u5219\u5fc5\u987b\u914d\u7f6e CORS\u3002\u56e0\u6b64\uff0c\u9996\u5148\uff0c\u6211\u4eec\u5c06\u6dfb\u52a0\u4e00\u4e2a\u4ee3\u7801\uff0c\u5141\u8bb8\u5c06\u6765\u81ea\u6240\u6709\u6e90\u7684\u6240\u6709\u8bf7\u6c42\u53d1\u9001\u5230\u6211\u4eec\u7684API\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic static void ConfigureCors(this IServiceCollection services) =&gt;\n            services.AddCors(options =&gt;\n            {\n                options.AddPolicy(&quot;CorsPolicy&quot;, builder =&gt;\n                builder.AllowAnyOrigin()\n                .AllowAnyMethod()\n                .AllowAnyHeader());\n            });\n<\/pre>\n<\/p>\n<p>We are using basic CORS policy settings because allowing any origin, method, and header is okay for now. But we should be more restrictive with those settings in the production environment. More precisely, as restrictive as possible.<br \/>\n\u6211\u4eec\u4f7f\u7528\u7684\u662f\u57fa\u672c\u7684 CORS \u7b56\u7565\u8bbe\u7f6e\uff0c\u56e0\u4e3a\u73b0\u5728\u5141\u8bb8\u4efb\u4f55\u6e90\u3001\u65b9\u6cd5\u548c\u6807\u5934\u90fd\u662f\u53ef\u4ee5\u7684\u3002\u4f46\u662f\uff0c\u6211\u4eec\u5e94\u8be5\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u5bf9\u8fd9\u4e9b\u8bbe\u7f6e\u8fdb\u884c\u66f4\u591a\u9650\u5236\u3002\u66f4\u786e\u5207\u5730\u8bf4\uff0c\u5c3d\u53ef\u80fd\u4e25\u683c\u3002<\/p>\n<p>Instead of the <strong>AllowAnyOrigin()<\/strong> method which allows requests from any source, we can use the <strong>WithOrigins(&quot;<a href=\"https:\/\/example.com\"><a href=\"https:\/\/example.com\"><a href=\"https:\/\/example.com\">https:\/\/example.com<\/a><\/a><\/a>&quot;)<\/strong> which will allow requests only from that concrete source. Also, instead of <strong>AllowAnyMethod()<\/strong> that allows all HTTP methods, we can use <strong>WithMethods(&quot;POST&quot;, &quot;GET&quot;)<\/strong> that will allow only specific HTTP methods. Furthermore, you can make the same changes for the <strong>AllowAnyHeader()<\/strong> method by using, for example, the <strong>WithHeaders(&quot;accept&quot;, &quot;content-type&quot;)<\/strong> method to allow only specific headers.<br \/>\n\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 <strong>WithOrigins(&quot;<a href=\"https:\/\/example.com\"><a href=\"https:\/\/example.com\"><a href=\"https:\/\/example.com\">https:\/\/example.com<\/a><\/a><\/a>&quot;)<\/strong> \u800c\u4e0d\u662f\u5141\u8bb8\u6765\u81ea\u4efb\u4f55\u6765\u6e90\u7684\u8bf7\u6c42\u7684<strong>AllowAnyOrigin()<\/strong> \u65b9\u6cd5\uff0c\u5b83\u53ea\u5141\u8bb8\u6765\u81ea\u8be5\u5177\u4f53\u6765\u6e90\u7684\u8bf7\u6c42\u3002\u6b64\u5916\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 <strong>WithMethods(&quot;POST&quot;, &quot;GET&quot;)<\/strong> \u800c\u4e0d\u662f\u5141\u8bb8\u6240\u6709HTTP\u65b9\u6cd5\u7684 <strong>AllowAnyMethod()<\/strong> \uff0c\u5b83\u53ea\u5141\u8bb8\u7279\u5b9a\u7684HTTP\u65b9\u6cd5\u3002\u6b64\u5916\uff0c\u60a8\u53ef\u4ee5\u5bf9 <strong>AllowAnyHeader()<\/strong>  \u65b9\u6cd5\u8fdb\u884c\u76f8\u540c\u7684\u66f4\u6539\uff0c\u4f8b\u5982\uff0c\u901a\u8fc7\u4f7f\u7528<strong>WithHeaders(&quot;accept&quot;, &quot;content-type&quot;)<\/strong> \u65b9\u6cd5\u6765\u4ec5\u5141\u8bb8\u7279\u5b9a\u7684\u6807\u5934\u3002<\/p>\n<h2>1.5 IIS Configuration<\/h2>\n<p>ASP.NET Core applications are by default self-hosted, and if we want to host our application on IIS, we need to configure an IIS integration which will eventually help us with the deployment to IIS. To do that, we need to add the following code to the <strong>ServiceExtensions<\/strong> class:<br \/>\nASP.NET Core \u5e94\u7528\u7a0b\u5e8f\u9ed8\u8ba4\u4e3a\u81ea\u627f\u8f7d\uff0c\u5982\u679c\u6211\u4eec\u8981\u5728 IIS \u4e0a\u6258\u7ba1\u5e94\u7528\u7a0b\u5e8f\uff0c\u5219\u9700\u8981\u914d\u7f6e IIS \u96c6\u6210\uff0c\u8fd9\u6700\u7ec8\u5c06\u5e2e\u52a9\u6211\u4eec\u90e8\u7f72\u5230 IIS\u3002\u4e3a\u6b64\uff0c\u6211\u4eec\u9700\u8981\u5c06\u4ee5\u4e0b\u4ee3\u7801\u6dfb\u52a0\u5230 <strong>ServiceExtensions<\/strong> \u7c7b\u4e2d\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic static void ConfigureIISIntegration(this IServiceCollection service) =&gt;\n            service.Configure&lt;IISOptions&gt;(options =&gt; { });\n<\/pre>\n<\/p>\n<p>We do not initialize any of the properties inside the options because we are fine with the default values for now. But if you need to fine-tune the configuration right away, you might want to take a look at the possible options:<br \/>\n\u6211\u4eec\u4e0d\u521d\u59cb\u5316\u9009\u9879\u4e2d\u7684\u4efb\u4f55\u5c5e\u6027\uff0c\u56e0\u4e3a\u6211\u4eec\u73b0\u5728\u53ef\u4ee5\u4f7f\u7528\u9ed8\u8ba4\u503c\u3002\u4f46\u662f\uff0c\u5982\u679c\u60a8\u9700\u8981\u7acb\u5373\u5fae\u8c03\u914d\u7f6e\uff0c\u5219\u53ef\u80fd\u9700\u8981\u67e5\u770b\u53ef\u80fd\u7684\u9009\u9879\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824ultimate-asp-net-core-web-api\/Image_1004.jpg\" alt=\"alt\" \/><\/p>\n<p>Now, we mentioned extension methods are great for organizing your code and extending functionalities. Let\u2019s go back to our Startup class and modify the <strong>ConfigureServices<\/strong> and the <strong>Configure<\/strong> methods to support CORS and IIS integration now that we\u2019ve written extension methods for those functionalities:<br \/>\n\u73b0\u5728\uff0c\u6211\u4eec\u63d0\u5230\u6269\u5c55\u65b9\u6cd5\u975e\u5e38\u9002\u5408\u7ec4\u7ec7\u4ee3\u7801\u548c\u6269\u5c55\u529f\u80fd\u3002\u8ba9\u6211\u4eec\u56de\u5230 Startup \u7c7b\uff0c\u4fee\u6539 <strong>ConfigureServices<\/strong> \u548c <strong>Configure<\/strong> \u65b9\u6cd5\u4ee5\u652f\u6301 CORS \u548c IIS \u96c6\u6210\uff0c\u56e0\u4e3a\u6211\u4eec\u5df2\u7ecf\u4e3a\u8fd9\u4e9b\u529f\u80fd\u7f16\u5199\u4e86\u6269\u5c55\u65b9\u6cd5\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic void ConfigureServices(IServiceCollection services)\n        {\n\n            services.ConfigureCors();\n            services.ConfigureIISIntegration();\n\n            services.AddControllers();\n        }\n<\/pre>\n<\/p>\n<p>And let's add a few mandatory methods to our Configure method:<br \/>\n\u8ba9\u6211\u4eec\u5411 Configure \u65b9\u6cd5\u6dfb\u52a0\u4e00\u4e9b\u5fc5\u9700\u7684\u65b9\u6cd5\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n        {\n            if (env.IsDevelopment())\n            {\n                app.UseDeveloperExceptionPage();\n            }\n            else\n            {\n                app.UseHsts();\n            }\n            app.UseHttpsRedirection();\n            app.UseStaticFiles();\n\n            app.UseCors(&quot;CorsPolicy&quot;);\n\n            app.UseForwardedHeaders(new ForwardedHeadersOptions\n            {\n                ForwardedHeaders = ForwardedHeaders.All\n            });\n\n            app.UseRouting();\n            app.UseAuthorization();\n            app.UseEndpoints(endpoints =&gt;\n            {\n                endpoints.MapControllers();\n            });\n        }\n<\/pre>\n<\/p>\n<p>We\u2019ve added CORS and IIS configuration to the <strong>ConfigureServices<\/strong> method. Furthermore, CORS configuration has been added to the application\u2019s pipeline inside the <strong>Configuration<\/strong> method. But as you can see, there are some additional methods unrelated to IIS configuration.<br \/>\n\u6211\u4eec\u5df2\u5c06 CORS \u548c IIS \u914d\u7f6e\u6dfb\u52a0\u5230 <strong>ConfigureServices<\/strong> \u65b9\u6cd5\u3002\u6b64\u5916\uff0cCORS \u914d\u7f6e\u5df2\u6dfb\u52a0\u5230<strong>Configuration<\/strong>\u65b9\u6cd5\u5185\u7684\u5e94\u7528\u7a0b\u5e8f\u7ba1\u9053\u4e2d\u3002\u4f46\u5982\u60a8\u6240\u89c1\uff0c\u8fd8\u6709\u4e00\u4e9b\u4e0e IIS \u914d\u7f6e\u65e0\u5173\u7684\u5176\u4ed6\u65b9\u6cd5\u3002<\/p>\n<p>Let\u2019s go through those and learn what they do.<br \/>\n\u8ba9\u6211\u4eec\u6765\u770b\u770b\u8fd9\u4e9b\uff0c\u4e86\u89e3\u5b83\u4eec\u7684\u4f5c\u7528\u3002<\/p>\n<ul>\n<li>\n<strong>app.UseForwardedHeaders()<\/strong> will forward proxy headers to the current request. This will help us during application deployment.<br \/>\n<strong>app.UseForwardedHeaders()<\/strong> \u4f1a\u5c06\u4ee3\u7406\u6807\u5934\u8f6c\u53d1\u5230\u5f53\u524d\u8bf7\u6c42\u3002\u8fd9\u5c06\u5728\u5e94\u7528\u7a0b\u5e8f\u90e8\u7f72\u671f\u95f4\u5e2e\u52a9\u6211\u4eec\u3002\n<\/li>\n<li>\n<strong>app.UseStaticFiles()<\/strong> enables using static files for the request. If we don\u2019t set a path to the static files directory, it will use a wwwroot folder in our project by default.<br \/>\n<strong>app.UseStaticFiles()<\/strong> \u5141\u8bb8\u5bf9\u8bf7\u6c42\u4f7f\u7528\u9759\u6001\u6587\u4ef6\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5982\u679c\u6211\u4eec\u4e0d\u8bbe\u7f6e\u9759\u6001\u6587\u4ef6\u76ee\u5f55\u7684\u8def\u5f84\uff0c\u5b83\u5c06\u4f7f\u7528wwwroot\u6587\u4ef6\u5939\u4e2d\u7684\u6587\u4ef6\u5939\u3002\n<\/li>\n<li>\n<strong>app.UseHsts()<\/strong> will add middleware for using HSTS, which adds the Strict-Transport-Security header.<br \/>\n<strong>app.UseHsts()<\/strong> \u5c06\u6dfb\u52a0\u7528\u4e8e\u4f7f\u7528 HSTS \u7684\u4e2d\u95f4\u4ef6\uff0c\u8fd9\u4f1a\u6dfb\u52a0 Strict-Transport-Security \u6807\u5934\u3002\n<\/li>\n<\/ul>\n<h2>1.6 Additional Code in the Startup class<\/h2>\n<p>Configuration from .NET Core 3.1 (and in 5.0) is a bit different than it was in 2.2, so we have to make some changes in the Startup class. First, in the <strong>ConfigureServices<\/strong> method, instead of <strong>AddMvc()<\/strong> as used in 2.2, now we have <strong>AddControllers()<\/strong>. This method registers only the controllers in <strong>IServiceCollection<\/strong> and not Views or Pages because they are not required in the Web API project which we are building.<br \/>\n.NET Core 3.1\uff08\u4ee5\u53ca 5.0 \u4e2d\u7684\u914d\u7f6e\uff09\u4e0e 2.2 \u4e2d\u7684\u914d\u7f6e\u7565\u6709\u4e0d\u540c\uff0c\u56e0\u6b64\u6211\u4eec\u5fc5\u987b\u5728 Startup \u7c7b\u4e2d\u8fdb\u884c\u4e00\u4e9b\u66f4\u6539\u3002\u9996\u5148\uff0c\u5728 <strong>ConfigureServices<\/strong> \u65b9\u6cd5\u4e2d\uff0c\u73b0\u5728\u6211\u4eec\u6709 <strong>AddControllers()<\/strong>\u800c\u4e0d\u662f 2.2 \u4e2d\u4f7f\u7528\u7684 <strong>AddMvc()<\/strong> \u3002\u6b64\u65b9\u6cd5\u4ec5\u6ce8\u518c\u63a7\u5236\u5668\u5728 <strong>IServiceCollection<\/strong> \u4e2d\uff0c\u800c\u4e0d\u662f\u89c6\u56fe\u6216\u9875\u9762\uff0c\u56e0\u4e3a\u5b83\u4eec\u5728\u6211\u4eec\u6b63\u5728\u6784\u5efa\u7684 Web API \u9879\u76ee\u4e2d\u4e0d\u662f\u5fc5\u9700\u7684\u3002<\/p>\n<p>In the Configure method, we have <strong>UseRouting()<\/strong> and <strong>UseAuthorization()<\/strong> methods. They add routing and authorization features to our application, respectively.<br \/>\n\u5728 Configure \u65b9\u6cd5\u4e2d\uff0c\u6211\u4eec\u6709 <strong>UseRouting()<\/strong> \u548c <strong>UseAuthorization()<\/strong> \u65b9\u6cd5\u3002\u5b83\u4eec\u5206\u522b\u4e3a\u6211\u4eec\u7684\u5e94\u7528\u7a0b\u5e8f\u6dfb\u52a0\u4e86\u8def\u7531\u548c\u6388\u6743\u529f\u80fd\u3002<\/p>\n<p>Finally, we have the <strong>UseEndpoints()<\/strong> method with the <strong>MapControllers()<\/strong> method, which adds an endpoint for the controller\u2019s action to the routing without specifying any routes.<br \/>\n\u6700\u540e\uff0c\u6211\u4eec\u6709 <strong>UseEndpoints()<\/strong> \u65b9\u6cd5\u548c <strong>MapControllers()<\/strong> \u65b9\u6cd5\uff0c\u8be5\u65b9\u6cd5\u5c06\u63a7\u5236\u5668\u64cd\u4f5c\u7684\u7ec8\u7ed3\u70b9\u6dfb\u52a0\u5230\u8def\u7531\u4e2d\uff0c\u800c\u65e0\u9700\u6307\u5b9a\u4efb\u4f55\u8def\u7531\u3002<\/p>\n<p>Microsoft advises that the order of adding different middlewares to the application builder is very important. So the <strong>UseRouting()<\/strong> method should be called before the <strong>UseAuthorization()<\/strong> method and <strong>UseCors()<\/strong> or <strong>UseStaticFiles()<\/strong> have to be called before the <strong>UseRouting()<\/strong> method.<br \/>\n\u5fae\u8f6f\u5efa\u8bae\uff0c\u5411\u5e94\u7528\u7a0b\u5e8f\u6784\u5efa\u5668\u6dfb\u52a0\u4e0d\u540c\u4e2d\u95f4\u4ef6\u7684\u987a\u5e8f\u975e\u5e38\u91cd\u8981\u3002\u56e0\u6b64\uff0c <strong>UseRouting()<\/strong>  \u65b9\u6cd5\u5e94\u8be5\u5728 <strong>UseAuthorization()<\/strong>  \u65b9\u6cd5\u4e4b\u524d\u8c03\u7528\uff0c<strong>UseCors()<\/strong> \u6216  <strong>UseStaticFiles()<\/strong> \u5fc5\u987b\u5728 <strong>UseRouting()<\/strong>  \u65b9\u6cd5\u4e4b\u524d\u8c03\u7528\u3002<\/p>\n<h2>1.7 Environment-Based Setting<\/h2>\n<p>While we develop our application, we use the \u201cdevelopment\u201d environment. But as soon as we publish our application, it goes to the \u201cproduction\u201d environment. Development and production environments should have different URLs, ports, connection strings, passwords, and other sensitive information.<br \/>\n\u5728\u5f00\u53d1\u5e94\u7528\u7a0b\u5e8f\u65f6\uff0c\u6211\u4eec\u4f7f\u7528\u201c\u5f00\u53d1\u201d\u73af\u5883\u3002\u4f46\u662f\uff0c\u4e00\u65e6\u6211\u4eec\u53d1\u5e03\u4e86\u5e94\u7528\u7a0b\u5e8f\uff0c\u5b83\u5c31\u4f1a\u8fdb\u5165\u201c\u751f\u4ea7\u201d\u73af\u5883\u3002\u5f00\u53d1\u548c\u751f\u4ea7\u73af\u5883\u5e94\u5177\u6709\u4e0d\u540c\u7684 URL\u3001\u7aef\u53e3\u3001\u8fde\u63a5\u5b57\u7b26\u4e32\u3001\u5bc6\u7801\u548c\u5176\u4ed6\u654f\u611f\u4fe1\u606f\u3002<\/p>\n<p>Therefore, we need to have a separate configuration for each environment and that\u2019s easy to accomplish by using .NET Core-provided mechanisms.<br \/>\n\u56e0\u6b64\uff0c\u6211\u4eec\u9700\u8981\u4e3a\u6bcf\u4e2a\u73af\u5883\u63d0\u4f9b\u5355\u72ec\u7684\u914d\u7f6e\uff0c\u8fd9\u53ef\u4ee5\u901a\u8fc7\u4f7f\u7528 .NET Core \u63d0\u4f9b\u7684\u673a\u5236\u8f7b\u677e\u5b9e\u73b0\u3002<\/p>\n<p>As soon as we create a project, we are going to see the <strong>appsettings.json<\/strong> file in the root, which is our main settings file, and when we expand it we are going to see the <strong>appsetings.Development.json<\/strong> file by default. These files are separate on the file system, but Visual Studio makes it obvious that they are connected somehow.<br \/>\n\u521b\u5efa\u9879\u76ee\u540e\uff0c\u6211\u4eec\u5c06\u5728\u6839\u76ee\u5f55\u4e2d\u770b\u5230 <strong>appsettings.json<\/strong> \u6587\u4ef6\uff0c\u8fd9\u662f\u6211\u4eec\u7684\u4e3b\u8981\u8bbe\u7f6e\u6587\u4ef6\uff0c\u5f53\u6211\u4eec\u5c55\u5f00\u5b83\u65f6\uff0c\u6211\u4eec\u5c06\u770b\u5230 <strong>appsetings.Development.json<\/strong> \u6587\u4ef6\u3002\u8fd9\u4e9b\u6587\u4ef6\u662f\u5206\u5f00\u7684\uff0c\u5728\u6587\u4ef6\u7cfb\u7edf\u4e0a\uff0c\u4f46Visual Studio\u6e05\u695a\u5730\u8868\u660e\u5b83\u4eec\u4ee5\u67d0\u79cd\u65b9\u5f0f\u8fde\u63a5\u5728\u4e00\u8d77\u3002<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824ultimate-asp-net-core-web-api\/Image_1005.gif\" alt=\"alt\" \/><\/p>\n<p>The apsettings.{EnvironmentSuffix}.json files are used to override the main appsettings.json file. When we use a key-value pair from the original file, we override it. We can also define environment-specific values too.<br \/>\n{EnvironmentSenduix}.json \u6587\u4ef6\u7528\u4e8e\u8986\u76d6\u4e3b appsettings.json \u6587\u4ef6\u3002\u5f53\u6211\u4eec\u4f7f\u7528\u539f\u59cb\u6587\u4ef6\u4e2d\u7684\u952e\u503c\u5bf9\u65f6\uff0c\u6211\u4eec\u4f1a\u8986\u76d6\u5b83\u3002\u6211\u4eec\u8fd8\u53ef\u4ee5\u5b9a\u4e49\u7279\u5b9a\u4e8e\u73af\u5883\u7684\u503c\u3002<\/p>\n<p>For the production environment, we should add another file: appsettings.Production.json:<br \/>\n\u5bf9\u4e8e\u751f\u4ea7\u73af\u5883\uff0c\u6211\u4eec\u5e94\u8be5\u6dfb\u52a0\u53e6\u4e00\u4e2a\u6587\u4ef6\uff1aappsettings.Production.json\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824ultimate-asp-net-core-web-api\/Image_1006.gif\" alt=\"alt\" \/><\/p>\n<p>The appsettings.Production.json file should contain the configuration for the production environment.<br \/>\nappsettings.Production.json \u6587\u4ef6\u5e94\u5305\u542b\u751f\u4ea7\u73af\u5883\u7684\u914d\u7f6e\u3002<\/p>\n<p>To set which environment our application runs on, we need to set up the <strong>ASPNETCORE_ENVIRONMENT<\/strong> environment variable. For example, to run the application in production, we need to set it to the Production value on the machine we do the deployment to.<br \/>\n\u82e5\u8981\u8bbe\u7f6e\u5e94\u7528\u7a0b\u5e8f\u5728\u54ea\u4e2a\u73af\u5883\u4e2d\u8fd0\u884c\uff0c\u6211\u4eec\u9700\u8981\u8bbe\u7f6e <strong>ASPNETCORE_ENVIRONMENT<\/strong> \u73af\u5883\u53d8\u91cf\u3002\u4f8b\u5982\uff0c\u82e5\u8981\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u8fd0\u884c\u5e94\u7528\u7a0b\u5e8f\uff0c\u6211\u4eec\u9700\u8981\u5728\u6267\u884c\u90e8\u7f72\u7684\u8ba1\u7b97\u673a\u4e0a\u5c06\u5176\u8bbe\u7f6e\u4e3a\u201c\u751f\u4ea7\u201d\u503c\u3002<\/p>\n<p>We can set the variable through the command prompt by typing set <strong>ASPNETCORE_ENVIRONMENT=Production<\/strong> in Windows or export <strong>ASPNET_CORE_ENVIRONMENT=Production<\/strong> in Linux.<br \/>\n\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4\u63d0\u793a\u7b26\u8bbe\u7f6e\u53d8\u91cf\uff0c\u65b9\u6cd5\u662f\u5728Windows\u4e2d\u952e\u5165set <strong>ASPNETCORE_ENVIRONMENT=Production<\/strong> \u6216\u5728Linux\u4e2d\u5bfc\u51fa<strong>ASPNET_CORE_ENVIRONMENT=Production<\/strong> \u3002<\/p>\n<p>ASP.NET Core applications use the value of that environment variable to decide which appsettings file to use accordingly. In this case, that will be appsettings.Production.json.<br \/>\nASP.NET Core\u5e94\u7528\u7a0b\u5e8f\u4f7f\u7528\u8be5\u73af\u5883\u53d8\u91cf\u7684\u503c\u6765\u51b3\u5b9a\u76f8\u5e94\u5730\u4f7f\u7528\u54ea\u4e2a\u5e94\u7528\u7a0b\u5e8f\u8bbe\u7f6e\u6587\u4ef6\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u8fd9\u5c06\u662fappsettings.Production.json.<\/p>\n<p>If we take a look at our <strong>launchSettings.json<\/strong> file, we are going to see that this variable is currently set to Development.<br \/>\n\u5982\u679c\u6211\u4eec\u770b\u4e00\u4e0b\u6211\u4eec\u7684 <strong>launchSettings.json<\/strong>  \u6587\u4ef6\uff0c\u6211\u4eec\u5c06\u770b\u5230\u6b64\u53d8\u91cf\u5f53\u524d\u8bbe\u7f6e\u4e3a\u201c\u5f00\u53d1\u201d\u3002<\/p>\n<p>In the next chapter, we\u2019ll learn how to configure a Logger service because it\u2019s really important to have it configured as early in the project as possible.<br \/>\n\u5728\u4e0b\u4e00\u7ae0\u4e2d\uff0c\u6211\u4eec\u5c06\u5b66\u4e60\u5982\u4f55\u914d\u7f6e Logger \u670d\u52a1\uff0c\u56e0\u4e3a\u5728\u9879\u76ee\u4e2d\u5c3d\u65e9\u914d\u7f6e\u5b83\u975e\u5e38\u91cd\u8981\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1 PROJECT CONFIGURATION Configuration in .NET Core is very different from what we\u2019re used to in .NET Framework projects. We don\u2019t use the web.config file anymore, but instead, use a built-in Configuration framework that comes out-of-the-box in .NET Core. .NET Core \u4e2d\u7684\u914d\u7f6e\u4e0e\u6211\u4eec\u4e60\u60ef \u7684\u914d\u7f6e\u975e\u5e38\u4e0d\u540c.NET Framework \u9879\u76ee\u3002\u6211\u4eec\u4e0d\u518d\u4f7f\u7528 web.config \u6587\u4ef6\uff0c\u800c\u662f\u4f7f\u7528\u5728 .NET Core \u4e2d\u5f00\u7bb1\u5373\u7528\u7684\u5185\u7f6e\u914d\u7f6e\u6846\u67b6\u3002 To be able to develop [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[23],"class_list":["post-136","post","type-post","status-publish","format-standard","hentry","category-csharp","tag-ultimate-asp-net-core-web-api"],"_links":{"self":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/136","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=136"}],"version-history":[{"count":0,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/136\/revisions"}],"wp:attachment":[{"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=136"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=136"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=136"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}