Asp.Net Core实战(干货)

匿名 (未验证) 提交于 2019-12-02 22:06:11

使用.NET Core,团队可以更容易专注的在.net core上工作。比如核心类库(如System.Collections)的更改仍然需要与.NET Framework相同的活力,但是ASP.NET Core或Entity Framework Core可以更轻松地进行实质性更改,而不受向后兼容性的限制。.NET Core借鉴了.NET Framework的最佳实践,并将软件工程的最新进展结合在一起。

寒暄、扯淡已经完毕,,,下面是我最近时间对.Net Core整理的相关知识,觉得这些在项目中是最基础且最会应用到的,,,,不喜欢扯理论,直接撸码:

1、浅谈Startup类

2、自定义路由

3、跨域设置

4、自定义读取配置文件信息

5、程序集批量依赖注入

6、使用NLog写入文件日志

7、使用NLog写入数据库日志

8、Nlog标签解读

-> configureServices ->configure

ConfigureServices方法:主要用于服务配置,比如依赖注入(DI)的配置,使用时该方法必须在Configure方法之前

Configure方法:用于应用程序响应HTTP请求,通过向IApplicationBuilder实例添加中间件组件来配置请求管道

在Startup类的Configure方法配置

public void Configure(IApplicationBuilder app, IHostingEnvironment env)         {             if (env.IsDevelopment())             {                 app.UseDeveloperExceptionPage();             }              #region 自定义路由配置             app.UseMvc(routes =>             {                 // 自定义路由                 routes.MapRoute(                   name: "default1",                   template: "api/{controller}/{action}/{id?}",                   defaults: new { controller = "Values", action = "Index" });                 // 默认路由                 routes.MapRoute(                    name: "default",                    template: "{controller}/{action}/{id?}",                    defaults: new { controller = "Values", action = "Index" });             });             #endregion         }
View Code

在Startup类的ConfigureServices方法配置

public void ConfigureServices(IServiceCollection services)         {             #region 跨域设置             services.AddCors(options =>             {                 options.AddPolicy("AppDomain", builder =>                 {                     builder.AllowAnyOrigin() // Allow access to any source from the host                     .AllowAnyMethod()        // Ensures that the policy allows any method                     .AllowAnyHeader()        // Ensures that the policy allows any header                     .AllowCredentials();     // Specify the processing of cookie                 });             });             #endregion              services.AddMvc();         }
View Code

其中“AppDomain”这个名字是自定义的,大家可以根据自己的喜好定义不同的名字,配置完成之后,在控制器上面添加[EnableCors("AppDomain")]特性即可,如果要实现全局的跨域设置,可以在Configure方法里面配置app.UseCors("AppDomain"),即能实现全局的跨域设置

using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Json; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using System.IO;  public class JsonConfigurationHelper     {         public static T GetAppSettings<T>(string key,string path= "appsettings.json") where T : class, new()         {             var currentClassDir = Directory.GetCurrentDirectory();             IConfiguration config = new ConfigurationBuilder()                 .SetBasePath(currentClassDir)                 .Add(new JsonConfigurationSource { Path = path, Optional = false, ReloadOnChange = true })                 .Build();             var appconfig = new ServiceCollection()                 .AddOptions()                 .Configure<T>(config.GetSection(key))                 .BuildServiceProvider()                 .GetService<IOptions<T>>()                 .Value;             return appconfig;         }     }
View Code
/// <summary>         /// 读取配置文件         /// </summary>         /// <returns></returns>         [HttpGet]         public dynamic JsonConfig()         {             var jsonStr = JsonConfigurationHelper.GetAppSettings<ConfigDTO>("config");             return Ok(jsonStr);         }          /// <summary>         /// 实体类         /// </summary>         public class ConfigDTO         {             public dynamic name { get; set; }         }
View Code
{   "config": {     "name": "Core.Api"   } }
View Code

截图看效果

我们都知道依赖注入主要是为了方便解耦,解除应用程序之间的依赖关系,在我看来DI、IOC这两者差不多是一样的,DI是从应用程序的角度而IOC是从容器的角度,它们主要是对同一件事情的不同角度的描述。然而,,,,,,当我们项目业务比较多的时候,如果要实现多个业务的注入,通常方法是手动一个个的添加注入,这样可能有点太繁琐,所以就想到了利用反射实现批量注入,,,,,,

帮助类

public class RuntimeHelper     {         /// <summary>         /// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包         /// </summary>         /// <returns></returns>         public static IList<Assembly> GetAllAssemblies()         {             var list = new List<Assembly>();             var deps = DependencyContext.Default;             var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package");//排除所有的系统程序集、Nuget下载包             foreach (var lib in libs)             {                 try                 {                     var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));                     list.Add(assembly);                 }                 catch (Exception)                 {                     // ignored                 }             }             return list;         }          public static Assembly GetAssembly(string assemblyName)         {             return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName));         }          public static IList<Type> GetAllTypes()         {             var list = new List<Type>();             foreach (var assembly in GetAllAssemblies())             {                 var typeInfos = assembly.DefinedTypes;                 foreach (var typeInfo in typeInfos)                 {                     list.Add(typeInfo.AsType());                 }             }             return list;         }          public static IList<Type> GetTypesByAssembly(string assemblyName)         {             var list = new List<Type>();             var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));             var typeInfos = assembly.DefinedTypes;             foreach (var typeInfo in typeInfos)             {                 list.Add(typeInfo.AsType());             }             return list;         }          public static Type GetImplementType(string typeName, Type baseInterfaceType)         {             return GetAllTypes().FirstOrDefault(t =>             {                 if (t.Name == typeName &&                     t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name))                 {                     var typeInfo = t.GetTypeInfo();                     return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType;                 }                 return false;             });         }     }
View Code
public static class ServiceExtension     {         /// <summary>         /// 用DI批量注入接口程序集中对应的实现类。         /// </summary>         /// <param name="service"></param>         /// <param name="interfaceAssemblyName"></param>         /// <returns></returns>         public static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName)         {             if (service == null)                 throw new ArgumentNullException(nameof(service));             if (string.IsNullOrEmpty(interfaceAssemblyName))                 throw new ArgumentNullException(nameof(interfaceAssemblyName));              var assembly = RuntimeHelper.GetAssembly(interfaceAssemblyName);             if (assembly == null)             {                 throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found");             }              //过滤掉非接口及泛型接口             var types = assembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType);              foreach (var type in types)             {                 var implementTypeName = type.Name.Substring(1);                 var implementType = RuntimeHelper.GetImplementType(implementTypeName, type);                 if (implementType != null)                     service.AddSingleton(type, implementType);             }             return service;         }          /// <summary>         /// 用DI批量注入接口程序集中对应的实现类。         /// </summary>         /// <param name="service"></param>         /// <param name="interfaceAssemblyName">接口程序集的名称(不包含文件扩展名)</param>         /// <param name="implementAssemblyName">实现程序集的名称(不包含文件扩展名)</param>         /// <returns></returns>         public static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName, string implementAssemblyName)         {             if (service == null)                 throw new ArgumentNullException(nameof(service));             if (string.IsNullOrEmpty(interfaceAssemblyName))                 throw new ArgumentNullException(nameof(interfaceAssemblyName));             if (string.IsNullOrEmpty(implementAssemblyName))                 throw new ArgumentNullException(nameof(implementAssemblyName));              var interfaceAssembly = RuntimeHelper.GetAssembly(interfaceAssemblyName);             if (interfaceAssembly == null)             {                 throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found");             }              var implementAssembly = RuntimeHelper.GetAssembly(implementAssemblyName);             if (implementAssembly == null)             {                 throw new DllNotFoundException($"the dll \"{implementAssemblyName}\" not be found");             }              //过滤掉非接口及泛型接口             var types = interfaceAssembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType);              foreach (var type in types)             {                 //过滤掉抽象类、泛型类以及非class                 var implementType = implementAssembly.DefinedTypes                     .FirstOrDefault(t => t.IsClass && !t.IsAbstract && !t.IsGenericType &&                                          t.GetInterfaces().Any(b => b.Name == type.Name));                 if (implementType != null)                 {                     service.AddSingleton(type, implementType.AsType());                 }             }              return service;         }     }
View Code

// This method gets called by the runtime. Use this method to add services to the container.         public void ConfigureServices(IServiceCollection services)         {             #region 程序集批量依赖注入             services.RegisterAssembly("Core.BLL");             #endregion              services.AddMvc();         }
View Code

调用(Ps:Core.BLL这个类库里面分别有一个接口IAccountService和一个类AccountService,AccountService类去继承接口IAccountService并实现接口里面的方法)

public interface IAccountService     {         int GetLst();     }  public class AccountService: IAccountService     {         public int GetLst()         {             return 1;         }     }
View Code
public class ValuesController : Controller     {         private readonly IAccountService _accountService;         public ValuesController(IAccountService accountService)         {             _accountService = accountService;         }          [HttpGet]         public dynamic GetAccount()         {             var result = this._accountService.GetLst();             return Ok();         } }
View Code

新建配置文件命名为Nlog.config

<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">   <targets>      <!--写入文件-->     <target      xsi:type="File"      name="DebugFile"      fileName="Logs\Debug\${shortdate}.log"      layout="日志时间:${longdate}${newline}日志来源:${callsite}${newline}日志级别:${uppercase:${level}}${newline}消息内容:${message}${newline}异常信息:${exception}${newline}==============================================================${newline}" >     </target>     <target        xsi:type="File"        name="InfoFile"        fileName="Logs\Info\${shortdate}.log"       layout="日志时间:${longdate}${newline}日志来源:${callsite}${newline}日志级别:${uppercase:${level}}${newline}消息内容:${message}${newline}异常信息:${exception}${newline}==============================================================${newline}" >     </target>     <target        xsi:type="File"        name="ErrorFile"        fileName="Logs\Error\${shortdate}.log"       layout="日志时间:${longdate}${newline}日志来源:${callsite}${newline}日志级别:${uppercase:${level}}${newline}消息内容:${message}${newline}异常信息:${exception}${newline}==============================================================${newline}" >     </target>        <rules>     <logger name="FileLogger" minlevel="Debug" maxLevel="Debug" writeTo="DebugFile" />     <logger name="FileLogger" minlevel="Info" maxLevel="Info" writeTo="InfoFile" />     <logger name="FileLogger" minlevel="Error" maxLevel="Error" writeTo="ErrorFile" />   </rules> </nlog>
View Code

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)         {             if (env.IsDevelopment())             {                 app.UseDeveloperExceptionPage();             }              #region NLog配置             loggerFactory.AddNLog(); // 添加NLog             loggerFactory.ConfigureNLog($"{Directory.GetCurrentDirectory()}\\Nlog.config"); // 添加Nlog.config配置文件             loggerFactory.AddDebug();             #endregion         }
View Code

写入日志到文件

public class ValuesController : Controller     {         private readonly Logger _logger;                 public ValuesController()         {             _logger = LogManager.GetLogger("FileLogger");         }          /// <summary>         /// 写入文件日志         /// </summary>         /// <returns></returns>         [HttpGet]         public dynamic WriteLogToFile()         {             _logger.Info("写入Info文件");             _logger.Debug("写入Debug文件");             _logger.Error("写入Error文件");             return Ok();         } }
View Code

添加依赖项:Microsoft.Extensions.LoggingNLog.Extensions.Logging

新建配置文件命名为Nlog.config

<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">   <targets>      <!--写入数据库-->     <target xsi:type="Database" name="Database"             connectionString="Data Source=.;Initial Catalog=MyDb;Persist Security Info=True;User ID=sa;Password=123456"             commandText="insert into NLog_Log([CreateOn],[Origin],[LogLevel], [Message], [Exception],[StackTrace],[Desc]) values (getdate(), @origin, @logLevel, @message,@exception, @stackTrace,@desc)">              <!--日志来源-->       <parameter name="@origin" layout="${callsite}"/>       <!--日志等级-->       <parameter name="@logLevel" layout="${level}"/>       <!--日志消息-->       <parameter name="@message" layout="${message}"/>       <!--异常信息-->       <parameter name="@exception" layout="${exception}" />       <!--堆栈信息-->       <parameter name="@stackTrace" layout="${stacktrace}"/>       <!--自定义消息内容-->       <parameter name="@desc" layout="${event-context:item=Desc}"/>     </target>   </targets>    <rules>     <logger name="DbLogger" levels="Trace,Debug,Info,Error"  writeTo="Database"/>   </rules> </nlog>
View Code

同第六项代码一样,也是在Configure方法设置,写入日志到数据库

/// <summary>         /// 将日志写入数据库         /// </summary>         /// <returns></returns>         [HttpGet]         public dynamic WriteLogToDb()         {             Logger _dblogger = LogManager.GetLogger("DbLogger");             LogEventInfo ei = new LogEventInfo();             ei.Properties["Desc"] = "我是自定义消息";             _dblogger.Info(ei);             _dblogger.Debug(ei);             _dblogger.Trace(ei);             return Ok();         }
View Code
USE [MyDb] GO  /****** Object:  Table [dbo].[NLog_Log]    Script Date: 08/09/2018 17:13:20 ******/ SET ANSI_NULLS ON GO  SET QUOTED_IDENTIFIER ON GO  CREATE TABLE [dbo].[NLog_Log](     [ID] [int] IDENTITY(1,1) NOT NULL,     [Origin] [nvarchar](500) NULL,     [LogLevel] [nvarchar](500) NULL,     [Message] [nvarchar](500) NULL,     [Desc] [nvarchar](500) NULL,     [Exception] [nvarchar](500) NULL,     [StackTrace] [nvarchar](500) NULL,     [CreateOn] [datetime] NULL ) ON [PRIMARY]  GO
View Code

NLog的使用方式基本上和其它的Log库差不多,用于输出日志的级别包括:Trace,Debug,Info,Warn,Error,Fatal

<nlog>标签
autoReload 修改配置文件后是否允许自动加载无须重启程序
throwExceptions 内部日志系统抛出异常
internalLogLevel 可选Trace|Debug|Info|Warn|Error|Fatal决定内部日志的级别 Off 关闭
internalLogFile 把内部的调试和异常信息都写入指定文件里
建议throwExceptions的值设为“false”,这样由于日志引发的问题不至于导致应用程序的崩溃。
<targets>标签
<target />区域定义了日志的目标或者说输出 ,,在这里可以按需设置文件名称和格式,输出方式。
name:自定义该target的名字,可供rule规则里使用
type: 定义类型,官方提供的可选类型有:
Chainsaw|ColoredConsole |Console |Database|Debug|Debugger|EventLog|File|LogReceiverService|Mail|Memory|MethodCall|Network |NLogViewer|Null |OutputDebugString|PerfCounter|Trace|WebService
不过常用的还是 File \Database \Colored Console\ Mail

https://github.com/nlog/NLog/wiki/Layout%20Renderers

<rules>标签

各种规则配置在logger里
name - 记录者的名字
minlevel - 最低级别
maxlevel - 最高级别
level - 单一日志级别
levels - 一系列日志级别,由逗号分隔。
writeTo - 规则匹配时日志应该被写入的一系列目标,由逗号分隔。

权责申明

http://www.cnblogs.com/sportsky/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为大家带来好的技术文章!想跟我一起进步么?那就【关注】我吧。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!