.NET6中一些常用组件的配置及使用记录,持续更新中。。。

NET6App

介绍

.NET 6的CoreApp框架,用来学习.NET6的一些变动和新特性,使用EFCore,等一系列组件的运用,每个用单独的文档篇章记录,持续更新文档哦。

如果对您有帮助,点击⭐Star⭐关注 ,感谢支持开源!

软件架构

分为模型层,服务层,接口层来做测试使用

0.如何使用IConfiguration、Environment

直接在builder后的主机中使用。

builder.Configuration;

builder.Environment

1.如何使用Swagger

.NET 6 自带模板已经默认添加Swagger,直接使用即可。

builder.Services.AddSwaggerGen();if(app.Environment.IsDevelopment()){    app.UseSwagger();    app.UseSwaggerUI();}

2. 如何添加EFCore到.NET 6中

按照EFCore常规使用方法,申明表的Entity及Dbcontext后,在program.cs文件中添加

builder.Services.AddDbContext(opt => {    opt.UseSqlServer(builder.Configuration.GetConnectionString("Default"));});

即可在其他地方注入使用 DataContext

使用Sqlite数据库,需要引用 Microsoft.EntityFrameworkCore.Sqlite,

并在添加服务时,改为

opt.UseSqlite(builder.Configuration.GetConnectionString("Default"));

包管理控制台数据库结构生成方法:

使用 add-migration 创建迁移

使用 update-database 更新数据结构

3.如何注入一个服务

builder.Services.AddScoped<UserIdentyService>();

4.如何定义全局的using引用

在根目录下新建一个 cs文件,比如Globalusing.cs,在里面添加你的全局引用,和常规引用不同的是,在using前面添加 global

globalusingService;globalusingEntity;globalusingEntity.Dto;

5.如何使用Autofac

添加 Nuget 引用

Autofac.Extensions.DependencyInjection

program.cs文件添加autofac的使用和注入配置

builder.Host.UseServiceProviderFactory(newAutofacServiceProviderFactory());builder.Host.ConfigureContainer(builder => {    Assembly assembly = Assembly.Load("Service.dll");    builder.RegisterAssemblyTypes(assembly)//.AsImplementedInterfaces()// 无接口的注入方式.InstancePerDependency(); });

此时即可构造函数注入使用。

6.如何使用Log4Net

添加引用

Microsoft.Extensions.Logging.Log4Net.AspNetCore

新建配置文件 log4net.config;

添加service配置

//注入Log4Netbuilder.Services.AddLogging(cfg =>{//默认的配置文件路径是在根目录,且文件名为log4net.config//cfg.AddLog4Net();//如果文件路径或名称有变化,需要重新设置其路径或名称//比如在项目根目录下创建一个名为config的文件夹,将log4net.config文件移入其中,并改名为log4net.config//则需要使用下面的代码来进行配置cfg.AddLog4Net(newLog4NetProviderOptions()    {        Log4NetConfigFileName ="config/log4net.config",        Watch =true});});

即可在需要的地方定义使用

_logger = LogManager.GetLogger(typeof(UserController));

7.如何使用全局异常过滤器

首先新建 GlobalExceptionFilter 全局异常过滤器,继承于 ExceptionFilter ,用于接收处理抛出的异常

publicclassGlobalExceptionFilter:IExceptionFilter{    readonly IWebHostEnvironment hostEnvironment;    readonly ILog logger;publicGlobalExceptionFilter(IWebHostEnvironment _hostEnvironment){this.hostEnvironment = _hostEnvironment;this.logger = LogManager.GetLogger(typeof(GlobalExceptionFilter));    }publicvoidOnException(ExceptionContext context){if(!context.ExceptionHandled)//如果异常没有处理{            var result =newApiResult            {                Code =500,                IsSuccess =false,                Message ="服务器发生未处理的异常"};if(hostEnvironment.IsDevelopment())            {                result.Message +=","+ context.Exception.Message;                result.Data = context.Exception.StackTrace;            }            logger.Error(result);            context.Result =newJsonResult(result);            context.ExceptionHandled =true;//异常已处理}    }}

然后在Service中添加全局异常过滤器

builder.Services.AddControllers(option =>

    {

        option.Filters.Add<GlobalExceptionFilter>();

    }

);

添加控制器方法完成测试

[HttpGet("exception")]publicApiResultExceptionAction(){thrownewNotImplementedException();}

8.如何使用redis做缓存

使用 StackExchange.Redis 作为缓存组件(其他组件类似的使用方式)。nuget 安装 StackExchange.Redis.Extensions.Core

首先,先建立一个类 RedisClient ,用于管理redis的连接和操作,再建立一个 RedisClientFactory 类,用于创建 redis的连接;

publicclassRedisClient{...}publicclassRedisClientFactory{...}

appsettings.json 中添加redis的配置

"RedisConfig": {

    "Redis_Default": {

      "Connection": "127.0.0.1:6379",

      "InstanceName": "Redis1:"

    },

    "Redis_6": {

      "Connection": "127.0.0.1:6379",

      "DefaultDatabase": 6,

      "InstanceName": "Redis2:"

    }

  }

service中添加 redis客户端的引用

//添加redis的使用builder.Services.AddSingleton(_=> RedisClientFactory.GetInstance(builder.Configuration));

一顿操作后,就可以在你想要使用redis的地方引用了

RedisClient redisClient...this.redisDb = redisClient.GetDatabase("Redis_Default");redisDb.StringSet("clientId","clientId", TimeSpan.FromSeconds(10));

要使用redis做分布式缓存,先引用 Microsoft.Extensions.Caching.StackExchangeRedis

//将Redis分布式缓存服务添加到服务中builder.Services.AddStackExchangeRedisCache(options =>    {//用于连接Redis的配置  Configuration.GetConnectionString("RedisConnectionString")读取配置信息的串options.Configuration ="Redis_6";// Configuration.GetConnectionString("RedisConnectionString");//Redis实例名RedisDistributedCacheoptions.InstanceName ="RedisDistributedCache";    });

引用自 "分布式 Redis 缓存"

9. 如何添加使用定时任务组件

此处使用 Hangfire 定时任务组件,轻便,可持久化,还有面板。

引用 Hangfire 后,即可新增定时任务。

//启用Hangfire服务.builder.Services.AddHangfire(x => x.UseStorage(newMemoryStorage()));builder.Services.AddHangfireServer();...//启用Hangfire面板app.UseHangfireDashboard();//开启一个定时任务RecurringJob.AddOrUpdate("test",() => Console.WriteLine("Recurring!"), Cron.Minutely());

访问 https://localhost:7219/hangfire 即可看到任务面板

10. 如何使用业务锁锁住下单或者支付操作

首先,做这个事需要能先构建出一个锁出来,这个锁有个锁的标识key,可以根据这个key判定key对应的锁是否存在,

这样的话,在某个用户支付或者下单减库存啥的时候,就可以按照这个key先上锁,后面有用户走其他渠道进行同样的操作的时候,就可以根据是否上锁了,来判断操作能否继续。

比如一个支付订单的业务,可以在手机上操作,也可以在电脑上操作,这个时候就可以给支付接口上锁,只要一个支付过程存在着,并且没有超时,那就不能在其他渠道进行操作。

我们上面已经使用了redis,下面就用redis构建个锁来模拟这个操作,具体看代码:

/// <summary>/// 测试业务锁/// </summary>/// <returns></returns>[HttpGet("lockhandle")]publicasync TaskLockHandle(intuserId){        var key ="user";        var token = $"ID:{userId}";try{if(redisDb.LockTake(key, token, TimeSpan.FromSeconds(50)))            {                await Task.Delay(30*1000);returnawait Task.FromResult(ApiResult.Success($"ID:{userId} 获取到锁了,操作正常,connectId:{Request.HttpContext.Connection.Id}"));            }else{returnawait Task.FromResult(ApiResult.Fail($"有正在操作的锁,connectId:{Request.HttpContext.Connection.Id}"));            }        }catch(Exception)        {throw;        }        finally        {            redisDb.LockRelease(key, token);        }    }

11. 如何配置跨域

此处主要记录全局跨域,不包括指定api跨域。先增加一个配置 "Cors": "http:127.0.0.1:5001",配置可以跨域的url,也可以使用默认跨域配置。

host配置以下服务,按需使用:

builder.Services.AddCors(delegate (CorsOptions options){    options.AddPolicy("CorsPolicy", delegate (CorsPolicyBuilder corsBuilder)    {//指定url跨域corsBuilder.WithOrigins(builder.Configuration.GetValue("Cors").Split(','));//默认跨域corsBuilder.SetIsOriginAllowed((string_) =>true).AllowAnyMethod().AllowAnyHeader()            .AllowCredentials();    });});

12. 如何使用NewtonsoftJson

.NET6 默认的系列化库是内置的 System.Text.Json,使用中如果有诸多不熟悉的地方,那肯定是想换回 NewtonsoftJson,需要nuget 引用 Microsoft.AspNetCore.Mvc.NewtonsoftJson 来配置使用,

常用配置包括日期格式、大小写规则、循环引用配置。。。等,下面是一个配置

builder.Services.AddControllers(option =>    {        option.Filters.Add();    }).AddNewtonsoftJson(options =>{    options.SerializerSettings.ContractResolver =newCamelCasePropertyNamesContractResolver();//序列化时key为驼峰样式options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;    options.SerializerSettings.DateFormatString ="yyyy-MM-dd HH:mm:ss";    options.SerializerSettings.ReferenceLoopHandling =  ReferenceLoopHandling.Ignore;//忽略循环引用});

13. 如何使用SignalR

首先添加一个 ChatHub 作为 交互中心处理器

publicclassChatHub:Hub    {publicasync TaskSendMessage(stringuser,stringmessage){            await Clients.All.SendAsync("ReceiveMessage", user, message);        }    }

在主机中使用服务

builder.Services.AddSignalR();...app.UseEndpoints(endpoints =>{    endpoints.MapHub("/chatHub");});

14. 如何使用Dapper

Dapper是大家常用的一个数据库连接扩展组件,下面介绍下,如何使用常规扩展,来在.net Core中使用Dapper。

首先,建立一个DbComponent ,来获取由 .netCore 提供的 Configuration 配置文件,并用 DbProviderFactories 工厂,创建数据库连接,此类只管创建连接,又其他使用类进行销毁。

/// <summary>/// 创建连接处理/// </summary>publicclassDbComponent{/// 数据库连接配置privatestaticConnectionStringSettings connectionSetting;publicstaticvoidInitDapper(ConnectionStringSettings connectionStringSettings){        connectionSetting = connectionStringSettings;    }//通过工厂模式创建Connection连接 此连接已打开publicstaticIDbConnectionGetConnection(){        get {            var cnnection = DbProviderFactories.GetFactory(connectionSetting.ProviderName).CreateConnection();if(cnnection == null)thrownewException("数据库链接获取失败!");            cnnection.ConnectionString = connectionSetting.ConnectionString;            cnnection.Open();returncnnection;        }    }}

使用前,需要在program中初始化一下组件

/// <summary>/// 初始化Dapper组件/// </summary>DbProviderFactories.RegisterFactory("Microsoft.Data.Sqlite", Microsoft.Data.Sqlite.SqliteFactory.Instance);DbComponent.InitDapper(newSystem.Configuration.ConnectionStringSettings{    ConnectionString = builder.Configuration.GetConnectionString("Default"),    ProviderName ="Microsoft.Data.Sqlite"});

程序启动后,就可以在需要的地方使用

publicclassUserIdentyService{publicApiResultDapperList(){using(var connect = DbComponent.Connection)        {            var users= connect.Query("SELECT * FROM Users").ToList();returnApiResult.Success(users);        }    }    }

15. 如何添加自定义配置文件

有时候我们不想把配置全部放在 appsettings.json ,我们想自己建立一个文件夹来存储其他配置文件,比如config/...json之类的,咋整呢,

我们新建个文件夹 config,下面建立一个配置文件app.json,里面存几个配置以便验证。

使用前添加如下代码即可

builder.Configuration.AddJsonFile("config/app.json");Console.WriteLine(builder.Configuration.GetValue("weixin"));

16. 如何简单上传文件

上传文件是每个api框架都会实现的功能,我们先实现一个简单的文件上传。

首先做个配置文件,存储上传的文件存储位置、大小及格式限制等的配置

publicclassUploadConfig{/// <summary>/// 最大值/// </summary>publicintMaxSize { get;set; } =1024*1024*1024;/// <summary>/// 存储路径/// </summary>publicstringUploadDir { get;set; } = @"D://Upload";/// <summary>/// 站点名称/// </summary>publicstringWebSite { get;set; }}

添加测试action,完成文件上传,并返回文件访问路径

/// <summary>/// 上传文件测试/// </summary>/// <param name="files"></param>/// <returns></returns>[HttpPost("upload")]publicasync TaskUpload([FromForm(Name ="file")] List files){    var config = configuration.GetSection("UploadConfig").Get();if(files.Count ==0)    {returnApiResult.Fail("没有需要上传的文件");    }    var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.UploadDir);if(!Directory.Exists(dir)) Directory.CreateDirectory(dir);//验证大小或者格式之类foreach (var file in files)    {        var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName;        var fileSize = file.Length;if(fileSize > config.MaxSize)        {returnApiResult.Fail($"{fileName}文件过大");        }    }//存储文件var result =newList();    foreach (var file in files)    {        var fileName = file.FileName;using(var stream = System.IO.File.Create(Path.Combine(dir, fileName)))        {            await file.CopyToAsync(stream);        }        result.Add(string.Join('/',config.WebSite,"upload/view"fileName));    }returnApiResult.Success(result);}

上述文件访问路径需要配置静态目录来进行访问

//启动www静态目录app.UseStaticFiles();//启动上传文件目录app.UseStaticFiles(newStaticFileOptions {    FileProvider =newPhysicalFileProvider(builder.Configuration.GetValue("UploadConfig:UploadDir")),    RequestPath ="/upload/view"});

至此,文件上传及访问已添加完成

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容