AsyncLocal< T>无法到达控制器 [英] AsyncLocal<T> doesn't reach controllers

查看:78
本文介绍了AsyncLocal< T>无法到达控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不太了解这种情况,其中AsyncLocal instance

I don't quite fully understand this situation, where AsyncLocal instance is set at a certain point in the AuthenticationHandler, but does not reach the controller, when it is injected into the constructor.

我使它类似于 IHttpContextAccessor 可以运行,但是仍然遥不可及.但是,如果我从中间件,它到达控制器.此外,还可以从 AuthenticationHandler 可以正常工作.

I've made it similar to how IHttpContextAccessor works, but still nowhere near. However, if I set the AsyncLocal from a Middleware, it reaches the controller. Also, setting the HttpContext.Items property from AuthenticationHandler works just fine.

问题:HttpContext如何能够一直保留Items属性的内容,并且由于某种安全原因,ASP.NET运行时是否出于某种安全原因而将我DomainContextAccessor的捕获的ExecutionContext丢弃?

Question: How is HttpContext able to retain Items property contents all the way, and is ASP.NET runtime disposing the captured ExecutionContext of my DomainContextAccessor for some security reason because of where it is being set at?

我已经制作了一个示例应用来演示该用例.我真的很感谢有人为这个问题提供帮助.

I've made a sample app to demo this use case. I'd really appreciate someone shedding the light on this problem.

推荐答案

您已经对我应该如何解决?"有个很好的答案.这里更多地说明了为什么这种方式.

You already have a good answer on "how should I fix this?" Here's more of a description of why it's behaving this way.

AsyncLocal< T> 具有与

AsyncLocal<T> has the same semantics as logging scopes. Because it has those same semantics, I always prefer to use it with an IDisposable, so that the scope is clear and explicit, and there's no weird rules around whether a method is marked async or not.

有关怪异规则的详细信息,请参见.总结:

For specifics on the weird rules, see this. In summary:

  • 将新值写入 AsyncLocal< T> 会在当前范围内设置该值 .
  • 标记为 async 的方法将在第一次写入时将它们的作用域复制到一个新的作用域(这是被修改的新作用域).
  • Writing a new value to an AsyncLocal<T> sets that value in the current scope.
  • Methods marked async will copy their scope to a new scope the first time it's written to (and it's the new scope that is modified).

我已经使它类似于IHttpContextAccessor的工作原理,但仍然遥不可及.

I've made it similar to how IHttpContextAccessor works, but still nowhere near.

我不建议复制 IHttpContextAccessor 的设计.它适用于非常具体的用例.如果要使用 AsyncLocal< T> ,请使用如下设计:

I don't recommend copying the design of IHttpContextAccessor. It works... for that very specific use case. If you want to use AsyncLocal<T>, then use a design like this:

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);
  }
}

用法:

using (MyImplicitValue.Set(myValue))
{
  // Code in here can get myValue from MyImplicitValue.Get().
}

如果需要,可以将其包装到 IMyImplicitValueAccessor 中,但请注意,逻辑应该使用如图所示的 IDisposable 模式.

You can wrap that into an IMyImplicitValueAccessor if desired, but note that any "setter" logic should be using the IDisposable pattern as shown.

AsyncLocal实例在AuthenticationHandler中的某个位置设置,但未到达控制器

AsyncLocal instance is set at a certain point in the AuthenticationHandler, but does not reach the controller

这是因为您的AuthenticationHandler设置了该值,但在设置该值后不会调用控制器(并且不应).

That's because your AuthenticationHandler sets the value but doesn't call the controller after setting that value (and it shouldn't).

但是,如果我从中间件设置了AsyncLocal,它将到达控制器.

However, if I set the AsyncLocal from a Middleware, it reaches the controller.

那是因为中间件被称为下一个中间件(最终到达控制器).也就是说,中间件的结构如下:

That's because middleware is calls the next middleware (eventually getting to the controller). I.e., middleware is structured like this:

public async Task InvokeAsync(HttpContext context)
{
  using (implicitValue.Set(myValue))
  {
    await _next(context);
  }
}

因此,当设置 AsyncLocal< T> 值时,控制器将处于范围之内.

So the controllers are in the scope of when that AsyncLocal<T> value was set.

HttpContext如何始终保留Items属性的内容

How is HttpContext able to retain Items property contents all the way

Items 只是一个属性包.它与 AsyncLocal< T> 没有任何关系.之所以存在,是因为它是 HttpContext 上的一个属性,并且由于在整个请求中使用了相同的 HttpContext 实例而得以保留.

Items is just a property bag. It doesn't have anything to do with AsyncLocal<T>. It exists because it's a property on HttpContext, and it persists because the same HttpContext instance is used throughout the request.

出于某些安全原因,ASP.NET运行时是否将我的DomainContextAccessor捕获的ExecutionContext设置为某个位置?

is ASP.NET runtime disposing the captured ExecutionContext of my DomainContextAccessor for some security reason because of where it is being set at?

不完全是. AsyncLocal< T> 设置得很好;只是在设置 AsyncLocal< T> 的范围内未调用控制器.

Not exactly. The AsyncLocal<T> is being set just fine; it's just that the controllers are not called within the scope of that AsyncLocal<T> being set.

这篇关于AsyncLocal&lt; T&gt;无法到达控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆