Asp.Net Core实战(干货)

内容预览:
  • /// </summary> /// <param name="service"></param>...~
  • /// </summary> /// <param name="service"></param>...~
  • 如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为...~

序言

使用.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标签解读

一、浅谈Startup类

在ASP.NET Core应用程序中,必须包含有Startup类,在主函数调用中,Startup类名可以随意命名,但通常使用系统默认的startup,可以通过startup的构造函数进行依赖注入startup类中必须包含Configure方法同时可以根据实际情况添加ConfigureServices方法,这两个方法均在应用程序运行时被调用。Startup 类的 执行顺序:构造 -> 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///",
defaults:
new { controller = "Values", action = "Index" });
// 默认路由
routes.MapRoute(
name:
"default",
template:
"//",
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”),即能实现全局的跨域设置

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

 这里是写的一个公共方法去读取配置文件appsettings.json

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 "" 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 "" not be found");
}

var implementAssembly = RuntimeHelper.GetAssembly(implementAssemblyName);
if (implementAssembly == null)
{
throw new DllNotFoundException($"the dll "" 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

 在Startupl类的ConfigureServices方法中添加

// 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写入文件日志

新建配置文件命名为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
="LogsDebug$.log"
layout
="日志时间:$$日志来源:$$日志级别:$}$消息内容:$$异常信息:$$==============================================================$" >
</target>
<target
xsi:type
="File"
name
="InfoFile"
fileName
="LogsInfo$.log"
layout
="日志时间:$$日志来源:$$日志级别:$}$消息内容:$$异常信息:$$==============================================================$" >
</target>
<target
xsi:type
="File"
name
="ErrorFile"
fileName
="LogsError$.log"
layout
="日志时间:$$日志来源:$$日志级别:$}$消息内容:$$异常信息:$$==============================================================$" >
</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

 在Startup类Configure方法中添加配置

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

#region NLog配置
loggerFactory.AddNLog();
// 添加NLog
loggerFactory.ConfigureNLog($"\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

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

添加依赖项: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="$"/>
<!--日志等级-->
<parameter name="@logLevel" layout="$"/>
<!--日志消息-->
<parameter name="@message" layout="$"/>
<!--异常信息-->
<parameter name="@exception" layout="$" />
<!--堆栈信息-->
<parameter name="@stackTrace" layout="$"/>
<!--自定义消息内容-->
<parameter name="@desc" layout="$"/>
</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标签解读

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

layouts 用来规定布局样式,语法“${属性}”,可以把上下文信息插入到日志中,更多布局渲染器可参考https://github.com/nlog/NLog/wiki/Layout%20Renderers

<rules>标签

各种规则配置在logger里

name – 记录者的名字

minlevel – 最低级别

maxlevel – 最高级别

level – 单一日志级别

levels – 一系列日志级别,由逗号分隔。

writeTo – 规则匹配时日志应该被写入的一系列目标,由逗号分隔。

 

 

 

 目前只整理了这些,后续会持续更新到这里面,如有不合理的地方,请大家加以斧正,,,希望能和大家共同学习、共同进步,,

 

 

权责申明

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

 

和大佬一起学习网络安全知识

以上就是:Asp.Net Core实战(干货) 的全部内容

本站部分内容来源于互联网和用户投稿,如有侵权请联系我们删除,谢谢^^
Email:[email protected]


0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论