我需要通过请求Web API服务中所有数据库调用的主机名来应用筛选。
这种过滤是这样工作的:
- 根据请求的主机名查找要配置文件的站点
- 在请求中进行的所有后续数据访问调用上应用Site.Id
本质上是一个全局过滤器,因此API服务返回的数据始终包含在主机中。
一个解决方案是将主机名作为参数传入我的所有服务方法,如下所示:
public IEnumerable<Profiles> GetProfiles ()
{
var host = HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
return profilesService.Get(host);
}
但由于这是所有请求的一致规则,我想想出一种更优雅的方法来处理它,所以我的服务调用只是profileSerivce.Get();
我想我需要在我的服务层中注入一个ISiteLocator,它要么有主机名,要么更好的是已经从数据库中检索到的Id,然后我可以应用它。但我很难理解如何以及在哪里引用HttpContext来获得主机名,以及是否可以使用StructureMap生命周期来优化它。
我想我需要在我的服务层中注入一个ISiteLocator
在我看来,你正朝着正确的方向前进。
我正在为如何以及在哪里引用HttpContext
这实际上很简单。在业务层中定义ISiteLocator
,并在ASP.NET web应用程序中定义一个AspNetSiteLocator
实现,最好是在CompositionRoot附近(或内部)。这个实现可能看起来像这样:
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更方便,因为消费者可能需要再次查询网站。然而,也许身份证是最方便的,但这取决于你自己。
如何[…]使用StructureMap生命周期优化
上面的实现没有任何状态,所以它可以在任何生存期内注册;例如,singleton。然而,对ISiteLocator.GetCurrentSite()
的每次调用都会导致对ISiteRepository
的新请求,这可能会导致太多的开销。在这种情况下,您可能想要一个将Site
存储在私有字段中并始终返回该实例的实现。在这种情况下,您应该在"每个Web请求"的基础上注册该实现(因为SERVER_NAME
在请求期间不会更改)。