ASP.NET MVC:HTTPContext 和依赖注入
目前,我有一个 ActionFilter,它从 HttpContext 获取当前用户名并将其传递到在服务方法上使用它的操作中。 例如:
Service.DoSomething(userName);
我现在有理由不在操作级别而是在控制器构造函数级别执行此操作。 目前我正在使用结构图来创建控制器并注入服务。 我正在看这样的东西:
public interface IUserProvider
{
string UserName { get; }
}
public class HttpContextUserProvider : IUserProvider
{
private HttpContext context;
public HttpContextUserProvider(HttpContext context)
{
this.context = context;
}
public string UserName
{
get
{
return context.User.Identity.Name;
}
}
}
也就是说,我的 IoC foo 真的很弱,因为这是我使用它的第一个项目。
所以我的问题是......我如何告诉结构图在 HttpContextUserProvider 的构造函数中传递 HttpContext ? 这看起来很奇怪......我不知道如何看待 HttpContext。
Currently I have an ActionFilter that gets the current users name from HttpContext and passes it into the action which uses it on a service method. eg:
Service.DoSomething(userName);
I now have a reason to do this not at the action level but the controller constructor level. Currently I'm using structure map to create controllers and inject the service. I'm looking at something like:
public interface IUserProvider
{
string UserName { get; }
}
public class HttpContextUserProvider : IUserProvider
{
private HttpContext context;
public HttpContextUserProvider(HttpContext context)
{
this.context = context;
}
public string UserName
{
get
{
return context.User.Identity.Name;
}
}
}
That said, my IoC foo is really weak as this is the first project I've used it on.
So my question is... how can I tell structure map to pass in HttpContext in the constructor for HttpContextUserProvider? This just seems weird... I'm not sure how to think of HttpContext.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
听起来您应该使用
HttpContextBase
而不是HttpContextUserProvider
。 这是HttpContext
的开箱即用抽象,允许您创建模拟、编写单元测试并注入依赖项。It sounds like you should be using
HttpContextBase
instead ofHttpContextUserProvider
. This is a out-of-box abstraction ofHttpContext
and allows you to create a mock, write UnitTests and inject your dependencies.有一个接口抽象
HttpContext.Current
。 仅公开您需要的方法。 例如,GetUserName()
将在实现中调用HttpContext.Current.User.Identity.Name
。 让它尽可能薄。获取该抽象并将其注入到您的其他提供程序类中。 这将允许您通过模拟 http 上下文抽象来测试提供程序。 附带的好处是,除了模拟之外,您还可以使用 HttpContext 抽象做其他有趣的事情。 一方面,重复使用它。 将通用类型参数添加到包等中。
Have an interface abstract
HttpContext.Current
. Expose only the methods you need.GetUserName()
would callHttpContext.Current.User.Identity.Name
in the implementation, for example. Make that as thin as possible.Take that abstraction and inject it into your other provider class. This will allow you to test the provider by mocking the http context abstraction. As a side benefit, you can do other nifty things with that
HttpContext
abstraction besides mock it. Reuse it, for one thing. Add generic type params to bags, etc.我不知道你为什么要打扰。 似乎直接在 HttpContextUserProvider 中使用 HttpContext.Current 是正确的做法。 你永远不会在不同的 HttpContext 中替换......
I'm not sure why you're bothering. It seems like just using HttpContext.Current directly in HttpContextUserProvider is the right thing to do. You're never going to be substituting in a different HttpContext...
也许我遗漏了一些东西,但上面的答案对我不起作用(已被删除——尽管它仍然是一个有用的答案——它展示了如何告诉 SM 传递构造函数参数)。 相反,如果我这样做:
我就会让它发挥作用。 我发现后这样做: 如果您需要 StructureMap 中的某些内容,但无法使用 new() 构建它...
编辑:
感谢 Brad 的回答我认为我对
HttpContext
有更好的处理。 他的答案肯定有效,我只是不确定我是否喜欢在类中调用HttpContext.Current
(看起来它隐藏了依赖关系,但我远不是这方面的专家) 。据我所知,上面的代码应该适用于注入
HttpContext
。 Matt Hinze 提出了补充一点,如果我从 HttpContext 需要的只是 User.Identity.Name,我的设计应该明确这一点(在HttpContext 周围有一个接口code>HttpContext
仅公开我需要的内容)。 我认为这是一个好主意。午餐时,我意识到我的服务实际上只需要依赖于一个字符串:
userName
。 让它依赖于IUserProvider
可能不会有太多附加值。 所以我知道我不希望它依赖于HttpContext
,而且我确实知道我需要的只是一个字符串 (userName
) - 我需要看看是否可以学习足够的StructureMap
foo 来为我建立这种联系。 (sirrocoo 的回答给出了从哪里开始的提示,但他删除了它:*()。Maybe I left something out, but the above answer doesn't work for me (has since been deleted -- it was still a useful answer though -- it showed how to tell SM to pass constructor arguments). Instead if I do:
I get it to work. I did this after finding: If you need something in StructureMap, but you can’t build it with new()…
Edit:
Thanks to Brad's answer I think I have a better handle on
HttpContext
. His answer definitely works, I just am not sure I like having the call toHttpContext.Current
inside a class (it seems like it hides the dependency, but I'm far from an expert on this stuff).The above code should work for injecting
HttpContext
as far as I can tell. Matt Hinze brings up the added that point that if all I need fromHttpContext
is theUser.Identity.Name
, my design should be explicit about that (having an Interface aroundHttpContext
only exposing what I need). I think this is a good idea.The thing is over lunch I kinda realized my service really only needs to depend on a string:
userName
. Having it depend onIUserProvider
might not have much added value. So I know I don't want it to depend onHttpContext
, and I do know all I need is a string (userName
) -- I need to see if I can learn enoughStructureMap
foo to have make this connection for me. (sirrocoo's answer gives a hint on where to start but he deleted it :*( ).