一. Cookie、Session、HttpClient
1. 说明
在Asp.Net Core Mvc中,服务的注册通常是在ConfigureService中进行,一个框架会注册很多服务,每个服务都会对应一系列配置,所以我们这里采用【扩展方法】的模式,将需要注册的服务剥离到 YpfCore.Utils层中,从而使ConfigureService中更加简洁。
(1). 扩展方法相关:https://www.cnblogs.com/yaopengfei/p/6921057.html
(2). Cookie和Session相关:https://www.cnblogs.com/yaopengfei/p/11270816.html
(3). HttpClient相关:https://www.cnblogs.com/yaopengfei/p/11300888.html
2. Cookie和Session
Session存储可以基于内存,可以基于Redis、SQLServer,下面重点封装基于内存和Redis的存储,需要安装程序集:【Microsoft.Extensions.Caching.StackExchangeRedis】,在YpfCore.Utils层中CoreMvcExtensions类中进行扩展。
(1). 相应配置
策略封装代码分享
/// <summary> /// Cookie和Session策略 /// (基于redis的Session策略注释,如果开启,需要把CacheStrategyExtensions中的AddMemoryCache注释掉) /// </summary> /// <param name="services"></param> /// <param name="CacheType">Session载体,Memory基于内存存储,StackRedis基于Redis存储,null什么也不注册</param> /// <returns></returns> public static IServiceCollection AddCookieAndSession(this IServiceCollection services, string CacheType) { //1.Cookie策略 services.Configure<CookiePolicyOptions>(options => { options.CheckConsentNeeded = context => false; options.MinimumSameSitePolicy = SameSiteMode.None; }); //2. Session相关配置 //2.1 配置Session相关的载体 switch (CacheType) { case "Memory": { services.AddDistributedMemoryCache(); }; break; case "StackRedis": { //需要把其它封装中的AddMemoryCache 或 AddDistributedMemoryCache都注释掉 services.AddStackExchangeRedisCache(options => { options.Configuration = ConfigHelp.GetString("RedisStr"); //options.InstanceName = "SampleInstance"; //给key加个前缀 }); }; break; case "null": { //什么也不注册 }; break; default: throw new Exception("Session载体无效"); }
配置文件
"RedisStr": "119.xx.xx.xx:6379,password=123456,defaultDatabase=0"
ConfigureService集成
//添加Cookie和Session配置 services.AddCookieAndSession("StackRedis");
Configure中开启
//2. 启用Cookie策略 app.UseCookiePolicy(); //3. 启用Session app.UseSession();
测试代码
{ var user = new T_SysUser() { id = Guid.NewGuid().ToString("N"), userAccount = "1234" }; HttpContext.Session.Set<T_SysUser>("userInfor", user); var data1 = HttpContext.Session.Get<T_SysUser>("userInfor"); }
(2). Session扩展
原Session的方法单调,这里提供两种扩展方法,分别是基于【Newtonsoft.Json】和 【protobuf-net】,详见YpfCore.Utils层中的SessionExtensions类。
代码分享:
/// <summary> /// Session的两种扩展方式 /// 依赖程序集:【Microsoft.AspNetCore.Http】和【Microsoft.AspNetCore.Http.Extensions】 /// 两种序列化模式:【Newtonsoft.Json】和 【protobuf-net】 /// 其中 【protobuf-net】序列化的类名上要加 [ProtoContract],属性上要加 [ProtoMember(1)] [ProtoMember(2)] /// </summary> public static class SessionExtensions { #region 01-利用Newtonsoft.Json进行扩展 public static void Set<T>(this ISession session, string key, T value) { session.SetString(key, JsonConvert.SerializeObject(value)); } public static T Get<T>(this ISession session, string key) { var value = session.GetString(key); return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value); } #endregion #region 02-利用protobuf-net进行扩展 public static void Set2<T>(this ISession session, string key, T value) { using (MemoryStream stream = new MemoryStream()) { Serializer.Serialize(stream, value); byte[] byteArrary = stream.ToArray(); session.Set(key, byteArrary); } } public static T Get2<T>(this ISession session, string key) { byte[] byteArray = session.Get(key); if (byteArray == null) { return default(T); } else { using (MemoryStream stream = new MemoryStream(byteArray)) { return Serializer.Deserialize<T>(stream); } } } #endregion }
调用测试:
{ var user = new T_SysUser() { id = Guid.NewGuid().ToString("N"), userAccount = "1234" }; HttpContext.Session.Set<T_SysUser>("userInfor", user); var data1 = HttpContext.Session.Get<T_SysUser>("userInfor"); }
3. HttpClient
(1) .方式一
常规写法,在ConfigureService注入AddHttpClient对象,这里同样是以扩展方法的形式剥离的YpfCore.Utils层中,然后在控制器中注入IHttpClientFactory 对象即可。
代码分享
ConfigureService中注入:services.AddMyHttpClient();
封装代码:
public static class CoreMvcExtensions { /// <summary> /// 注册HttpClient服务 /// </summary> /// <param name="services"></param> /// <returns></returns> public static IServiceCollection AddMyHttpClient(this IServiceCollection services) { //1.基本用法 services.AddHttpClient(); //2. 命名客户端(用于指定表头和请求根目录---目前用不到) services.AddHttpClient("client1", c => { c.BaseAddress = new Uri("http://localhost:15319/"); c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); c.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample"); }); return services; } }
(2). 方式二
彻底封装,在YpfCore.Utils层中的RequestHelp类中模拟注入的方式封装Get和Post方法,Core Mvc中直接调用即可,不需要ConfigureService中注册任何东西。
封装代码:
// <summary> /// 基于HttpClientFactory的请求封装 /// 依赖【Microsoft.Extensions.DependencyInjection】和 【Microsoft.Extensions.Http】 /// 可以直接调用,在CoreMvc中不再需要注入AddHttpClient了,因为下面封装里已Add进去了 /// </summary> public class RequestHelp { /// <summary> /// Get请求 /// </summary> /// <param name="url">请求地址</param> /// <returns></returns> public static string MyGetRequest(string url) { var serviceProvider = new ServiceCollection().AddHttpClient().BuildServiceProvider(); IHttpClientFactory clientFactory = serviceProvider.GetService<IHttpClientFactory>(); var request = new HttpRequestMessage(HttpMethod.Get, url); var client = clientFactory.CreateClient(); var response = client.SendAsync(request).Result; var myResult = response.Content.ReadAsStringAsync().Result; return myResult; } /// <summary> /// Post请求-表单形式 /// </summary> /// <param name="url">请求地址</param> /// <param name="content">请求内容</param> /// <returns></returns> public static string MyPostRequest(string url, string content) { var serviceProvider = new ServiceCollection().AddHttpClient().BuildServiceProvider(); IHttpClientFactory clientFactory = serviceProvider.GetService<IHttpClientFactory>(); var request = new HttpRequestMessage(HttpMethod.Post, url); //内容的处理 request.Content = new StringContent(content, Encoding.UTF8, "application/x-www-form-urlencoded"); var client = clientFactory.CreateClient(); var response = client.SendAsync(request).Result; var myResult = response.Content.ReadAsStringAsync().Result; return myResult; } /// <summary> /// Post请求-Json形式 /// </summary> /// <param name="url">请求地址</param> /// <param name="content">请求内容</param> /// <returns></returns> public static string MyPostRequestJson(string url, object content) { var serviceProvider = new ServiceCollection().AddHttpClient().BuildServiceProvider(); IHttpClientFactory clientFactory = serviceProvider.GetService<IHttpClientFactory>(); var request = new HttpRequestMessage(HttpMethod.Post, url); //内容的处理 request.Content = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json"); var client = clientFactory.CreateClient(); var response = client.SendAsync(request).Result; var myResult = response.Content.ReadAsStringAsync().Result; return myResult; } }
调用测试:
{ string url1 = "http://localhost:29793/api/DemoApi/GetMsg1?userAccount=admin&userId=123456"; string url2 = "http://localhost:29793/api/DemoApi/GetMsg2"; string url3 = "http://localhost:29793/api/DemoApi/GetMsg3"; //Get请求 var result1 = RequestHelp.MyGetRequest(url1); //Post-表单提交 var result2 = RequestHelp.MyPostRequest(url2, "userAccount=admin&userId=123456"); //Post-Json提交 var user = new { userId = "admin", userAccount = "123456" }; var result3 = RequestHelp.MyPostRequestJson(url3, user); }
二. 静态资源、路由、跨域
参考
(1). 静态资源参考:https://www.cnblogs.com/yaopengfei/p/10823322.html
(2). 路由参考:https://www.cnblogs.com/yaopengfei/p/11849496.html
(3). 跨域参考:https://www.cnblogs.com/yaopengfei/p/11191938.html
1. 静态资源
Asp.Net Core MVC中默认开启静态文件中间件(在Configure方法中 app.UseStaticFiles()),即wwwroot目录(即根目录)下的文件均可以访问,通常我们可能需要单独在根目录下新建文件,比如DownLoad,那么就需要自行配置。
代码分享:
//1. 启用静态资源 app.UseStaticFiles(); //开启DownLoad文件夹,便于下载相关的请求的进行访问(发布的时候,发布目录中必须要有下面的文件夹!!!) app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "DownLoad")), //配置相对路径(建议和前面的名起个一样的,当然也可以起别的,注意前面要有/) RequestPath = "/DownLoad" });
2. 路由
这里我们配置两个路由规则,普通路由和Area区域路由, 区域中的action必须配置: [Area("区域名")], 对于WebApi,可以单独配置:[Route("api/xxx_areas/[controller]/[action]")]和[ApiController] ,同样可以替换Restful默认风格。
代码分享:
app.UseEndpoints(endpoints => { //默认路由 endpoints.MapControllerRoute( name: "default", pattern: "{controller=Admin}/{action=LoginIndex}/{id?}"); //pattern: "{controller=Demo}/{action=Test1}/{id?}"); //区域路由(要放在默认路由的后面) //注:必须以特性的形式在对应控制器上加上区域名称 [Area("XXXX")] endpoints.MapControllerRoute( name: "default2", pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"); });
3. 跨域
这里直接在Configure中全局配置允许跨域请求,至于单独作用,见之前的参考文档。
app.UseCors(options =>
{
options.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。