代码之家  ›  专栏  ›  技术社区  ›  anonymous

ASP.NET MVC:httpContext和依赖项注入

  •  16
  • anonymous  · 技术社区  · 16 年前

    目前我有一个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。

    4 回复  |  直到 12 年前
        1
  •  8
  •   Matt Hinze    16 年前

    具有接口abstract httpcontext.current。只公开您需要的方法。 GetUserName() 例如,将在实现中调用httpcontext.current.user.identity.name。把它弄得尽可能薄。

    接受这个抽象,并将其注入到其他提供者类中。这将允许您通过模拟HTTP上下文抽象来测试提供者。作为一个附带的好处,您可以使用HTTPContext抽象做其他漂亮的事情,除了模仿它。一方面,重用它。向包等添加通用类型参数。

        2
  •  9
  •   TheCodeKing    12 年前

    听起来你应该用 HttpContextBase 而不是 HttpContextUserProvider . 这是一个开箱即用的抽象 HttpContext 并允许您创建模拟、编写单元测试和注入依赖项。

    public class SomethingWithDependenciesOnContext
    {
        public SomethingWithDependenciesOnContext(HttpContextBase context) {
            ...
        }
    
        public string UserName
        {
            get {return context.User.Identity.Name;}
        }
    }
    
    ObjectFactory.Initialize(x => 
              x.For<HttpContextBase>()
              .HybridHttpOrThreadLocalScoped()
              .Use(() => new HttpContextWrapper(HttpContext.Current));
    
        3
  •  3
  •   Brad Wilson    16 年前

    我不知道你为什么这么麻烦。似乎只是在httpContextUserProvider中直接使用httpContext.current是正确的做法。你永远不会在不同的httpcontext中替换…

        4
  •  2
  •   anonymous    16 年前

    也许我遗漏了一些东西,但是上面的答案对我来说不起作用(已经被删除了——尽管它仍然是一个有用的答案——它展示了如何告诉sm传递构造函数参数)。相反,如果我这样做:

    ObjectFactory.Initialize(x =>
    {
        x.BuildInstancesOf<HttpContext>()
             .TheDefault.Is.ConstructedBy(() => HttpContext.Current);
        x.ForRequestedType<IUserProvider>()
             .TheDefault.Is.OfConcreteType<HttpContextUserProvider>();
    });
    

    我让它工作。我在发现: http://codebetter.com/blogs/jeremy.miller/archive/2008/03/20/if-you-need-something-in-structuremap-but-you-can-t-build-it-with-new.aspx


    编辑:

    多亏了布拉德的回答我 认为 我对httpContext有更好的理解。他的回答肯定有效,我只是不确定我是否喜欢调用httpContext.current在类中(它似乎隐藏了依赖性,但我远不是这方面的专家)。

    据我所知,上面的代码应该可以用于注入httpcontext。MattHinze提出了一个补充点,如果我从httpContext需要的只是user.identity.name,那么我的设计应该是明确的(在httpContext周围有一个接口只公开我需要的内容)。我觉得这是个好主意。

    午餐过后,我有点意识到我的服务只需要依赖一个字符串:用户名。如果它依赖于IUserProvider,可能没有太多附加值。所以我知道我不希望它依赖于httpContext,我只需要一个字符串(用户名)——我需要看看我是否可以学习足够的结构映射foo来为我建立这个连接。(Sirrocoo的回答给出了从哪里开始的提示,但他删除了它:*()。