Web API中批量OData请求的HttpContext为NULL -错误的设计模式
本文关键字:HttpContext NULL 设计模式 错误 请求 API OData Web | 更新日期: 2023-09-27 18:15:19
我正在尝试确定正确的方法来注入一个依赖到一个控制器,其中要注入的具体类型是一个基于路由数据参数的变量。
到目前为止,我有以下设置,可以完美地用于正常请求:
控制器 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路由配置,我可以指定路由模板应该包含一个'company'参数:
配置
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"
下面是如何处理以下url的:
http://odata-demo/data/101/Orders
创建SageOrderService
并将其注入OrdersController
http://odata-demo/data/ 222 /
订单创建DynamicsAxOrderService
并注入OrdersController
相同的逻辑适用于许多不同的服务,如:
- SageStockService/AxStockService
- SageBomService/AxBomService 等
注意:我选择将公司Id放在URL中,这样我就可以配置反向代理将请求转发到更靠近目标数据库的本地web服务器。
这一切工作完美,直到我尝试使用OData批处理。当我发送批量请求时,似乎没有HttpContext.Current
(它是null)。
这个问题问了类似的问题,但没有考虑到OData批处理请求。
这个回答中的注释表明,通过路由数据注入有代码味道,但没有详细说明。
所以,问题是,我如何获得HttpContext.Current
批处理OData请求?或者有没有更好的方法来做我想做的事?
由于公司已经包含在路由数据中,我可以为每个动作添加一个额外的公司参数,如下所示,以允许传入公司编号,然后使用工厂来获得正确的具体类型:
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
}
想法吗?