Ost*_*ati 3 asp.net-web-api asp.net-core
我不太完全理解这种情况,其中 AsyncLocal实例是在AuthenticationHandler中的某个点设置的,但当它被注入到constructor中时却没有到达控制器。
我已经使它类似于IHttpContextAccessor 的工作方式,但仍然相距甚远。但是,如果我从Middleware设置 AsyncLocal ,它就会到达控制器。另外,从AuthenticationHandler设置 HttpContext.Items 属性也可以正常工作。
问题: HttpContext 如何能够一直保留 Items 属性内容,并且 ASP.NET 运行时是否出于某种安全原因处理我的 DomainContextAccessor 捕获的 ExecutionContext(因为它的设置位置)?
我制作了一个示例应用程序来演示此用例。我真的很感激有人能阐明这个问题。
对于“我应该如何解决这个问题?”您已经有了一个很好的答案。这里有更多关于它为什么会这样的描述。
AsyncLocal<T>与日志记录范围具有相同的语义。因为它具有相同的语义,所以我总是更喜欢将它与 an 一起使用IDisposable,以便范围清晰明确,并且对于是否标记方法没有奇怪的规则async。
有关奇怪规则的具体信息,请参阅此。总之:
AsyncLocal<T>设置该值。async将在第一次写入时将其作用域复制到新作用域(并且修改的是新作用域)。我已经使它类似于 IHttpContextAccessor 的工作方式,但仍然相距甚远。
我不建议复制 的设计IHttpContextAccessor。它适用于特定的用例。如果你想使用AsyncLocal<T>,那么使用这样的设计:
static class MyImplicitValue
{
private static readonly AsyncLocal<T> Value = new();
public static T Get() => Value.Value;
public static IDisposable Set(T newValue)
{
var oldValue = Value.Value;
Value.Value = newValue;
return new Disposable(() => Value.Value = oldValue);
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
using (MyImplicitValue.Set(myValue))
{
// Code in here can get myValue from MyImplicitValue.Get().
}
Run Code Online (Sandbox Code Playgroud)
如果需要,您可以将其包装到 a 中IMyImplicitValueAccessor,但请注意,任何“setter”逻辑都应使用IDisposable所示的模式。
AsyncLocal 实例在 AuthenticationHandler 中的某个点设置,但未到达控制器
这是因为您的 AuthenticationHandler 设置了该值,但在设置该值后不会调用控制器(也不应该)。
但是,如果我从中间件设置 AsyncLocal,它就会到达控制器。
这是因为中间件会调用下一个中间件(最终到达控制器)。即,中间件的结构如下:
public async Task InvokeAsync(HttpContext context)
{
using (implicitValue.Set(myValue))
{
await _next(context);
}
}
Run Code Online (Sandbox Code Playgroud)
因此控制器处于AsyncLocal<T>设置该值时的范围内。
HttpContext如何能够一直保留Items属性内容
Items只是一个财产袋。和它没有任何关系AsyncLocal<T>。它存在是因为它是 上的一个属性,并且它持续存在是因为在整个请求过程中使用了HttpContext同一个实例。HttpContext
ASP.NET 运行时是否出于某种安全原因处理我的 DomainContextAccessor 捕获的 ExecutionContext(因为它的设置位置)?
不完全是。正在AsyncLocal<T>设置得很好;只是控制器不会在所AsyncLocal<T>设置的范围内被调用。
| 归档时间: |
|
| 查看次数: |
822 次 |
| 最近记录: |