• 第二节:必备中间件集成1(Cookie、Session、HttpClient、静态资源、路由配置、跨域等)


    一. 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载体无效");
                }
    View Code

    配置文件

    "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
        }
    View Code

    调用测试:

                {
                    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;
            }
    
        }
    View Code

    (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;
            }
    
        }
    View Code

    调用测试:

                {
                    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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    再谈iframe自适应高度
    一个软件外包老鸟对外包业的反思
    需求分析中减少客户摩擦的若干法则
    C# 进制转换
    'filter' is not a known css property name
    Ajax之ModalPopupExtender 的后台调用
    Microsoft SQL Server 中的小数数据类型
    ExtJS Combobox 如何设置默认和取值问题
    wp7 控制控件显隐
    wp7 MediaElement播放
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/14236551.html
Copyright © 2020-2023  润新知