将主机从HttpContext注入服务层

时间:2012-09-28 16:48:28

标签: c# dependency-injection structuremap httpcontext asp.net-web-api

我需要通过在Web API服务中的所有数据库调用上请求主机名来应用过滤。

此过滤的工作原理如下:

  1. 根据请求主机名
  2. 查找要反对的网站
  3. 在请求中进行的所有后续数据访问调用中应用Site.Id
  4. 本质上是一个全局过滤器,以便API服务返回的数据始终包含在主机中。

    一种解决方案是将主机名作为参数传递给我所有的服务方法,如:

    public IEnumerable<Profiles> GetProfiles ()
    {
     var host = HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
     return profilesService.Get(host);
    }
    

    但由于这是对所有请求的一致规则,我想提出一种更优雅的方式来处理这个问题,所以我的服务调用只是profileSerivce.Get();

    我认为我需要将ISiteLocator注入我的服务层,该服务层具有主机名,甚至更好的已经从数据库中检索到的Id然后我可以应用。但是我正在努力解决HttpContext如何以及在哪里获取主机名,以及是否可以使用StructureMap生命周期来优化它。

1 个答案:

答案 0 :(得分:2)

  

我想我需要将ISiteLocator注入我的服务层

在我看来,你正朝着正确的方向前进。

  

我正在努力研究如何以及在哪里引用它   HttpContext的

实际上这很简单。在您的业务层中定义ISiteLocator并在ASP.NET Web应用程序中定义AspNetSiteLocator实现,最好在您的Composition Root附近(或内部)。该实现可能如下所示:

public class AspNetSiteLocator : ISiteLocator
{
    private readonly ISiteRepository siteRepository;

    public AspNetSiteLocator(ISiteRepository siteRepository)
    {
        this.siteRepository = siteRepository;
    }

    Site ISiteLocator.GetCurrentSite()
    {
        return this.siteRepository.GetById(CurrentHostName);
    }

    private static string CurrentHostName
    {
        get
        {
           return HttpContext.Current.Request
               .ServerVariables["SERVER_NAME"];
        }
    }
}
  

具有主机名或甚至更好的Id已检索   来自数据库

尝试让ISiteLocator以对该定位器的使用者最方便的方式返回数据。在我的示例中,我返回了一个Site实体(如果您的域中有这样的实体)。这可能比主机名或Id更方便,因为消费者可能不得不再次查询该站点。但是,也许Id是最方便的,但这取决于你找出来。

  

如何使用StructureMap生命周期来优化它

上面的实现没有任何状态,因此可以在任何生命周期内注册;例如单身人士。但是,每次调用ISiteLocator.GetCurrentSite()都会向ISiteRepository发出新请求,这可能会导致过多的开销。在这种情况下,您可能需要一个将Site存储在私有字段中的实现,并始终返回该实例。在这种情况下,您应该在“每Web请求”的基础上注册该实现(因为SERVER_NAME在请求期间不会更改。)