将 HttpContext 注入到一个类中,并在 .net core 中调用控制器外的类
Posted
技术标签:
【中文标题】将 HttpContext 注入到一个类中,并在 .net core 中调用控制器外的类【英文标题】:Inject the HttpContext into a class and call the class outside the controller in .net core 【发布时间】:2021-11-25 10:02:15 【问题描述】:我需要为每个用户保存一些信息,例如语言和时区,所以我将它们保存在 cookie 中并通过整个网站访问它们。以前更容易在控制器外部访问 httpContext,但在 .Net Core 中,我看到需要使用注入。
我看了很多文章,过程是:
-
为类创建接口
创建将访问 HttpContext 的实际类
在 Startup.cs 设置注入并注册依赖
从 Controller 的构造函数调用类
在 Microsoft 此处查看详细信息:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-5.0
现在,问题是,这只会将问题提升到更高级别,您只能从控制器实例化您的类,但是如果您需要从另一个地方调用该类,例如在另一个类中,那么您需要像这样调用构造函数
注入类:
public class MyClass : IMyClass
private readonly IHttpContextAccessor _httpContextAccessor;
public MyClass(IHttpContextAccessor httpContextAccessor)
_httpContextAccessor = httpContextAccessor;
...
使用上面注入的新类:
public class MyClass2
public MyClass2()
MyClass myclass = new MyClass(httpContextAccessor)
但此时您没有 httpContextAccessor 对象,因为没有从控制器调用并将 httpContextAccessor 传递给这个新类只是......不可行。
那么,如何正确地做到这一点呢?如何将 HttpContext 注入到一个类中,以及如何在不依赖控制器的情况下调用该类?
【问题讨论】:
【参考方案1】:但此时你没有 httpContextAccessor
我不太明白这里的意思。 IHttpContextAccessor
已注册为单例服务生命周期,这意味着我们可以从应用程序的任何位置获取它。
假设这种情况,MyClass2
需要一个MyClass
的对象,那么,在哪里可以这样做
public class MyClass2
public MyClass2(IHttpContextAccessor httpContextAccessor)
MyClass myclass = new MyClass(httpContextAccessor)
// Some service make use of MyClass2, MyClass2 not register on DI
public class DemonstrateService
private readonly MyClass2 myClass2;
public DemonstrateService(IHttpContextAccessor httpContextAccessor)
myClass2 = new MyClass2(httpContextAccessor);
// Some service make use of MyClass2, MyClass2 got registered on DI
public class DemonstrateService
private readonly MyClass2 _myClass2;
public DemonstrateService(MyClass2 myClass2)
_myClass2 = myClass2;
// Register in DI
services.AddScoped<DemonstrateService>();
services.AddScoped<MyClass2>();
...
// Using it anywhere, it's not restricted to Controller
顺便说一句,我们可以很容易地看到这种嵌套的依赖关系并没有那么好组织。但是我们以自己的方式实现代码。 github 上有很多干净的代码 .Net 核心存储库,我们可以从中学习一些基础知识。
【讨论】:
通过在Model中添加构造函数来注入HttpContext,当你使用LINQ检索数据时它也会触发,所以我想没有解决办法。我找到了一个方法。我会发布我的解决方案。【参考方案2】:似乎通过在 Model 类中添加构造函数来注入 HttpContext 是不可能的,因为 LINQ 在执行查询时也会调用构造函数。我发现我可以在模型之外使用一个 STATIC 类来保留我需要的所有设置,比如“UserTimezone”。因此,我没有尝试从静态类中读取 Cookie,而是设置了一个静态字符串属性来保存该值,并且该值似乎在整个网页请求周期中都保持不变。
基本上,我这样做了,并且为我工作:
-
创建一个 ActionFilter 并在每个控制器上调用它
在 Startup.cs 中设置此过滤器的注入
HttpContext 然后从控制器注入到过滤器中
在过滤器中,我添加了一个函数来读取 Cookie 中的值并将它们保存到静态类(即 MyGlobalStatic.UserTimezone)
然后我在所有需要这些值的模型中使用静态类(即,我需要 UserTimeZone 将 DateTime 字段从数据库通用时间转换为用户的本地时间)。
【讨论】:
如果我是对的……静态类不能被初始化,因此,它的所有属性都只有一个实例(它们都是静态的)。然后,当我们将数据设置为......例如,一个字符串,在调试时,只发送了一个HttpRequest
请求,那么它应该可以工作。但是每秒 100 个请求怎么样?该属性将被覆盖 100 次,这对于每个请求的范围将不再正确。还是我只是错过了什么?以上是关于将 HttpContext 注入到一个类中,并在 .net core 中调用控制器外的类的主要内容,如果未能解决你的问题,请参考以下文章