{"id":1102,"date":"2025-05-27T14:46:02","date_gmt":"2025-05-27T06:46:02","guid":{"rendered":"https:\/\/www.hyy.net\/?p=1102"},"modified":"2025-05-27T14:46:02","modified_gmt":"2025-05-27T06:46:02","slug":"ultimate-asp-net-core-web-api-2-creating-the-required-projects","status":"publish","type":"post","link":"https:\/\/diji.net\/?p=1102","title":{"rendered":"Ultimate ASP.NET Core Web API  2 Creating the Required Projects"},"content":{"rendered":"<h1>2 Configuring a logging service<\/h1>\n<p>2 \u914d\u7f6e\u65e5\u5fd7\u8bb0\u5f55\u670d\u52a1<\/p>\n<p>Why do logging messages matter so much during application development? While our application is in the development stage, it's easy to debug the code and find out what happened. But debugging in a production environment is not that easy.\u200c<br \/>\n\u4e3a\u4ec0\u4e48\u5728\u5e94\u7528\u7a0b\u5e8f\u5f00\u53d1\u8fc7\u7a0b\u4e2d\uff0c\u65e5\u5fd7\u8bb0\u5f55\u6d88\u606f\u5982\u6b64\u91cd\u8981\uff1f\u867d\u7136\u6211\u4eec\u7684\u5e94\u7528\u7a0b\u5e8f\u5904\u4e8e\u5f00\u53d1\u9636\u6bb5\uff0c\u4f46\u5f88\u5bb9\u6613\u8c03\u8bd5\u4ee3\u7801\u5e76\u627e\u51fa\u53d1\u751f\u4e86\u4ec0\u4e48\u3002\u4f46\u662f\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u8fdb\u884c\u8c03\u8bd5\u5e76\u4e0d\u662f\u90a3\u4e48\u5bb9\u6613\u3002<\/p>\n<p>That's why log messages are a great way to find out what went wrong and why and where the exceptions have been thrown in our code in the production environment. Logging also helps us more easily follow the flow of our application when we don\u2019t have access to the debugger.<br \/>\n\u8fd9\u5c31\u662f\u4e3a\u4ec0\u4e48\u65e5\u5fd7\u6d88\u606f\u662f\u627e\u51fa\u95ee\u9898\u6240\u5728\u4ee5\u53ca\u751f\u4ea7\u73af\u5883\u4e2d\u4ee3\u7801\u4e2d\u5f15\u53d1\u5f02\u5e38\u7684\u539f\u56e0\u548c\u4f4d\u7f6e\u7684\u597d\u65b9\u6cd5\u3002\u65e5\u5fd7\u8bb0\u5f55\u8fd8\u6709\u52a9\u4e8e\u6211\u4eec\u5728\u65e0\u6cd5\u8bbf\u95ee\u8c03\u8bd5\u5668\u65f6\u66f4\u8f7b\u677e\u5730\u8ddf\u8e2a\u5e94\u7528\u7a0b\u5e8f\u7684\u6d41\u7a0b\u3002<\/p>\n<p>.NET Core has its implementation of the logging mechanism, but in all our projects we prefer to create our custom logger service with the external logger library NLog.<br \/>\n.NET Core \u5177\u6709\u65e5\u5fd7\u8bb0\u5f55\u673a\u5236\u7684\u5b9e\u73b0\uff0c\u4f46\u5728\u6211\u4eec\u6240\u6709\u7684\u9879\u76ee\u4e2d\uff0c\u6211\u4eec\u66f4\u559c\u6b22\u4f7f\u7528\u5916\u90e8\u8bb0\u5f55\u5668\u5e93 NLog \u521b\u5efa\u81ea\u5b9a\u4e49\u8bb0\u5f55\u5668\u670d\u52a1\u3002<\/p>\n<p>We are going to do that because having an abstraction will allow us to have any logger behind our interface. This means that we can start with NLog, and at some point, we can switch to any other logger and our interface will still work because of our abstraction.<br \/>\n\u6211\u4eec\u4e4b\u6240\u4ee5\u8fd9\u6837\u505a\uff0c\u662f\u56e0\u4e3a\u6709\u4e00\u4e2a\u62bd\u8c61\u5c06\u5141\u8bb8\u6211\u4eec\u5728\u63a5\u53e3\u540e\u9762\u62e5\u6709\u4efb\u4f55 Logger\u3002\u8fd9\u610f\u5473\u7740\u6211\u4eec\u53ef\u4ee5\u4ece NLog \u5f00\u59cb\uff0c\u5728\u67d0\u4e9b\u65f6\u5019\uff0c\u6211\u4eec\u53ef\u4ee5\u5207\u6362\u5230\u4efb\u4f55\u5176\u4ed6 logger\uff0c\u5e76\u4e14\u7531\u4e8e\u6211\u4eec\u7684\u62bd\u8c61\uff0c\u6211\u4eec\u7684\u63a5\u53e3\u4ecd\u7136\u53ef\u4ee5\u5de5\u4f5c\u3002<\/p>\n<h2>2.1 Creating the Required Projects<\/h2>\n<p>2.1 \u521b\u5efa\u6240\u9700\u7684\u9879\u76ee<\/p>\n<p>Let\u2019s create two new projects. In the first one named Contracts, we are going to keep our interfaces. We will use this project later on too, to define our contracts for the whole application. The second one, LoggerService, we are going to use to write our logger logic in.\u200c<br \/>\n\u8ba9\u6211\u4eec\u521b\u5efa\u4e24\u4e2a\u65b0\u9879\u76ee\u3002\u5728\u7b2c\u4e00\u4e2a\u540d\u4e3a Contract\uff0c\u6211\u4eec\u5c06\u4fdd\u7559\u6211\u4eec\u7684\u63a5\u53e3\u3002\u6211\u4eec\u7a0d\u540e\u4e5f\u5c06\u4f7f\u7528\u8fd9\u4e2a\u9879\u76ee\u6765\u5b9a\u4e49\u6574\u4e2a\u5e94\u7528\u7a0b\u5e8f\u7684 Contract\u3002\u7b2c\u4e8c\u4e2a\u662f LoggerService\uff0c\u6211\u4eec\u5c06\u4f7f\u7528\u5b83\u6765\u7f16\u5199\u6211\u4eec\u7684 Logger \u903b\u8f91\u3002<\/p>\n<p>To create a new project, right-click on the solution window, choose Add, and then NewProject. Choose the Class Library (C#) project template:<br \/>\n\u8981\u521b\u5efa\u65b0\u9879\u76ee\uff0c\u8bf7\u53f3\u952e\u5355\u51fb\u89e3\u51b3\u65b9\u6848\u7a97\u53e3\uff0c\u9009\u62e9 Add\uff08\u6dfb\u52a0\uff09\uff0c\u7136\u540e\u9009\u62e9 NewProject\u3002\u9009\u62e9 Class Library \uff08C#\uff09 \u9879\u76ee\u6a21\u677f\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/images\/ultimateaspnetcorewebapi6\/0201.jpg\" alt=\"alt text\" \/><\/p>\n<p>Finally, name it Contracts, and choose the .NET 6.0 as a version. Do the same thing for the second project and name it LoggerService. Now that we have these projects in place, we need to reference them from our main project.<br \/>\n\u6700\u540e\uff0c\u5c06\u5176\u547d\u540d\u4e3a Contracts\uff0c\u5e76\u9009\u62e9 .NET 6.0 \u4f5c\u4e3a\u7248\u672c\u3002\u5bf9\u7b2c\u4e8c\u4e2a\u9879\u76ee\u6267\u884c\u76f8\u540c\u7684\u4f5c\uff0c\u5e76\u5c06\u5176\u547d\u540d\u4e3a LoggerService\u3002\u73b0\u5728\u6211\u4eec\u5df2\u7ecf\u51c6\u5907\u597d\u4e86\u8fd9\u4e9b\u9879\u76ee\uff0c\u6211\u4eec\u9700\u8981\u4ece\u4e3b\u9879\u76ee\u4e2d\u5f15\u7528\u5b83\u4eec\u3002<\/p>\n<p>To do that, navigate to the solution explorer. Then in the LoggerService project, right-click on Dependencies and choose the Add Project Reference option. Under Projects, click Solution and check the Contracts project.<br \/>\n\u4e3a\u6b64\uff0c\u8bf7\u5bfc\u822a\u5230\u89e3\u51b3\u65b9\u6848\u8d44\u6e90\u7ba1\u7406\u5668\u3002\u7136\u540e\u5728 LoggerService \u9879\u76ee\u4e2d\uff0c\u53f3\u952e\u5355\u51fb Dependencies \u5e76\u9009\u62e9 Add Project Reference \u9009\u9879\u3002\u5728 Projects \u4e0b\uff0c\u5355\u51fb Solution \u5e76\u9009\u4e2d Contracts \u9879\u76ee\u3002<\/p>\n<p>Now, in the main project right click on Dependencies and then click on Add Project Reference. Check the LoggerService checkbox to import it. Since we have referenced the Contracts project through the LoggerService, it will be available in the main project too.<br \/>\n\u73b0\u5728\uff0c\u5728\u4e3b\u9879\u76ee\u4e2d\uff0c\u53f3\u952e\u5355\u51fb Dependencies\uff0c\u7136\u540e\u5355\u51fb Add Project Reference\u3002\u9009\u4e2d LoggerService \u590d\u9009\u6846\u4ee5\u5bfc\u5165\u5b83\u3002\u7531\u4e8e\u6211\u4eec\u5df2\u7ecf\u901a\u8fc7 LoggerService \u5f15\u7528\u4e86 Contracts \u9879\u76ee\uff0c\u56e0\u6b64\u5b83\u4e5f\u5c06\u5728\u4e3b\u9879\u76ee\u4e2d\u53ef\u7528\u3002<\/p>\n<h2>2.2 Creating the ILoggerManager Interface and Installing NLog<\/h2>\n<p>2.2 \u521b\u5efa ILoggerManager \u63a5\u53e3\u5e76\u5b89\u88c5 NLog<\/p>\n<p>Our logger service will contain four methods for logging our messages:\u200c<br \/>\n\u6211\u4eec\u7684 logger \u670d\u52a1\u5c06\u5305\u542b\u56db\u79cd\u8bb0\u5f55\u6d88\u606f\u7684\u65b9\u6cd5\uff1a<\/p>\n<p>\u2022 Info messages<br \/>\n\u2022 \u4fe1\u606f\u6d88\u606f<\/p>\n<p>\u2022 Debug messages<br \/>\n\u2022 \u8c03\u8bd5\u6d88\u606f<\/p>\n<p>\u2022 Warning messages<br \/>\n\u2022 \u8b66\u544a\u6d88\u606f<\/p>\n<p>\u2022 Error messages<br \/>\n\u2022 \u9519\u8bef\u6d88\u606f<\/p>\n<p>To achieve this, we are going to create an interface named ILoggerManager inside the Contracts project containing those four method definitions.<br \/>\n\u4e3a\u6b64\uff0c\u6211\u4eec\u5c06\u5728\u5305\u542b\u8fd9\u56db\u4e2a\u65b9\u6cd5\u5b9a\u4e49\u7684 Contracts \u9879\u76ee\u4e2d\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a ILoggerManager \u7684\u63a5\u53e3\u3002<\/p>\n<p>So, let\u2019s do that first by right-clicking on the Contracts project, choosing the Add -&gt; New Item menu, and then selecting the Interface option where we have to specify the name ILoggerManager and click the Add button. After the file creation, we can add the code:<br \/>\n\u56e0\u6b64\uff0c\u8ba9\u6211\u4eec\u9996\u5148\u53f3\u952e\u5355\u51fb Contracts \u9879\u76ee\uff0c\u9009\u62e9 Add -&gt; New Item \u83dc\u5355\uff0c\u7136\u540e\u9009\u62e9 Interface \u9009\u9879\uff0c\u6211\u4eec\u5fc5\u987b\u5728\u5176\u4e2d\u6307\u5b9a\u540d\u79f0 ILoggerManager \u5e76\u5355\u51fb Add \u6309\u94ae\u3002\u521b\u5efa\u6587\u4ef6\u540e\uff0c\u6211\u4eec\u53ef\u4ee5\u6dfb\u52a0\u4ee3\u7801\uff1a<\/p>\n<pre><code>namespace Contract\n{\n    public interface ILoggerManager\n    {\n            void LogInfo(string message); \n            void LogWarn(string message);\n            void LogDebug(string message); \n            void LogError(string message); \n    }\n}\n<\/code><\/pre>\n<p>Before we implement this interface inside the LoggerService project, we need to install the NLog library in our LoggerService project. NLog is a logging platform for .NET which will help us create and log our messages.<br \/>\n\u5728 LoggerService \u9879\u76ee\u4e2d\u5b9e\u73b0\u6b64\u63a5\u53e3\u4e4b\u524d\uff0c\u6211\u4eec\u9700\u8981\u5728 LoggerService \u9879\u76ee\u4e2d\u5b89\u88c5 NLog \u5e93\u3002NLog \u662f\u4e00\u4e2a .NET \u7684\u65e5\u5fd7\u8bb0\u5f55\u5e73\u53f0\uff0c\u5b83\u5c06\u5e2e\u52a9\u6211\u4eec\u521b\u5efa\u548c\u8bb0\u5f55\u6211\u4eec\u7684\u6d88\u606f\u3002<\/p>\n<p>We are going to show two different ways of adding the NLog library to our project.<br \/>\n\u6211\u4eec\u5c06\u5c55\u793a\u5c06 NLog \u5e93\u6dfb\u52a0\u5230\u9879\u76ee\u4e2d\u7684\u4e24\u79cd\u4e0d\u540c\u65b9\u6cd5\u3002<\/p>\n<ol>\n<li>In the LoggerService project, right-click on the Dependencies and choose Manage NuGet Packages. After the NuGet Package Manager window appears, just follow these steps:<br \/>\n\u5728 LoggerService \u9879\u76ee\u4e2d\uff0c\u53f3\u952e\u5355\u51fb Dependencies \u5e76\u9009\u62e9 Manage NuGet Packages\u3002\u51fa\u73b0 NuGet \u5305\u7ba1\u7406\u5668\u7a97\u53e3\u540e\uff0c\u53ea\u9700\u6309\u7167\u4ee5\u4e0b\u6b65\u9aa4\u4f5c\uff1a<\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"\/images\/ultimateaspnetcorewebapi6\/0202.jpg\" alt=\"alt text\" \/><\/p>\n<ol start=\"2\">\n<li>From the View menu, choose Other Windows and then click on the Package Manager Console. After the console appears, type:<br \/>\n\u4ece View \uff08\u89c6\u56fe\uff09 \u83dc\u5355\u4e2d\uff0c\u9009\u62e9 Other Windows \uff08\u5176\u4ed6\u7a97\u53e3\uff09\uff0c\u7136\u540e\u5355\u51fb Package Manager \u63a7\u5236\u53f0\u3002\u63a7\u5236\u53f0\u51fa\u73b0\u540e\uff0c\u952e\u5165\uff1a<\/li>\n<\/ol>\n<pre><code>Install-Package NLog.Extensions.Logging -Version 1.7.4<\/code><\/pre>\n<p>After a couple of seconds, NLog is up and running in our application.<br \/>\n\u51e0\u79d2\u949f\u540e\uff0cNLog \u5728\u6211\u4eec\u7684\u5e94\u7528\u7a0b\u5e8f\u4e2d\u542f\u52a8\u5e76\u8fd0\u884c\u3002<\/p>\n<h2>2.3 Implementing the Interface and Nlog.Config File<\/h2>\n<p>2.3 \u5b9e\u73b0\u63a5\u53e3\u548c Nlog.Config \u6587\u4ef6<\/p>\n<p>In the LoggerService project, we are going to create a new\u200c class: LoggerManager. We can do that by repeating the same steps for the interface creation just choosing the class option instead of an interface. Now let\u2019s have it implement the ILoggerManager interface we previously defined:<br \/>\n\u5728 LoggerService \u9879\u76ee\u4e2d\uff0c\u6211\u4eec\u5c06\u521b\u5efa\u4e00\u4e2a\u65b0\u7c7b\uff1aLoggerManager\u3002\u4e3a\u6b64\uff0c\u53ea\u9700\u9009\u62e9 class \u9009\u9879\u800c\u4e0d\u662f interface\uff0c\u5373\u53ef\u5bf9\u754c\u9762\u521b\u5efa\u91cd\u590d\u76f8\u540c\u7684\u6b65\u9aa4\u3002\u73b0\u5728\u8ba9\u6211\u4eec\u8ba9\u5b83\u5b9e\u73b0\u6211\u4eec\u4e4b\u524d\u5b9a\u4e49\u7684 ILoggerManager \u63a5\u53e3\uff1a<\/p>\n<pre><code>using Contract;\nusing NLog;\n\nnamespace LoggerService\n{\n    public class LoggerManager : ILoggerManager\n    {\n        private static ILogger logger = LogManager.GetCurrentClassLogger();\n        public LoggerManager() { }\n        public void LogDebug(string message) =&gt; logger.Debug(message);\n        public void LogError(string message) =&gt; logger.Error(message);\n        public void LogInfo(string message) =&gt; logger.Info(message);\n        public void LogWarn(string message) =&gt; logger.Warn(message);\n    }\n}<\/code><\/pre>\n<p>As you can see, our methods are just wrappers around NLog\u2019s methods. Both ILogger and LogManager are part of the NLog namespace. Now, we need to configure it and inject it into the Program class in the section related to the service configuration.<br \/>\n\u5982\u4f60\u6240\u89c1\uff0c\u6211\u4eec\u7684\u65b9\u6cd5\u53ea\u662f NLog \u65b9\u6cd5\u7684\u5305\u88c5\u5668\u3002ILogger \u548c LogManager \u90fd\u662f NLog \u547d\u540d\u7a7a\u95f4\u7684\u4e00\u90e8\u5206\u3002\u73b0\u5728\uff0c\u6211\u4eec\u9700\u8981\u914d\u7f6e\u5b83\u5e76\u5c06\u5176\u6ce8\u5165\u5230\u4e0e\u670d\u52a1\u914d\u7f6e\u76f8\u5173\u7684\u90e8\u5206\u7684 Program \u7c7b\u4e2d\u3002<\/p>\n<p>NLog needs to have information about where to put log files on the file system, what the name of these files will be, and what is the minimum level of logging that we want.<br \/>\nNLog \u9700\u8981\u4e86\u89e3\u5c06\u65e5\u5fd7\u6587\u4ef6\u653e\u5728\u6587\u4ef6\u7cfb\u7edf\u4e0a\u7684\u54ea\u4e2a\u4f4d\u7f6e\u3001\u8fd9\u4e9b\u6587\u4ef6\u7684\u540d\u79f0\u4ee5\u53ca\u6211\u4eec\u6240\u9700\u7684\u6700\u4f4e\u65e5\u5fd7\u8bb0\u5f55\u7ea7\u522b\u7684\u4fe1\u606f\u3002<\/p>\n<p>We are going to define all these constants in a text file in the main project and name it nlog.config. So, let\u2019s right-click on the main project, choose Add -&gt; New Item, and then search for the Text File. Select the Text File, and add the name nlog.config.<br \/>\n\u6211\u4eec\u5c06\u5728\u4e3b\u9879\u76ee\u7684\u6587\u672c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u6240\u6709\u8fd9\u4e9b\u5e38\u91cf\uff0c\u5e76\u5c06\u5176\u547d\u540d\u4e3a nlog.config\u3002\u56e0\u6b64\uff0c\u8ba9\u6211\u4eec\u53f3\u952e\u5355\u51fb\u4e3b\u9879\u76ee\uff0c\u9009\u62e9 Add -&gt; New Item\uff0c\u7136\u540e\u641c\u7d22 Text File\u3002\u9009\u62e9\u6587\u672c\u6587\u4ef6\uff0c\u5e76\u6dfb\u52a0\u540d\u79f0 nlog.config\u3002<\/p>\n<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;\n&lt;nlog xmlns=&quot;http:\/\/www.nlog-project.org\/schemas\/NLog.xsd&quot; \n      xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot; \n      autoReload=&quot;true&quot; \n      internalLogLevel=&quot;Trace&quot; \n      internalLogFile=&quot;.\\internal_logs\\internallog.txt&quot;&gt;\n    &lt;targets&gt;\n        &lt;target name=&quot;logfile&quot; \n                xsi:type=&quot;File&quot; \n                fileName=&quot;.\\logs\\${shortdate}_logfile.txt&quot; \n                layout=&quot;${longdate} ${level:uppercase=true} ${message}&quot;\/&gt;\n    &lt;\/targets&gt;\n    &lt;rules&gt;\n        &lt;logger name=&quot;*&quot; minlevel=&quot;Debug&quot; writeTo=&quot;logfile&quot; \/&gt;\n    &lt;\/rules&gt;\n&lt;\/nlog&gt;<\/code><\/pre>\n<p>You can find the internal logs at the project root, and the logs folder in the bin\\debug folder of the main project once we start the app. Once the application is published both folders will be created at the root of the output folder which is what we want.<br \/>\n\u60a8\u53ef\u4ee5\u5728\u9879\u76ee\u6839\u76ee\u5f55\u4e0b\u627e\u5230\u5185\u90e8\u65e5\u5fd7\uff0c\u5e76\u5728\u542f\u52a8\u5e94\u7528\u7a0b\u5e8f\u540e\u5728\u4e3b\u9879\u76ee\u7684 bin\\debug \u6587\u4ef6\u5939\u4e2d\u627e\u5230 logs \u6587\u4ef6\u5939\u3002\u5e94\u7528\u7a0b\u5e8f\u53d1\u5e03\u540e\uff0c\u5c06\u5728\u8f93\u51fa\u6587\u4ef6\u5939\u7684\u6839\u76ee\u5f55\u4e0b\u521b\u5efa\u4e24\u4e2a\u6587\u4ef6\u5939\uff0c\u8fd9\u5c31\u662f\u6211\u4eec\u60f3\u8981\u7684\u3002<\/p>\n<p><b>NOTE:<\/b>  If you want to have more control over the log output, we suggest renaming the current file to nlog.development.config and creating another configuration file called nlog.production.config. Then you can do something like this in the code: env.ConfigureNLog($&quot;nlog.{env.EnvironmentName}.config&quot;); to get the different configuration files for different environments. From our experience production path is what matters, so this might be a bit redundant.<br \/>\n\u6ce8\u610f\uff1a\u5982\u679c\u60a8\u60f3\u5bf9\u65e5\u5fd7\u8f93\u51fa\u8fdb\u884c\u66f4\u591a\u63a7\u5236\uff0c\u6211\u4eec\u5efa\u8bae\u5c06\u5f53\u524d\u6587\u4ef6\u91cd\u547d\u540d\u4e3a nlog.development.config\uff0c\u5e76\u521b\u5efa\u53e6\u4e00\u4e2a\u540d\u4e3a nlog.production.config \u7684\u914d\u7f6e\u6587\u4ef6\u3002\u7136\u540e\uff0c\u60a8\u53ef\u4ee5\u5728\u4ee3\u7801\u4e2d\u6267\u884c\u5982\u4e0b\u4f5c\uff1aenv.ConfigureNLog($&quot;nlog.{env.EnvironmentName}.config&quot;);\u4ee5\u83b7\u53d6\u4e0d\u540c\u73af\u5883\u7684\u4e0d\u540c\u914d\u7f6e\u6587\u4ef6\u3002\u6839\u636e\u6211\u4eec\u7684\u7ecf\u9a8c\uff0c\u751f\u4ea7\u8def\u5f84\u624d\u662f\u6700\u91cd\u8981\u7684\uff0c\u6240\u4ee5\u8fd9\u53ef\u80fd\u6709\u70b9\u591a\u4f59\u3002<\/p>\n<h2>2.4 Configuring Logger Service for Logging Messages<\/h2>\n<p>2.4 \u914d\u7f6e Logger \u670d\u52a1\u4ee5\u8bb0\u5f55\u6d88\u606f<\/p>\n<p>Setting up the configuration for a logger service is quite easy. First, we need to update the Program class and include the path to the configuration file for the NLog configuration:\u200c<br \/>\n\u4e3a Logger \u670d\u52a1\u8bbe\u7f6e\u914d\u7f6e\u975e\u5e38\u7b80\u5355\u3002\u9996\u5148\uff0c\u6211\u4eec\u9700\u8981\u66f4\u65b0 Program \u7c7b\u5e76\u5305\u542b NLog \u914d\u7f6e\u7684\u914d\u7f6e\u6587\u4ef6\u8def\u5f84\uff1a<\/p>\n<pre><code>using CompanyEmployees.Extensions;\nusing Microsoft.AspNetCore.HttpOverrides;\nusing NLog;\n\nvar builder = WebApplication.CreateBuilder(args);\n\n\/\/ Add services to the container.\n\n\/\/ \u8fd9\u4e2a\u65b9\u6cd5\u5728net8\u7684nlog5.4\u4e2d\u63d0\u793a\u5df2\u8fc7\u65f6\nLogManager.LoadConfiguration(\n    string.Concat(Directory.GetCurrentDirectory(), \n    &quot;\/nlog.config&quot;));\nbuilder.Services.ConfigureCors();\nbuilder.Services.ConfigureIISIntegration();<\/code><\/pre>\n<p>We are using NLog\u2019s LogManager static class with the LoadConfiguration method to provide a path to the configuration file.<br \/>\n\u6211\u4eec\u5c06 NLog \u7684 LogManager \u9759\u6001\u7c7b\u4e0e LoadConfiguration \u65b9\u6cd5\u7ed3\u5408\u4f7f\u7528\uff0c\u4ee5\u63d0\u4f9b\u914d\u7f6e\u6587\u4ef6\u7684\u8def\u5f84\u3002<\/p>\n<p><b>NOTE:<\/b> If VisualStudio asks you to install the NLog package in the main project, don\u2019t do it. Just remove the LoggerService reference from the main project and add it again. We have already installed the required package in the LoggerService project and the main project should be able to reference it as well.<br \/>\n\u6ce8\u610f\uff1a\u5982\u679c VisualStudio \u8981\u6c42\u60a8\u5728\u4e3b\u9879\u76ee\u4e2d\u5b89\u88c5 NLog \u5305\uff0c\u8bf7\u4e0d\u8981\u8fd9\u6837\u505a\u3002\u53ea\u9700\u4ece\u4e3b\u9879\u76ee\u4e2d\u5220\u9664 LoggerService \u5f15\u7528\uff0c\u7136\u540e\u518d\u6b21\u6dfb\u52a0\u5373\u53ef\u3002\u6211\u4eec\u5df2\u7ecf\u5728 LoggerService \u9879\u76ee\u4e2d\u5b89\u88c5\u4e86\u6240\u9700\u7684\u5305\uff0c\u4e3b\u9879\u76ee\u4e5f\u5e94\u8be5\u80fd\u591f\u5f15\u7528\u5b83\u3002<\/p>\n<p>The next thing we need to do is to add the logger service inside the .NET Core\u2019s IOC container. There are three ways to do that:<br \/>\n\u63a5\u4e0b\u6765\u6211\u4eec\u9700\u8981\u505a\u7684\u662f\u5728 .NET Core \u7684 IOC \u5bb9\u5668\u4e2d\u6dfb\u52a0\u8bb0\u5f55\u5668\u670d\u52a1\u3002\u6709\u4e09\u79cd\u65b9\u6cd5\u53ef\u4ee5\u505a\u5230\u8fd9\u4e00\u70b9\uff1a<\/p>\n<p>\u2022 By calling the services.AddSingleton method, we can create a service the first time we request it and then every subsequent request will call the same instance of the service. This means that all components share the same service every time they need it and the same instance will be used for every method call.<br \/>\n\u2022 \u901a\u8fc7\u8c03\u7528services.AddSingleton \u65b9\u6cd5\uff0c\u6211\u4eec\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8bf7\u6c42\u670d\u52a1\u65f6\u521b\u5efa\u4e00\u4e2a\u670d\u52a1\uff0c\u7136\u540e\u6bcf\u4e2a\u540e\u7eed\u8bf7\u6c42\u90fd\u5c06\u8c03\u7528\u8be5\u670d\u52a1\u7684\u540c\u4e00\u5b9e\u4f8b\u3002\u8fd9\u610f\u5473\u7740\u6240\u6709\u7ec4\u4ef6\u6bcf\u6b21\u9700\u8981\u65f6\u90fd\u5171\u4eab\u76f8\u540c\u7684\u670d\u52a1\uff0c\u5e76\u4e14\u6bcf\u4e2a\u65b9\u6cd5\u8c03\u7528\u90fd\u5c06\u4f7f\u7528\u76f8\u540c\u7684\u5b9e\u4f8b\u3002<\/p>\n<p>\u2022 By calling the services.AddScoped method, we can create a service once per request. That means whenever we send an HTTP request to the application, a new instance of the service will be created.<br \/>\n\u2022 \u901a\u8fc7\u8c03\u7528services.AddScoped \u65b9\u6cd5\uff0c\u6211\u4eec\u53ef\u4ee5\u4e3a\u6bcf\u4e2a\u8bf7\u6c42\u521b\u5efa\u4e00\u6b21\u670d\u52a1\u3002\u8fd9\u610f\u5473\u7740\u6bcf\u5f53\u6211\u4eec\u5411\u5e94\u7528\u7a0b\u5e8f\u53d1\u9001 HTTP \u8bf7\u6c42\u65f6\uff0c\u90fd\u4f1a\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u670d\u52a1\u5b9e\u4f8b\u3002<\/p>\n<p>\u2022 By calling the services.AddTransient method, we can create a service each time the application requests it. This means that if multiple components need the service, it will be created again for every single component request.<br \/>\n\u2022 \u901a\u8fc7\u8c03\u7528services.AddTransient\u65b9\u6cd5\uff0c\u6211\u4eec\u53ef\u4ee5\u5728\u6bcf\u6b21\u5e94\u7528\u7a0b\u5e8f\u8bf7\u6c42\u65f6\u521b\u5efa\u4e00\u4e2a\u670d\u52a1\u3002\u8fd9\u610f\u5473\u7740\uff0c\u5982\u679c\u591a\u4e2a\u7ec4\u4ef6\u9700\u8981\u8be5\u670d\u52a1\uff0c\u5c06\u4e3a\u6bcf\u4e2a\u7ec4\u4ef6\u8bf7\u6c42\u518d\u6b21\u521b\u5efa\u8be5\u670d\u52a1\u3002<\/p>\n<p>So, let\u2019s add a new method in the ServiceExtensions class:<br \/>\n\u56e0\u6b64\uff0c\u8ba9\u6211\u4eec\u5728 ServiceExtensions \u7c7b\u4e2d\u6dfb\u52a0\u4e00\u4e2a\u65b0\u65b9\u6cd5\uff1a<\/p>\n<pre><code>using Contract;\nusing LoggerService;\n\nnamespace CompanyEmployees.Extensions\n{\n    public static class ServiceExtensions\n    {\n        public 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\n        public static void ConfigureIISIntegration(this IServiceCollection services) =&gt;\n            services.Configure&lt;IISOptions&gt;(options =&gt;\n            {\n            });\n\n        public static void ConfigureLoggerService(this IServiceCollection services) =&gt; \n            services.AddSingleton&lt;ILoggerManager, LoggerManager&gt;();\n    }\n}<\/code><\/pre>\n<p>And after that, we need to modify the Program class to include our newly created extension method:<br \/>\n\u4e4b\u540e\uff0c\u6211\u4eec\u9700\u8981\u4fee\u6539 Program \u7c7b\u4ee5\u5305\u542b\u6211\u4eec\u65b0\u521b\u5efa\u7684\u6269\u5c55\u65b9\u6cd5\uff1a<\/p>\n<pre><code>builder.Services.AddControllers();\nbuilder.Services.ConfigureLoggerService();\nbuilder.Services.ConfigureCors();\nbuilder.Services.ConfigureIISIntegration();<\/code><\/pre>\n<p>Every time we want to use a logger service, all we need to do is to inject it into the constructor of the class that needs it. .NET Core will resolve that service and the logging features will be available.<br \/>\n\u6bcf\u6b21\u6211\u4eec\u60f3\u4f7f\u7528 Logger \u670d\u52a1\u65f6\uff0c\u6211\u4eec\u9700\u8981\u505a\u7684\u5c31\u662f\u5c06\u5176\u6ce8\u5165\u5230\u9700\u8981\u5b83\u7684\u7c7b\u7684\u6784\u9020\u51fd\u6570\u4e2d\u3002.NET Core \u5c06\u89e3\u6790\u8be5\u670d\u52a1\uff0c\u5e76\u4e14\u65e5\u5fd7\u8bb0\u5f55\u529f\u80fd\u5c06\u53ef\u7528\u3002<\/p>\n<p>This type of injecting a class is called Dependency Injection and it is built into .NET Core.<br \/>\n\u8fd9\u79cd\u7c7b\u578b\u7684\u6ce8\u5165\u7c7b\u79f0\u4e3a\u4f9d\u8d56\u9879\u6ce8\u5165\uff0c\u5b83\u5185\u7f6e\u4e8e .NET Core \u4e2d\u3002<\/p>\n<p>Let\u2019s learn a bit more about it.<br \/>\n\u8ba9\u6211\u4eec\u66f4\u591a\u5730\u4e86\u89e3\u5b83\u3002<\/p>\n<h2>2.5 DI, IoC, and Logger Service Testing<\/h2>\n<p>2.5 DI\u3001IoC \u548c Logger \u670d\u52a1\u6d4b\u8bd5<\/p>\n<p>What is Dependency Injection (DI) exactly and what is IoC (Inversion of Control)?\u200c<br \/>\n\u7a76\u7adf\u4ec0\u4e48\u662f\u4f9d\u8d56\u6ce8\u5165 \uff08DI\uff09\uff0c\u4ec0\u4e48\u662f IoC\uff08\u63a7\u5236\u53cd\u8f6c\uff09\uff1f<\/p>\n<p>Dependency injection is a technique we use to achieve the decoupling of objects and their dependencies. It means that rather than instantiating an object explicitly in a class every time we need it, we can instantiate it once and then send it to the class.<br \/>\n\u4f9d\u8d56\u6ce8\u5165\u662f\u6211\u4eec\u7528\u6765\u5b9e\u73b0\u5bf9\u8c61\u53ca\u5176\u4f9d\u8d56\u7684\u89e3\u8026\u7684\u4e00\u79cd\u6280\u672f\u3002\u8fd9\u610f\u5473\u7740\uff0c\u4e0e\u5176\u6bcf\u6b21\u9700\u8981\u65f6\u90fd\u5728\u7c7b\u4e2d\u663e\u5f0f\u5b9e\u4f8b\u5316\u5bf9\u8c61\uff0c\u4e0d\u5982\u5b9e\u4f8b\u5316\u5b83\u4e00\u6b21\uff0c\u7136\u540e\u5c06\u5176\u53d1\u9001\u5230\u7c7b\u3002<\/p>\n<p>This is often done through a constructor. The specific approach we utilize is also known as the Constructor Injection.<br \/>\n\u8fd9\u901a\u5e38\u662f\u901a\u8fc7\u6784\u9020\u51fd\u6570\u5b8c\u6210\u7684\u3002\u6211\u4eec\u4f7f\u7528\u7684\u7279\u5b9a\u65b9\u6cd5\u4e5f\u79f0\u4e3a Constructor Injection\u3002<\/p>\n<p>In a system that is designed around DI, you may find many classes requesting their dependencies via their constructors. In this case, it is helpful to have a class that manages and provides dependencies to classes through the constructor.<br \/>\n\u5728\u56f4\u7ed5 DI \u8bbe\u8ba1\u7684\u7cfb\u7edf\u4e2d\uff0c\u60a8\u53ef\u80fd\u4f1a\u53d1\u73b0\u8bb8\u591a\u7c7b\u901a\u8fc7\u5176\u6784\u9020\u51fd\u6570\u8bf7\u6c42\u5176\u4f9d\u8d56\u9879\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u62e5\u6709\u4e00\u4e2a\u901a\u8fc7\u6784\u9020\u51fd\u6570\u7ba1\u7406\u7c7b\u5e76\u63d0\u4f9b\u7c7b\u4f9d\u8d56\u9879\u7684\u7c7b\u4f1a\u5f88\u6709\u5e2e\u52a9\u3002<\/p>\n<p>These classes are referred to as containers or more specifically, Inversion of Control containers. An IoC container is essentially a factory that is responsible for providing instances of the types that are requested from it.<br \/>\n\u8fd9\u4e9b\u7c7b\u79f0\u4e3a\u5bb9\u5668\uff0c\u6216\u8005\u66f4\u5177\u4f53\u5730\u8bf4\uff0c\u79f0\u4e3a\u63a7\u5236\u53cd\u8f6c\u5bb9\u5668\u3002IoC \u5bb9\u5668\u672c\u8d28\u4e0a\u662f\u4e00\u4e2a\u5de5\u5382\uff0c\u8d1f\u8d23\u63d0\u4f9b\u4ece\u5b83\u8bf7\u6c42\u7684\u7c7b\u578b\u7684\u5b9e\u4f8b\u3002<\/p>\n<p>To test our logger service, we are going to use the default WeatherForecastController. You can find it in the main project in the Controllers folder. It comes with the ASP.NET Core Web API template.<br \/>\n\u4e3a\u4e86\u6d4b\u8bd5\u6211\u4eec\u7684 logger \u670d\u52a1\uff0c\u6211\u4eec\u5c06\u4f7f\u7528\u9ed8\u8ba4\u7684 WeatherForecastController\u3002\u60a8\u53ef\u4ee5\u5728\u4e3b\u9879\u76ee\u7684 Controllers \u6587\u4ef6\u5939\u4e2d\u627e\u5230\u5b83\u3002\u5b83\u9644\u5e26 ASP.NET Core Web API \u6a21\u677f\u3002<\/p>\n<p>In the Solution Explorer, we are going to open the Controllers folder and locate the WeatherForecastController class. Let\u2019s modify it:<br \/>\n\u5728\u89e3\u51b3\u65b9\u6848\u8d44\u6e90\u7ba1\u7406\u5668\u4e2d\uff0c\u6211\u4eec\u5c06\u6253\u5f00 Controllers \u6587\u4ef6\u5939\u5e76\u627e\u5230 WeatherForecastController \u7c7b\u3002\u8ba9\u6211\u4eec\u4fee\u6539\u4e00\u4e0b\uff1a<\/p>\n<pre><code>using Contract;\nusing Microsoft.AspNetCore.Mvc;\n\n[Route(&quot;[controller]&quot;)]\n[ApiController]\npublic class WeatherForecastController : ControllerBase\n{\n    private ILoggerManager _logger;\n    public WeatherForecastController(ILoggerManager logger) { _logger = logger; }\n    [HttpGet]\n    public IEnumerable&lt;string&gt; Get()\n    {\n        _logger.LogInfo(&quot;Here is info message from our values controller.&quot;); \n        _logger.LogDebug(&quot;Here is debug message from our values controller.&quot;); \n        _logger.LogWarn(&quot;Here is warn message from our values controller.&quot;); \n        _logger.LogError(&quot;Here is an error message from our values controller.&quot;);\n        return new string[] { &quot;value1&quot;, &quot;value2&quot; };\n    }\n}<\/code><\/pre>\n<p>Now let\u2019s start the application and browse to \uff1a<br \/>\n\u73b0\u5728\uff0c\u8ba9\u6211\u4eec\u542f\u52a8\u5e94\u7528\u7a0b\u5e8f\u5e76\u6d4f\u89c8\u5230\uff1a<br \/>\n<a href=\"https:\/\/localhost:5001\/weatherforecast\">https:\/\/localhost:5001\/weatherforecast<\/a>.<\/p>\n<p>As a result, you will see an array of two strings. Now go to the folder that you have specified in the nlog.config file, and check out the result. You should see two folders: the internal_logs folder and the logs folder. Inside the logs folder, you should find a file with the following logs:<br \/>\n\u7ed3\u679c\uff0c\u60a8\u5c06\u770b\u5230\u4e00\u4e2a\u5305\u542b\u4e24\u4e2a\u5b57\u7b26\u4e32\u7684\u6570\u7ec4\u3002\u73b0\u5728\u8f6c\u5230\u60a8\u5728 nlog.config \u6587\u4ef6\u4e2d\u6307\u5b9a\u7684\u6587\u4ef6\u5939\uff0c\u5e76\u67e5\u770b\u7ed3\u679c\u3002\u60a8\u5e94\u8be5\u770b\u5230\u4e24\u4e2a\u6587\u4ef6\u5939\uff1ainternal_logs \u6587\u4ef6\u5939\u548c logs \u6587\u4ef6\u5939\u3002\u5728 logs \u6587\u4ef6\u5939\u4e2d\uff0c\u60a8\u5e94\u8be5\u4f1a\u627e\u5230\u4e00\u4e2a\u5305\u542b\u4ee5\u4e0b\u65e5\u5fd7\u7684\u6587\u4ef6\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/images\/ultimateaspnetcorewebapi6\/0203.jpg\" alt=\"alt text\" \/><\/p>\n<p>That\u2019s all we need to do to configure our logger for now. We\u2019ll add some messages to our code along with the new features.<br \/>\n\u8fd9\u5c31\u662f\u6211\u4eec\u73b0\u5728\u9700\u8981\u505a\u7684\u914d\u7f6e logger \u7684\u5168\u90e8\u5de5\u4f5c\u3002\u6211\u4eec\u5c06\u5411\u4ee3\u7801\u4e2d\u6dfb\u52a0\u4e00\u4e9b\u6d88\u606f\u4ee5\u53ca\u65b0\u529f\u80fd\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>2 Configuring a logging service 2 \u914d\u7f6e\u65e5\u5fd7\u8bb0\u5f55\u670d\u52a1 Why do logging messages matter so much during application development? While our application is in the development stage, it&#8217;s easy to debug the code and find out what happened. But debugging in a production environment is not that easy.\u200c \u4e3a\u4ec0\u4e48\u5728\u5e94\u7528\u7a0b\u5e8f\u5f00\u53d1\u8fc7\u7a0b\u4e2d\uff0c\u65e5\u5fd7\u8bb0\u5f55\u6d88\u606f\u5982\u6b64\u91cd\u8981\uff1f\u867d\u7136\u6211\u4eec\u7684\u5e94\u7528\u7a0b\u5e8f\u5904\u4e8e\u5f00\u53d1\u9636\u6bb5\uff0c\u4f46\u5f88\u5bb9\u6613\u8c03\u8bd5\u4ee3\u7801\u5e76\u627e\u51fa\u53d1\u751f\u4e86\u4ec0\u4e48\u3002\u4f46\u662f\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u8fdb\u884c\u8c03\u8bd5\u5e76\u4e0d\u662f\u90a3\u4e48\u5bb9\u6613\u3002 That&#8217;s why log messages are a great way [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1102","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/1102","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=1102"}],"version-history":[{"count":0,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/1102\/revisions"}],"wp:attachment":[{"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1102"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1102"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1102"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}