在请求期间访问/使用同一对象 - asp.net

发布于 2024-07-27 21:03:37 字数 650 浏览 6 评论 0原文

我有一个 HttpModule,它在每个请求上创建一个 CommunityPrincipal (实现 IPrincipal 接口)对象。 我想以某种方式存储每个请求的对象,以便我可以在需要时获取它,而无需进行强制转换或再次创建它。

基本上我想模仿 FormsAuthenticationModule 的工作方式。 它在每次请求时为 HttpContext.User 属性分配一个实现 IPrincipal 接口的对象。

我以某种方式希望能够调用 HttpContext.MySpecialUser (或 MySpecialContext.MySpecialUser - 可以创建静态类)等,它将返回我的对象​​(特定类型)。

我可以使用扩展方法,但我不知道如何存储该对象,以便在请求期间可以访问它。

如何才能实现这一目标?

请注意,我想将其存储为特定类型(CommunityPrincipal - 不仅仅是作为对象)。 当然,它应该仅适用于正在处理的当前请求,而不应与所有其他线程/请求共享。

现在,我将 CommunityPrincipal 对象分配给 HttpModule 中的 HttpContext.User,但每次需要使用 CommunityPrincipal 对象上未在 IPrincipal 接口中定义的属性时,它都要求我进行强制转换。

i have a HttpModule that creates an CommunityPrincipal (implements IPrincipal interface) object on every request. I want to somehow store the object for every request soo i can get it whenever i need it without having to do a cast or create it again.

Basically i want to mimic the way the FormsAuthenticationModule works.
It assigns the HttpContext.User property an object which implements the IPrincipal interface, on every request.

I somehow want to be able to call etc. HttpContext.MySpecialUser (or MySpecialContext.MySpecialUser - could create static class) which will return my object (the specific type).

I could use a extension method but i dont know how to store the object so it can be accessed during the request.

How can this be achieved ?

Please notice i want to store it as the specific type (CommunityPrincipal - not just as an object).
It should of course only be available for the current request being processed and not shared with all other threads/requests.

Right now i assign my CommunityPrincipal object to the HttpContext.User in the HttpModule, but it requires me to do a cast everytime i need to use properties on the CommunityPrincipal object which isnt defined in the IPrincipal interface.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

荒岛晴空 2024-08-03 21:03:37

我建议您不要将数据耦合到线程本身。 您无法控制 ASP.NET 现在或将来如何使用线程。

数据与请求上下文密切相关,因此它应该与上下文一起定义、生存和消亡。 这正是放置它的正确位置,并且在 HttpModule 中实例化该对象也是合适的。

强制转换确实不应该是一个大问题,但如果您想摆脱这个问题,我强烈推荐为此使用 HttpContext 的扩展方法...这正是扩展方法旨在处理的情况。

以下是我的实现方式:

创建一个静态类来放置扩展方法:

public static class ContextExtensions
{
    public static CommunityPrinciple GetCommunityPrinciple(this HttpContext context)
    {
        if(HttpContext.Current.Items["CommunityPrinciple"] != null)
        {
            return HttpContext.Current.Items["CommunityPrinciple"] as CommunityPrinciple;
        }
    }
}

在 HttpModule 中,只需将主体放入上下文项集合中,例如:

HttpContext.Current.Items.Add("CommunityPrincipal", MyCommunityPrincipal); 

这使常规上下文的用户属性保持在自然状态,以便第 3 方代码,框架代码,以及您编写的任何其他内容都不会因篡改那里的正常 IPrincipal 而面临风险。 该实例仅在其有效的用户请求期间存在。 最重要的是,该方法可用于编码,就像它只是任何常规 HttpContext 成员一样......并且不需要强制转换。

I'd recommend you stay away from coupling your data to the thread itself. You have no control over how asp.net uses threads now or in the future.

The data is very much tied to the request context so it should be defined, live, and die along with the context. That is just the right place to put it, and instantiating the object in an HttpModule is also appropriate.

The cast really shouldn't be much of a problem, but if you want to get away from that I'd highly recommend an extension method for HttpContext for this... this is exactly the kind of situation that extension methods are designed to handle.

Here is how I'd implement it:

Create a static class to put the extension method:

public static class ContextExtensions
{
    public static CommunityPrinciple GetCommunityPrinciple(this HttpContext context)
    {
        if(HttpContext.Current.Items["CommunityPrinciple"] != null)
        {
            return HttpContext.Current.Items["CommunityPrinciple"] as CommunityPrinciple;
        }
    }
}

In your HttpModule just put the principal into the context items collection like:

HttpContext.Current.Items.Add("CommunityPrincipal", MyCommunityPrincipal); 

This keeps the regular context's user property in the natural state so that 3rd party code, framework code, and anything else you write isn't at risk from you having tampered with the normal IPrincipal stroed there. The instance exists only during the user's request for which it is valid. And best of all, the method is available to code as if it were just any regular HttpContext member.... and no cast needed.

盗梦空间 2024-08-03 21:03:37

将您的自定义主体分配给 Context.User 是正确的。 希望您在 Application_AuthenticateRequest 中执行此操作。

说到你的问题,你只从 ASPX 页面访问用户对象吗? 如果是这样,您可以实现一个包含您的演员阵容的自定义基本页面。

public class CommunityBasePage : Page
{
    new CommunityPrincipal User
    {
        get { return base.User as CommunityPrincipal; }
    }
}

然后让您的页面继承自 CommunityBasePage,然后您就可以从 this.User 访问您的所有属性。

Assigning your custom principal to Context.User is correct. Hopefully you're doing it in Application_AuthenticateRequest.

Coming to your question, do you only access the user object from ASPX pages? If so you could implement a custom base page that contains the cast for you.

public class CommunityBasePage : Page
{
    new CommunityPrincipal User
    {
        get { return base.User as CommunityPrincipal; }
    }
}

Then make your pages inherit from CommunityBasePage and you'll be able to get to all your properties from this.User.

山有枢 2024-08-03 21:03:37

由于您已经将对象存储在 HttpContext.User 属性中,因此实现您的目标真正需要的是实现您的目标的静态方法:-

  public static class MySpecialContext
  {
    public static CommunityPrinciple Community
    {
        get
        {
           return (CommunityPrinciple)HttpContext.Current.User;
        }
    }
  }

现在您可以将 CommunityPrinciple 获取为:-

  var x = MySpecialContext.Community;

然而,要避免似乎需要付出很大的努力:-

  var x = (CommunityPrinciple)Context.User;

另一种选择是 HttpContext 上的扩展方法:-

  public static class HttpContextExtensions
  {
    public static CommunityPrinciple GetCommunity(this HttpContext o)
    {
      return (CommunityPrinciple)o.User;
    }
  }

使用它:-

  var x = Context.GetCommunity();

这非常整洁,但需要您记住包含在每个需要它的文件的使用列表中定义扩展类的名称空间。

编辑

暂时假设您有一些非常充分的理由,为什么即使在上述调用的代码中执行强制转换仍然是不可接受的(顺便说一句,我真的很想了解什么情况会导致您这个结论)。

另一种选择是 ThreadStatic 字段:-

  public class MyModule : IHttpModule
  {
    [ThreadStatic]
    private static CommunityPrinciple _threadCommunity;

    public static CommunityPrinciple Community
    {
        get
        {
           return _threadCommunity;
        }
    }
    // Place here your original module code but instead of (or as well as) assigning
    // the Context.User store in _threadCommunity.
    // Also at the appropriate point in the request lifecyle null the _threadCommunity

  }

用 [ThreadStatic] 修饰的字段将为每个线程提供一个存储实例。 因此,多个线程可以修改和读取 _threadCommunity,但每个线程都将对其特定的字段实例进行操作。

Since you already storing the object in the HttpContext.User property all you really need to acheive you goal is a Static method that acheives your goal:-

  public static class MySpecialContext
  {
    public static CommunityPrinciple Community
    {
        get
        {
           return (CommunityPrinciple)HttpContext.Current.User;
        }
    }
  }

Now you can get the CommunityPrinciple as:-

  var x = MySpecialContext.Community;

However it seems a lot of effort to got to avoid:-

  var x = (CommunityPrinciple)Context.User;

An alternative would be an Extension method on HttpContext:-

  public static class HttpContextExtensions
  {
    public static CommunityPrinciple GetCommunity(this HttpContext o)
    {
      return (CommunityPrinciple)o.User;
    }
  }

The use it:-

  var x = Context.GetCommunity();

That's quite tidy but will require you to remember to include the namespace where the extensions class is defined in the using list in each file the needs it.

Edit:

Lets assume for the moment that you have some really good reason why even a cast performed inside called code as above is still unacceptable (BTW, I'd be really interested to understand what circumstance leads you to this conclusion).

Yet another alternative is a ThreadStatic field:-

  public class MyModule : IHttpModule
  {
    [ThreadStatic]
    private static CommunityPrinciple _threadCommunity;

    public static CommunityPrinciple Community
    {
        get
        {
           return _threadCommunity;
        }
    }
    // Place here your original module code but instead of (or as well as) assigning
    // the Context.User store in _threadCommunity.
    // Also at the appropriate point in the request lifecyle null the _threadCommunity

  }

A field decorated with [ThreadStatic] will have one instance of storage per thread. Hence multiple threads can modify and read _threadCommunity but each will operate on their specific instance of the field.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文