用于Web API中的批处理OData请求的NULL HttpContext - 错误的设计模式?

时间:2015-09-29 14:06:41

标签: c# asp.net asp.net-web-api odata ninject

我正在尝试确定将依赖项注入控制器的正确方法,其中要注入的具体类型是基于路由数据参数的变量。

到目前为止,我有以下设置,它完全适用于正常请求:

控制器

 public class OrdersController : ODataController
 {

    private IOrderService ErpService { get; }

    public OrdersController(IOrderService orderService)
    {
        ErpService = orderService;
    }

    [EnableQuery(PageSize = 100)]
    public IQueryable<OrderDto> Get(ODataQueryOptions<OrderDto> queryOptions)
    {
        return ErpService.Orders(queryOptions);
    }

    ...
    // Post
    // Patch/Put
    // Delete
}

使用以下OData路由配置,我可以指定路由模板应该包含一个&#39;公司&#39;参数:

配置

config.MapODataServiceRoute( "ODataRoute", "data/{company}", model, new DefaultODataPathHandler(),
                conventions, new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));

这允许我使用静态方法从URL中读取公司ID:

public static string GetSalesCompanyFromRequest()
{
    var salesCompany = "";
    if (HttpContext.Current == null) return "";

    var routeData = HttpContext.Current.Request.RequestContext.RouteData;
    if (routeData.Values.ContainsKey("company"))
    {
        salesCompany = routeData.Values["company"].ToString();
    }

    return salesCompany;
}

然后,使用Ninject,我可以选择使用哪个具体的IOrderService实例(简化为简洁):

kernel.Bind<IOrderService>()
            .To<SageOrderService>()
            .When(ctx => GetSalesCompanyFromRequest() == "101").InRequestScope();

kernel.Bind<IOrderService>()
            .To<DynamicsAxOrderService>()
            .When(ctx => GetSalesCompanyFromRequest() == "222").InRequestScope();

kernel.Bind<IOrderService>()
            .To<SapOrderService>()
            .When(ctx => GetSalesCompanyFromRequest() == "333").InRequestScope();

连接器配置

Id          ErpType        ConnectionString
--------------------------------------------
111         Sage           "connectionstring1"
222         DynamicsAx     "connectionstring2"
333         SAP            "connectionstring3"

以下是处理以下网址的方法:

http://odata-demo/data/101/Orders
创建SageOrderServiceOrdersController

并注入DynamicsAxOrderService

http://odata-demo/data/ 222 /订单
创建OrdersControllerHttpContext.Current

并注入HttpContext.Current

同样的逻辑适用于许多不同的服务,例如:

  • SageStockService / AxStockService
  • SageBomService / AxBomService

注意: 我选择将公司ID放在URL中,这样我就可以配置反向代理将请求转发到更靠近目标数据库的本地Web服务器。

这一切都完美无缺,直到我尝试使用OData Batching。 当我发送批量请求时,似乎没有var myOptions = { zoom : currentZoomLevel, center : latlng, disableDefaultUI: true, minZoom: 2, maxZoom: 20, mapTypeId : google.maps.MapTypeId.SATELLITE, }; map = new google.maps.Map(document.getElementById("googlemap"), myOptions); (它为空)。

This question询问类似的内容但不考虑OData批量请求。

Comments在这个答案中建议按路线数据注入代码气味,但没有详细说明。

那么,问题是,如何获得批量OData请求的var styleArray = [ { featureType: "all", stylers: [ { visibility: "off" } ] }/*,{ featureType: "road.arterial", elementType: "geometry", stylers: [ { hue: "#00ffee" }, { saturation: 50 } ] },{ featureType: "poi.business", elementType: "labels", stylers: [ { visibility: "off" } ] }*/ ]; var latlng = new google.maps.LatLng(24.91654, 15.31326); var myOptions = { zoom : currentZoomLevel, center : latlng, disableDefaultUI: true, minZoom: 2, maxZoom: 20, mapTypeId : google.maps.MapTypeId.SATELLITE, styles :styleArray /*[ { "featureType": "administrative.country", "elementType": "labels", "stylers": [ { "visibility": "on" } ] } ]*/ }; map = new google.maps.Map(document.getElementById("googlemap"), myOptions); ?或者,有没有更好的方法来做我想做的事情?

1 个答案:

答案 0 :(得分:0)

由于公司已经在路线数据中,我可以为每一个动作添加一个额外的公司参数,如下所示,以允许公司号码被传入,然后使用工厂获得正确的具体类型:

public class OrdersController : ODataController
{

    [EnableQuery(PageSize = 100)]
    public IQueryable<OrderDto> Get(ODataQueryOptions<OrderDto> queryOptions, string company)
    {

        var erpService = ErpServiceFactory.GetService(company);

        return erpService.Orders(queryOptions);
    }

    ...
    // Post
    // Patch/Put
    // Delete
}

这意味着我还必须在每个动作中初始化OrderService,这有点气味。

如果我使用ActionFilter定位并将正确的具体类型传递给动作,我想这可能不那么臭:

public class RequiresOrderServiceAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        string salesCompany = "";
        var data = actionContext.Request.GetRouteData();

        if (data.Values.ContainsKey("company"))
        {
            salesCompany = data.Values["company"].ToString();

            var orderService = ErpServiceFactory.GetService(company);

            actionContext.ActionArguments.Add("erpService", orderService);
        }
    }
}

public class OrdersController : ODataController
{

    [EnableQuery(PageSize = 100)]
    public IQueryable<OrderDto> Get(ODataQueryOptions<OrderDto> queryOptions, IOrderService erpService)
    {
        return erpService.Orders(queryOptions);
    }

    ...
    // Post
    // Patch/Put
    // Delete
}

思想?