1

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

此过滤的工作方式如下:

  1. 根据请求的主机名查找要配置文件的站点
  2. 将 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 生命周期对其进行优化。

4

1 回答 1

2

我想我需要在我的服务层中注入一个 ISiteLocator

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

我正在努力解决如何以及在何处可以引用 HttpContext

这其实很简单。ISiteLocator在您的业务层中定义并在AspNetSiteLocator您的 ASP.NET Web 应用程序中定义一个实现,最好靠近(或内部)您的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在请求期间不会更改)。

于 2012-09-29T09:34:10.250 回答