Abp + Grpc 如何实现用户会话状态传递

0.背景 在实际项目当中,我们采用的是 Abp 框架,但是 Abp 框架官方并没有针对 Grpc 进行模块封装。基于此我结合 Abp 与 MagicOnion 封装了一个 Abp.Grpc 模块,它包括服务端和调用端两部分的包。通过这两个包,你可以很方便地在 Abp 框架当中集成 Grpc 实现服务内部通讯。 但是在实际使用当中会出现一个问题,当 A 服务调用 B 服务的时候,A 服务当前登录用户为 admin,调用 B 服务的 IAbpSession 的值仍然为空,这个时候当 B 服务内部实现使用了 IAbpSession 时会出现问题。 这是因为通过 Grpc 接口调用时,并没有传递诸如 Token 之类的东西,而在 B 服务内部的 IAbpSession 本身附加的数据是从 HttpContext 里面获取的,所以 B 服务当前是没有用户状态的。 1.解决 所幸 IAbpSession 提供了一个 Use 方法,通过这个方法我们可以临时地改变 IAbpSession 内部的值,当 。定义如下: 1 IDisposable Use(int? tenantId, long? userId); 使用方法如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class TestAppService : ITransientDependency { private readonly IAbpSession _abpSession; public TestAppService(IAbpSession abpSession) { _abpSession = abpSession; } public void TestMethod() { using(_abpSession.

ASP .NET CORE 根据环境变量支持多个 appsettings.json

0.背景 在开发项目的过程当中,生产环境与调试环境的配置肯定是不一样的。拿个最简单的例子来说,比如连接字符串这种东西,调试环境肯定是不能连接生产数据库的。在之前的话,这种情况只能说是你 COPY 两个同名的配置文件来进行处理。然后你在本地就使用本地的配置,生产环境就使用生产环境的配置文件,十分麻烦。 而 ASP .NET CORE 支持利用环境变量来动态配置 JSON 文件,下面就来看一下吧。 1.准备工作 首先在你的 ASP .NET CORE 项目当中添加一个 appsettings.json 文件,内容如下: 1 2 3 4 5 { "ConnectionString": { "Default": "Normal Database" } } 之后再继续添加一个 appsettings.Development.json,之后在你的解决方案管理器就会看到下面这种情况。 更改其内容如下: 1 2 3 4 5 { "ConnectionString": { "Default": "Development Database" } } 之后呢,我们继续添加一个生产环境的配置文件,名字叫做 appsettings.Production.json ,更改其内容如下: 1 2 3 4 5 { "ConnectionString": { "Default": "Production Database" } } 最后我们的文件应该如下图: 以上就是我们的准备工作,我们准备了两个环境的配置文件以及一个默认情况的配置文件,下面我就就来看看如何应用环境变量来达到我们想要的效果。 2.环境控制 在项目调试的时候,我们可以通过右键项目属性,跳转到调试可以看到一个环境变量的设定,通过更改 ASPNETCORE_ENVIRONMENT 的值来切换不同环境。

Abp 源码分析:九、事件总线

0.简介 事件总线就是订阅/发布模式的一种实现,本质上事件总线的存在是为了降低耦合而存在的。 从上图可以看到事件由发布者发布到事件总线处理器当中,然后经由事件总线处理器调用订阅者的处理方法,而发布者和订阅者之间并没有耦合关系。 像 Windows 本身的设计也是基于事件驱动,当用户点击了某个按钮,那么就会触发相应的按钮点击事件,而程序只需要监听这个按钮点击事件即可进行相应的处理,而事件被触发的时候往往都会附带相应的事件源,事件所产生的数据等。 还是以按钮被点击为例,该事件被触发的时候会装填上触发时间,被谁触发的数据放在一个 EventArgs 内部,然后将其存放到事件处理器中,然后处理器根据事件的类型去查找订阅了该事件类型的对象,附带上事件数据去调用这些订阅者对象的处理方法。 Abp 本身也实现了事件总线,并且在框架内部也实现了丰富的事件类型,例如实体更新事件、异常事件等等。 注意:在下文当中处理器的含义等同于订阅者,请阅读的时候自行切换。 0.1.使用方法 在引用了 Abp 框架的项目当中使用事件总线相当简单,只需要直接注入 IEventBus 即可触发相应的事件。如果你想要监听某个事件,并且你也想在事件被触发的时候进行处理,那么直接继承自 IEventHandler<TEventData> / IAsyncEventHandler<TEventData> 实现其接口方法 HandleEvent() 即可。 比如说,我们首先定义了一个 TestEventData 的事件,如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /// <summary> /// 测试事件 /// </summary> public class TestEventData : EventData { public TestEventData(string code) { Code = code; } /// <summary> /// 待验证的编码 /// </summary> public string Code { get; } } 很简单,这个事件触发的时候会传递一个 string 类型的 Code 参数。

Abp 源码分析:八、缓存管理

0.简介 缓存在一个业务系统中十分重要,常用的场景就是用来储存调用频率较高的数据。Abp 也提供了一套缓存机制供用户使用,在使用 Abp 框架的时候可以通过注入 ICacheManager 来新建/设置缓存。 同时 Abp 框架也提供了 Redis 版本的 ICacheManager 实现,你也可以很方便的将现有的内存缓存替换为 Redis 缓存。 0.1 典型使用方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class TestAppService : ApplicationService { private readonly ICacheManager _cacheMgr; private readonly IRepository<TestEntity> _rep; // 注入缓存管理器与测试实体的仓储 public TestAppService(ICacheManager cacheMgr, IRepository<TestEntity> rep) { _cacheMgr = cacheMgr; _rep = rep; } public void TestMethod() { // 获取/创建一个新的缓存 var cache = _cacheMgr.

Abp 源码分析:七、工作单元的实现

0.简介 Abp 框架在其内部实现了仓储模式,并且支持 EF Core 与 Dapper 来进行数据库连接与管理,你可以很方便地通过注入通用仓储来操作你的数据,而不需要你自己来为每一个实体定义单独的仓储的实现,通用仓储包含了常用的 CRUD 接口和一些常用方法。 例如: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class TestAppService : ITransientDependency { private readonly IRepository<TestTable> _rep; // 注入通用仓储 public TestAppService(IRepository<TestTable> rep) { _rep = rep; } public void TestMethod() { // 插入一条新数据 _rep.Insert(new TestTable{ Name = "TestName" }); } } 1.通用仓储定义与实现 在 Abp 内部,仓储的基本定义存放在 Abp 项目的 Domain/Repositories 内部,包括以下几个文件: 文件名称 作用描述 AbpRepositoryBase.
Built with Hugo
主题 StackJimmy 设计