Coder Social home page Coder Social logo

senparc / senparc.co2net Goto Github PK

View Code? Open in Web Editor NEW
356.0 26.0 125.0 3.63 MB

支持 .NET Framework & .NET Core 的公共基础扩展库

License: Apache License 2.0

C# 99.95% HTML 0.05%
base-library dotnet dotnet-core senparc co2net cache utility helper configuration settings

senparc.co2net's Introduction

Senparc.CO2NET

Build status NuGet license

模块功能 Nuget 名称 Nuget 支持 .NET 版本
CO2NET 基础库 Senparc.CO2NET Senparc.CO2NET Senparc.CO2NET .NET 3.5 .NET 4.0 .NET 4.5 .NET Core 2.0
APM 模块 Senparc.CO2NET.APM Senparc.CO2NET.APM Senparc.CO2NET.APM .NET 3.5 .NET 4.0 .NET 4.5 .NET Core 2.0
Redis 基础库 Senparc.CO2NET.Cache.Redis Senparc.CO2NET.Cache.Redis Senparc.CO2NET.Cache.Redis .NET 3.5 .NET 4.0 .NET 4.5 .NET Core 2.0
Memcached 基础库 Senparc.CO2NET.Cache.Memcached Senparc.CO2NET.Cache.Memcached Senparc.CO2NET.Cache.Memcached .NET 3.5 .NET 4.0 .NET 4.5 .NET Core 2.0
WebApi(新) Senparc.CO2NET.WebApi Senparc.CO2NET.WebApi Senparc.CO2NET.Cache.Memcached .NET 3.5 .NET 4.0 .NET 4.5 .NET Core 2.0

.NET Core 2.0 同时支持 .NET Standard 2.0+ 及 .NET Core 2.1/3.1、.NET 5.0/6.0/7.0+

CO2NET 将逐步停止对 .NET Framework 4.0 及以下版本的支持。

Senparc.CO2NET 是一个支持 .NET Framework 和 .NET Core 的公共基础扩展库,包含常规开发所需要的基础帮助类。

开发者可以直接使用 CO2NET 为项目提供公共基础方法,免去重复准备和维护公共代码的痛苦。

Senparc.CO2NET 已经作为 Senparc.Weixin SDKNCF 等 Senparc 系列产品的的基础库被依赖。

如何使用 Nuget 安装?

PM> Install-Package Senparc.CO2NET

阶段

目前发布的已经是稳定版,持续更新中,您可关注本项目进展!

程序集在线文档:http://doc.weixin.senparc.com/html/G_Senparc_CO2NET.htm

本项目后期将会配备更加完整的文档,如果大家迫不及待想要尝试,可以打开解决方案文件,参考单元测试项目(Senparc.CO2NET.Tests),每一个方法都能找到对应的用法,本项目完整指之一就是将单元测试代码覆盖率做到接近100%。

视频预告介绍

抢先预览(2018年6月15日)

使用 CO2NET 初始化微信项目及普通项目(2018年6月22日)

senparc.co2net's People

Contributors

554393109 avatar ccccccmd avatar chunacy avatar dependabot[bot] avatar hellodba avatar jeffreysu avatar lxings avatar oyq413 avatar qideqian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

senparc.co2net's Issues

dotnet core 2.2 调用Senparc.CO2NET的方法报错

dotnet core 2.2 调用Senparc.CO2NET的方法报错,请问是什么原因?
System.ArgumentNullException: Value cannot be null.
Parameter name: services
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
at Senparc.CO2NET.SenparcDI.GetIServiceProvider(Boolean useGlobalScope)
at Senparc.CO2NET.HttpUtility.RequestUtility.HttpGet(String url, Encoding encoding)
at Senparc.Weixin.MP.CommonAPIs.CommonApi.GetToken(String appid, String secret, String grant_type)

RequestUtility.HttpGet的serviceProvider 参数为必填,.NetFramework4.5 环境下无法调用

以下方法,serviceProvider 是必填参数,在.NetFramework 4.5 环境中,无法调用 ?

/// <summary> /// 使用Get方法获取字符串结果(没有加入Cookie) /// </summary> /// <param name="serviceProvider">.NetCore 下的服务器提供程序,如果 .NET Framework 则保留 null</param> /// <param name="url"></param> /// <param name="encoding"></param> /// <returns></returns> public static string HttpGet( IServiceProvider serviceProvider, string url, Encoding encoding = null)

关于Senparc.CO2NET.RegisterServices.RegisterServices注册的问题

是不是应该可以在Startup.ConfigureService中配置:
services.AddSingleton<IRegisterService, RegisterService>();

然后在Configure中注入来的好看一些:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IRegisterService registerService)

这样更符合.net core的风格一点

.Net Core项目调用上传临时素材接口时,若文件名称为中文,上传后的临时素材文件名被编码。

问题:.Net Core项目调用上传临时素材接口(MediaApi.Upload())时,若文件名称为中文,上传后的临时素材文件名被编码。
文件:Senparc.CO2NET/Utilities/HttpUtility/RequestUtility.Common.cs
行数:246
问题代码:fileName = fileName.UrlEncode();

HttpUtility.HttpPost_Common_NetCore 方法中调用了CreateFileContent方法,该方法对获取到的文件名进行了UrlEncode。导致上传后的临时素材文件名被编码,使用该素材media_id发送文件时,文件名称无法正常显示中文,显示为被编码后的文本。

对应的HttpPost_Common_Net45方法则未进行编码,上传后的临时素材名称正常显示。

Framework跟.net core兼容性问题

AddSenparcGlobalServices 不支持Framework,BuildFromWebConfig 又不支持.net core,,如果同时使用了两个(我的项目因为一些原因不得不同时依赖framework跟.netcore),注册逻辑就要写两套,太麻烦了!还不如旧的sdk兼容性好!

BaseContainer.GetAllItem()报错

调用BaseContainer的GetAllItem方法,发现报错“json转换失败”。后来查看源码发现,是这个方法有问题:

namespace Senparc.CO2NET.Cache.CsRedis
{
    /// <summary>
    /// Redis的Object类型容器缓存(Key为String类型),Key-Value 类型储存
    /// </summary>
    public class RedisObjectCacheStrategy : BaseRedisObjectCacheStrategy
    {
        /// <summary>
        /// 根据 key 的前缀获取对象列表(最多 99999 条)
        /// </summary>
        public IList<T> GetAllByPrefix<T>(string key)
        {
            var keyPattern = GetFinalKey("*");//获取带Senparc:DefaultCache:前缀的Key([DefaultCache]   
            var keys = base.Client.Keys(/*database: Client.GetDatabase().Database,*/ pattern: keyPattern/*, pageSize: 99999*/);
            List<T> list = new List<T>();
            foreach (var fullKey in keys)
            {
                var obj = Get<T>(fullKey, true);
                if (obj != null)
                {
                    list.Add(obj);
                }
            }

            return list;
        }
    }
}

应该是直接使用传进来的key,而不是调用GetFinalKey。GetFinalKey返回的是设置的redis命名空间,会返回所有key,因此反序列化时出现问题。应该直接使用key。其他的redis缓存策略也有这个问题

net 8出错。

我已经写了为什么还出错。builder.Services.AddMemoryCache();

依赖注入未设置!如果您使用的是本地缓存,请确保在 Startup.cs 中执行了 services.AddMemoryCache() 方法!

项目升级到.net core 2.2后初始化错误

Application startup exception: System.TypeInitializationException: The type initializer for 'Nested' threw an exception. ---> System.TypeInitializationException: The type initializer for 'Nested' threw an exception. ---> System.ArgumentNullException: Value cannot be null.
Parameter name: services
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
at Senparc.CO2NET.SenparcDI.GetIServiceProvider()
at Senparc.CO2NET.Cache.LocalObjectCacheHelper.get_LocalObjectCache()
at Senparc.CO2NET.Cache.LocalObjectCacheStrategy..ctor()
at Senparc.CO2NET.Cache.LocalObjectCacheStrategy.Nested..cctor()
--- End of inner exception stack trace ---
at Senparc.Weixin.Cache.LocalContainerCacheStrategy.<>c.<.ctor>b__2_0()
at Senparc.CO2NET.Cache.CacheStrategyDomainWarehouse.RegisterCacheStrategyDomain(IDomainExtensionCacheStrategy domainCacheStrategy)
at Senparc.Weixin.Cache.LocalContainerCacheStrategy.Nested..cctor()
--- End of inner exception stack trace ---
at Senparc.Weixin.WeixinRegister.UseSenparcWeixin(IRegisterService registerService, SenparcWeixinSetting senparcWeixinSetting, SenparcSetting senparcSetting)
at Tensee.Banch.BanchApplicationModule.Initialize() in D:\workspace\C#\DuoMai_TooHot\src\Tensee.Banch.Application\BanchApplicationModule.cs:line 50
at System.Collections.Generic.List1.ForEach(Action1 action)
at Abp.Modules.AbpModuleManager.StartModules() in D:\Github\aspnetboilerplate\src\Abp\Modules\AbpModuleManager.cs:line 48
at Abp.AbpBootstrapper.Initialize() in D:\Github\aspnetboilerplate\src\Abp\AbpBootstrapper.cs:line 155
at Abp.AspNetCore.AbpApplicationBuilderExtensions.InitializeAbp(IApplicationBuilder app) in D:\Github\aspnetboilerplate\src\Abp.AspNetCore\AspNetCore\AbpApplicationBuilderExtensions.cs:line 67
at Abp.AspNetCore.AbpApplicationBuilderExtensions.UseAbp(IApplicationBuilder app, Action`1 optionsAction) in D:\Github\aspnetboilerplate\src\Abp.AspNetCore\AspNetCore\AbpApplicationBuilderExtensions.cs:line 38
at Tensee.Banch.Web.Startup.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) in D:\workspace\C#\DuoMai_TooHot\src\Tensee.Banch.Web.Host\Startup\Startup.cs:line 154
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()

APM程序监控模块,造成CPU占满

问题描述

  • 访问量较小的情况下,突然出现CPU占满的状况

  • 使用WinDb命令,'!runaway' 发现cpu占用最多的为如下线程
    image
    ~* e!clrstack,最后显示多个线程被柱塞senparc.CO2NET.APM.DataOperation+d__8.MoveNext()这个地方,调用堆栈如下
    image

  • 使用版本如下:

<package id="Senparc.CO2NET" version="0.8.2" targetFramework="net45" /> 
 <package id="Senparc.CO2NET.APM" version="0.4.1.1" targetFramework="net45" /> 
 <package id="Senparc.NeuChar" version="0.7.4" targetFramework="net45" /> 
 <package id="Senparc.NeuChar.App" version="0.5.4" targetFramework="net45" /> 
 <package id="Senparc.Weixin" version="6.4.8" targetFramework="net45" /> 
 <package id="Senparc.Weixin.MP" version="16.7.9" targetFramework="net45" /> 
 <package id="Senparc.Weixin.MP.MVC" version="5.0.0" targetFramework="net45" />
  • 全局配置如下
       var isGLobalDebug = false;//设置全局 Debug 状态 
           var isWeixinDebug = false;//设置微信 Debug 状态 
           var senparcSetting = SenparcSetting.BuildFromWebConfig(isGLobalDebug); 
           var register = RegisterService.Start(senparcSetting).UseSenparcGlobal();//CO2NET全局注册,必须! 
           var senparcWeixinSetting = SenparcWeixinSetting.BuildFromWebConfig(isWeixinDebug); 
           register.UseSenparcWeixin(senparcWeixinSetting, senparcSetting);////微信全局注册,必须! 
           AccessTokenContainer.RegisterAsync(ConfigSetting.AppId, ConfigSetting.Appsecret).GetAwaiter().GetResult(); 

代码定位

  • 类:Senparc.CO2NET.APM.DataOperation类
  • 方法: SetAsync
  • 使用的是本地缓存策略
using (await cacheStragety.BeginCacheLockAsync("SenparcAPM", finalKey).ConfigureAwait(false))
                    {
                        var list = await GetDataItemListAsync(kindName).ConfigureAwait(false);
                        list.Add(dataItem);
                        await cacheStragety.SetAsync(finalKey, list, Config.DataExpire, true).ConfigureAwait(false);

                        await RegisterFinalKeyAsync(kindName).ConfigureAwait(false);//注册Key

                        if (SenparcTrace.RecordAPMLog)
                        {
                            SenparcTrace.SendCustomLog($"APM 性能记录 - DataOperation.Set - {_domain}:{kindName}", SystemTime.DiffTotalMS(dt1) + " ms");
                        }

                        return;// dataItem;
                    }

解决期望

  • APM默认关闭不使用
  • 程序中存在死锁问题,请进行详细检查

可能的解决方案

  • 修改Senparc.CO2NET.APM.DataOperation 中, 使用线程安全的字典集合作为默认本地的缓存
 KindNameStore = new ConcurrentDictionary<string, ConcurrentDictionary<string, DateTimeOffset>>();

关于微信请求消息MessageHandler和OnExecuted消息顺序问题

问题说明:我在OnEvent_ScanRequest事件里面返回了一个多文本消息(7张图片,标题,链接),然后在OnExecuted方法里发送一条模板消息,结果总是先收到模板消息后才收到多文本消息。
经过代码调试发现,代码是先执行OnEvent_ScanRequest事件后再执行OnExecuted方法的,我希望是先收到多文本消息后再收到模板消息的。。。

建议用DateTimeOffset替换DateTime

DateTimeOffset包含时区信息 DateTimeOffset.UtcNow和DateTimeOffset.Now是一样的,使用DateTime类型传递,序列化反序列化很容易搞错时区出bug

序列化数据时会有字段丢失

创建一张会员卡,supply_bonus和supply_balance设置为false,序列化后这两个值丢失,微信报错没有提供这两个字段

关于接口不使用ApiController 使用普通Controller

asp.net core已经把 ApiController 和普通Controller统一起来了,webapi 接收微信数据也没有问题。
第一种:微信wx.request header: {'content-type': 'application/json'},webapi使用 [frombody]定义一个接受类用来接收参数,直接用参数接收不到。
第二种: header: {"content-type": "application/x-www-form-urlencoded"}
提示参数 :Form Data 中code:033BVv6Y1iBPpT0EYl7Y1hHG6Y1BVv6r
1、 public ActionResult OnLogin([FromForm]CodeViewModel model)
使用[fromform]可以接收到,但是也必须使用类接收参数
2、 public ActionResult OnFormLogin(string code) 可以直接用简单类型接收参数。

The SSL connection could not be established, see inner exception

core 3.1 HttpClient默认是启用服务端证书校验的,而CO2NET默认没有关闭或者默认直接通过服务端证书校验,导致请求微信相关API时候出错:The SSL connection could not be established, see inner exception。目前我的临时解决方案如下:
services.AddHttpClient("elite-wechat")
.ConfigurePrimaryHttpMessageHandler(() =>
{
var httpClientHandler = HttpClientHelper.GetHttpClientHandler(null, RequestUtility.SenparcHttpClientWebProxy, System.Net.DecompressionMethods.GZip);
//httpClientHandler.ClientCertificates.Add(cert);
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errir) => true;

                     return httpClientHandler;
                 });

nuget更新到最新版后,执行 app.UseSenparcGlobal 时的错误

把 nuget更新到最新版后,执行 app.UseSenparcGlobal 时,出现报错 所在位置是 Senparc.CO2NET.Helpers.ReflectionHelper.GetStaticMember , 错误为 System.NullReferenceException:“Object reference not set to an instance of an object.”

经过各种测试排查,发现使用 redis 时,如果只引用 Senparc.CO2NET.Cache.Redis 或 只引用 Senparc.CO2NET.Cache.CsRedis (相关配置均是对应的正确写法)就会出错,但是如果将两者都引用,但是只执行某一个配置,则不会出错

怀疑是在 app.UseSenparcGlobal 中尝试去找这2个

调用SnsApi.JsCode2Json(_wxOpenAppId, _wxOpenAppSecret, code)出现下面错误是什么原因

at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
at Senparc.CO2NET.SenparcDI.GetIServiceProvider(Boolean useGlobalScope)
at Senparc.CO2NET.HttpUtility.RequestUtility.HttpGet(String url, Encoding encoding)
at Senparc.CO2NET.HttpUtility.Get.GetJson[T](String url, Encoding encoding, Action`2 afterReturnText)
at Senparc.Weixin.CommonAPIs.CommonJsonSend.Send[T](String accessToken, String urlFormat, Object data, CommonJsonSendType sendType, Int32 timeOut, Boolean checkValidationResult, JsonSetting jsonSetting)
at Senparc.Weixin.WxOpen.AdvancedAPIs.Sns.SnsApi.JsCode2Json(String appId, String secret, String jsCode, String grantType, Int32 timeOut)

RequestUtility.HttpPost突然获取不到参数

Dictionary<string, string> formData = new Dictionary<string, string>();
formData.Add("test", DateTime.Now.Ticks.ToString());
formData.Add("formdata", formDataJson);

string strJson = RequestUtility.HttpPost(url, null, formData, UTF8Encoding.UTF8);

传入test 和 formdata,但是在url这个页面去request.form["test"]取不到test参数
2.16版本

Senparc.CO2NET.Cache.CsRedis bug

就不翻译英文了.

Senparc.CO2NET/src/Senparc.CO2NET.Cache.CsRedis/ObjectCacheStrategy/BaseRedisObjectCacheStrategy.cs
行38
Client = new CSRedis.CSRedisClient(Config.SenparcSetting.Cache_Redis_Configuration);
应该用
Client = new CSRedis.CSRedisClient(RedisManager.ConfigurationOption);

否则 Senparc.CO2NET.Cache.CsRedis.Register.SetConfigurationOption(redisConnection);
连接配置无法生效
都是调用空配置

HttpClientHalder 动态证书怎么处理

   HttpClientHandler handler = HttpClientHelper.GetHttpClientHandler(cookieContainer, SenparcHttpClientWebProxy, DecompressionMethods.GZip);

            if (checkValidationResult)
            {
                handler.ServerCertificateCustomValidationCallback = new Func<HttpRequestMessage, X509Certificate2, X509Chain, SslPolicyErrors, bool>(CheckValidationResult);
            }

            if (cer != null)
            {
                handler.ClientCertificates.Add(cer);
            }
  var senparcHttpClient = SenparcDI.GetRequiredService<SenparcHttpClient>();
 senparcHttpClient.SetCookie(new Uri(url), cookieContainer);//设置Cookie

HttpClientHalder 动态证书怎么处理,这里的handler对象没看到使用

RequestUtility.HttpClientHeader()方法里面通过DefaultRequestHeaders设定Timeout是不会触发超时的

  • HttpClient之前我们测试过只能在首次发出请求前通过Client的Timeout属性设定,第二次修改值就会抛出异常

  • 在我们系统里面是按照【业务功能+Timeout时间】来创建Client实例,并在构造函数指定Timeout

  • 我的愚见是添加SenparcHttpClient.GetInstanceByName(httpClientName, timeOut)构造函数,通过IHttpClientFactory创建Client实例并初始化Timeout;后续的Http请求Timeout参数移除

我发现了一个严重的bug,排查了3天,终于确定是Senparc导致的。

我有个项目,使用了下面的代码,软件登录偶尔就会卡很久,最长可能要10几秒,排查了数据库,云数据库,腾讯云监控都没问题,问了客服也没问题,我sql 执行也不慢。ORM库,我测试也没问题。

但是我输出了查询慢的秒数,发现只要很慢的那种,都会报一个错误。错误的行是await next();这句,这个为什么会让我的软件偶尔响应很慢?连续3天我软件偶尔使用很慢,我今天去掉了这个,软件一上午没事了。

代码如下。

app.Use(async (context, next) =>
{
    var senparcSetting = context.RequestServices.GetRequiredService<IOptions<SenparcSetting>>();
    var senparcWeixinSetting = context.RequestServices.GetRequiredService<IOptions<SenparcWeixinSetting>>();
    var env = context.RequestServices.GetRequiredService<IWebHostEnvironment >();

// 启动 CO2NET 全局注册,必须!

    var registerService = app.UseSenparcGlobal(env, senparcSetting.Value, globalRegister =>
        {
        }, true)
        //使用 Senparc.Weixin SDK
        .UseSenparcWeixin(senparcWeixinSetting.Value, (weixinRegister, setting) =>
        {
            weixinRegister
                //注册多个公众号或小程序(可注册多个) 
                .RegisterWxOpenAccount(senparcWeixinSetting.Value, "adl助手");
            weixinRegister.RegisterMpAccount(senparcWeixinSetting.Value.Items["通知公众号"]);
        });
    // 使用配置...

    await next();
});

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.