如何使用中间件来替代控制器初始化?

5
我正在将我的ASP.Net应用迁移到ASP.Net Core,其中一个功能是所有控制器都继承自一个基本控制器,在该控制器中我执行以下操作:
protected override void Initialize(HttpControllerContext controllerContext)
{
    base.Initialize(controllerContext);

    string token = controllerContext.Request.Properties["token"] as string;
    user = UserCache.Get(token);

    //Called by derived controllers
    //to set their repository user
    SetInfo();
}

我需要将上述代码移动到中间件吗?中间件能否允许我调用控制器的SetInfo()方法?


你能解释一下 SetInfo() 是做什么的吗?如果整个 token 处理程序可以在管道处理方法中处理,那就很有意义。 - Turbot
2个回答

1
在第一部分中,看起来您正在提取身份验证令牌。可以配置一个中间件在控制器操作之前运行,但这涉及如何将信息传递给控制器。例如,身份验证中间件只需设置HttpRequest的Principal即可在控制器执行期间重复使用。
关于SetInfo,是否使用中间件清楚地取决于信息的性质,但是它是可行的。例如,在我的情况下,为了调试原因,在开发环境中,我有一个中间件通过将其添加到HttpContext中将我的会话过期时间信息传输到我的控制器。虽然我不是说这是一个好的做法。
context.Request.HttpContext.Items.Add(ExpiresUTCEntry, context.Properties.ExpiresUtc);

0

为什么不将其转换为惰性控制器属性呢?

这样做很好,因为如果您不使用它,现在就不会从缓存中获取用户。

private User _user;
public User user { get { return _user ?? (_user = UserCache.Get(this.Request.Properties["token"])); } }

在构造函数上调用初始化程序

关于SetInfo()

我建议将此代码移动到构造函数或其他位置(取决于此函数的内容)。控制器是在Router完成其工作后创建的。通过IControllerFactory。你可以扩展DefaultControllerFactory。该类负责创建控制器实例。(确保在IServiceCollection中注册它,否则你的类就不是被解析的那个。

在你的情况下,我认为最好重新思考你的架构,专注于尽可能无状态,并避免使用以下描述的反模式之一。

有关MVC请求管道的信息

这就是在MVC中请求管道的工作方式(并且仍然适用于AspNetCore)。 enter image description here 图片来自dotnetCurry

在管道中较早地访问用户

如果您想要在请求管道的早期访问用户,我建议:

  • @dabouls的答案:添加中间件以将其注入到Http.Items中
  • 创建一个UserRepository类,并在Ioc容器中注册它以请求范围使用HttpContextAccessor,但通常访问HttpContext.Current是一种反模式,不鼓励使用。

Request 没有 Properties 属性。您是指 IHeaderDictionary 吗? - Ivan-Mark Debono
@Ivan-MarkDebono 在控制器上吗? - Joel Harkes
是的,在this.Request.Properties上。 - Ivan-Mark Debono

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接