简体   繁体   English

ASP.NET 内核 - 向 HttpRequest 添加自定义属性

[英]ASP.NET Core - Add Custom Property to HttpRequest

I have some ASP.NET Middleware that analyzes a request as it comes in. Based on what's available in that HttpRequest , I would like to add a custom property that I can use in my code.我有一些 ASP.NET 中间件可以在请求进入时对其进行分析。根据该HttpRequest中可用的内容,我想添加一个可以在我的代码中使用的自定义属性。 My question is, is there a way for me to add a property to HttpRequest so that I can access it in my controller?我的问题是,有没有办法让我向HttpRequest添加一个属性,以便我可以在我的 controller 中访问它? For example, in my Controller , I would like to do something like this:例如,在我的Controller中,我想做这样的事情:

namespace MyWebsite.Controllers
{
  public class MyController : Controller

  public IActionResult Index()
  {
    if (this.Request.MyProperty == null)
    {
      return View("~/Views/NoExist.cshtml");
    }
    return View ("/Views/Index.cshtml");
  }
}

MyProperty represents the custom property that I would like to inject, or add, via my custom middleware. MyProperty表示我想通过我的自定义中间件注入或添加的自定义属性。 Is this possible?这可能吗? If so, how?如果是这样,怎么做? If not, what is the recommended approach?如果没有,推荐的方法是什么?

Thank you!谢谢!

The traditional way of achieving what you want is sharing everything via HttpContext.Items .实现您想要的东西的传统方式是通过HttpContext.Items共享所有内容。 That way you should manage the keys yourself or even can declare your extension methods for conveniently setting & getting the values.这样,您应该自己管理keys ,甚至可以声明您的扩展方法以方便地设置和获取值。

However here I'd like to introduce a new way associated with a new concept request feature in asp.net core .不过在这里我想介绍一种与asp.net core中的新概念request feature相关的新方法。 The features associated with each request can be added by different middlewares along the pipeline and can be consumed by any (if available).与每个请求相关的特性可以由管道中的不同中间件添加,并且可以被任何(如果可用)使用。 That looks like neater and more organized, although may not be very convenient compared to the old way.这看起来更整洁,更有条理,尽管与旧方式相比可能不是很方便。

Suppose you're in the context of your middleware, the following code will add a feature which exposes your property:假设您在中间件的上下文中,以下代码将添加一个公开您的属性的功能:

//declare the feature interface first
public interface IMyFeature {
    string MyProperty {get;}
}

//the concrete type for the feature
public class MyFeature : IMyFeature {
    public MyFeature(string myProperty){
        MyProperty = myProperty;
    }
    public string MyProperty {get;}
}

//the context is in your middleware
//add the feature
var myFeature = new MyFeature("value of your choice");
//context here is the HttpContext
context.Features.Set<IMyFeature>(myFeature);

Now anywhere later in the pipeline, you can consume the feature added like this:现在,在管道的任何后期,您都可以使用添加的功能,如下所示:

//context here is the HttpContext
var myFeature = context.Features.Get<IMyFeature>();
if(myFeature != null){
    //consume your feature
}

One point I think the request features concept is good about is its clear definition of feature interfaces which can be learned, referenced and managed easily by your code.我认为request features概念好的一点是它对feature interfaces的清晰定义,可以通过代码轻松学习、引用和管理。 Even porting it to some library for reusing makes more sense than depending on some constant key for accessing the shared data (as achieved by using HttpContext.Items ).即使将其移植到某个库以进行重用,也比依赖某个常量键来访问共享数据(通过使用HttpContext.Items实现)更有意义。 Of course for some simple data sharing, you can just use HttpContext.Items , the request feature should be used when it may evolve later, has a clear cool concept around it and may contain more data.当然对于一些简单的数据共享,你可以使用HttpContext.Items ,请求特性应该在以后可能发展的时候使用,围绕它有一个清晰的酷概念,并且可能包含更多的数据。

  1. Create a singleton that has a readonly ConcurrentDictionary property.创建一个具有只读 ConcurrentDictionary 属性的 singleton。 Alternatively, create a static class with a readonly static property of type ConcurrentDictionary.或者,使用 ConcurrentDictionary 类型的只读 static 属性创建 static class。

  2. Add a readonly Queue property to your global class.将只读队列属性添加到全局 class。

  3. Use the HttpContext.TraceIdentifier as a unique key and add the data to the ConcurrentDictionary as the value.使用 HttpContext.TraceIdentifier 作为唯一键,并将数据作为值添加到 ConcurrentDictionary。 Also add the HttpContext.TraceIdentifier and DateTime.Now to the Queue property.还将 HttpContext.TraceIdentifier 和 DateTime.Now 添加到 Queue 属性。

  4. Create a clean-up method that removes old data from the Queue and ConcurrentDictionary by pulling data off the Queue until it is under a particular age, say 90 seconds.创建一个清理方法,通过从队列中拉出数据直到它低于特定年龄,比如 90 秒,从队列和 ConcurrentDictionary 中删除旧数据。

  5. Create a background worker that runs periodically and calls the cleanup method.创建一个定期运行并调用清理方法的后台工作程序。 There are libraries that do this.有图书馆可以做到这一点。 You can also spin off a thread at startup, but this lacks redundancy unless you code it.您也可以在启动时分离一个线程,但这缺乏冗余,除非您对其进行编码。

  6. Access your data from any called code using the key HttpContext.TraceIdentifier.使用键 HttpContext.TraceIdentifier 从任何调用的代码访问您的数据。

Happy Coding!快乐编码!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM