如何为 WebApi 2 和 OData 控制器设置 IIS TransferRequestHandler 路径?



我希望正确配置System.Web.Handlers.TransferRequestHandlerpath属性,以便在 ASP.NET WebApi 2项目中处理WebApi REST操作ODataController自定义函数的路由。

我的web.config文件处理程序配置如下,以支持自定义 ODataController 函数调用(在此处查看我的相关问题(:

<handlers>
<clear/>
<remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
<remove name="OPTIONSVerbHandler"/>
<remove name="TRACEVerbHandler"/>
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="/*" verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
</handlers>
</system.webServer>

请注意,路径设置为/*,并且在访问我们ODataControllers上的自定义OData 函数时效果很好

尽管如此,我们还有一个 ApiController 并且当我们访问它时,IIS 无法正确处理请求并失败并显示以下详细信息:

HTTP 错误 500.0 - 内部服务器错误 内部服务器错误

详细错误信息:
模块托管管道处理程序通知执行请求处理程序

处理程序扩展无 urlHandler-集成-4.0
错误代码0x800703e9

如果我按照此处的建议将TransferRequestHandlerpath设置为*.,则WebApi请求将得到正确解析,但是ODataController请求最终无法在HTTP 400中找到:

HTTP 错误 404.4 - 未找到
您要查找的资源没有与之关联的处理程序。

详细错误信息:
模块IIS Web 核心
通知映射请求处理程序
处理程序尚未确定
错误代码0x80070002

如何正确配置它以处理这两种情况?

++++ 编辑:++++为了
清楚起见,这是我用来测试控制器的查询:

  • 自定义 odata 函数调用 :http://localhost:xxxx/myProject/odata/SomeModels/MyNamespace.MyCustomFunction(parameterA=123,parameterB=123)
  • 本机 odata GET 调用 :http://localhost:xxxx/myProject/odata/SomeModels
  • 原生网页 API 获取调用:http://localhost:xxxx/myProject/api/SomeOtherModel?parameterC=123

我的网络 api 控制器 :

public class SomeOtherModelsController : ApiController
{
public IHttpActionResult Get(int parameterC)
{
// ...
return Ok(/* some result */);
}
[HttpPost]
public IHttpActionResult Post(SomeOtherModel model)
{
// ...
return Ok(/* some result */);
}
}

我的数据控制器:

public class SomeModelController : ODataController
{
[EnableQuery]
public IHttpActionResult Get()
{
// ...
return Ok(/* some result*/);
}
[HttpGet]
[EnableQuery]
public IHttpActionResult MyCustomFunction(int parameterA, int parameterB)
{
// ...
return Ok(/* some result */);
}
[HttpGet]
[EnableQuery]
public IHttpActionResult AnotherCustomFunction()
{
// ...
return Ok(/* some result */);
}
}

下面是 Web API 配置:

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);

和 OData 配置:

var builder = new ODataConventionModelBuilder
{
Namespace = "MyNamespace"
};
builder.EntitySet<SomeModelModel>("SomeModels");
var anotherCustomFunction = builder.EntityType<SomeModelModel>().Collection.Function("AnotherCustomFunction");
anotherCustomFunction.Returns<SomeResultValue>();
var myCustomFunction = builder.EntityType<SomeModel>().Collection.Function("MyCustomFunction");
myCustomFunction.Parameter<int>("parameterA");
myCustomFunction.Parameter<int>("parameterB");
myCustomFunction.ReturnsFromEntitySet<SomeModelModel>("SomeModels");

这里提出的一个可能的解决方案是将<modules runAllManagedModulesForAllRequests="true" />添加到web.config文件中的<system.webServer>

<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>

事实证明,添加此模块使得不需要System.Web.Handlers.TransferRequestHandler处理程序的存在。

因此,以下 system.webServer 配置足以处理 api 查询和自定义 OData 函数查询:

<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<remove name="OPTIONSVerbHandler"/>
<remove name="TRACEVerbHandler"/>
</handlers>
</system.webServer>

尽管如此,我对这个解决方案并不满意,因为我不太确切地知道<modules runAllManagedModulesForAllRequests="true" />的影响。

从我之前的回答开始,我创建了一个新模型(AnotherModel(和一个新的ApiController(OtherModelsController(。

另一个模型.cs

namespace DemoOdataFunction.Models
{
public class AnotherModel
{
public int Id { get; set; }
public int MyInt { get; set; }
public string MyString { get; set; }
}
}

另一个模型控制器.cs

namespace DemoOdataFunction.Controllers
{
public class AnotherModelsController : ApiController
{
public IHttpActionResult Get(int parameterC)
{
// ...
return Ok();
}
public IHttpActionResult Get()
{
// ...
return Ok("Ok");
}
[HttpPost]
public IHttpActionResult Post(AnotherModel model)
{
// ...
return Ok();
}
}
}

无需任何其他更改,API 和 OData 控制器都可以工作。

GET
http://localhost:4186/api/AnotherModels?parameterC=1
GET
http://localhost:4186/api/AnotherModels 
Post
http://localhost:4186/api/AnotherModels
{
"Id" : 1,
"MyInt" : 2,
"MyString" : "Hello"
}
GET
http://localhost:4186/odata/TestModels/MyNamespace.MyFunction(parA=1,parB=2)

我也尝试将 web.config 的"路径"设置更改为 *,但这没关系。 我建议您从头开始创建一个新项目并将其与您的项目进行比较。

最新更新