【问题标题】:How to setup IIS TransferRequestHandler path for both WebApi 2 and OData Controllers?如何为 WebApi 2 和 OData 控制器设置 IIS TransferRequestHandler 路径?
【发布时间】:2018-01-17 02:45:54
【问题描述】:

我希望正确配置 System.Web.Handlers.TransferRequestHandler path 属性以处理 both 到 WebApi REST 操作 ODataController 自定义 功能的路由在 ASP.NET WebApi 2 项目中。

我的web.config 文件处理程序配置如下,以支持自定义 ODataController 函数调用 (see my related question here):

    <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 - 内部服务器错误
内部服务器错误

详细错误信息:
模块 ManagedPipelineHandler
通知 ExecuteRequestHandler
Handler ExtensionlessUrlHandler -Integrated-4.0
错误代码 0x800703e9

如果我将 TransferRequestHandler path 设置为 *. as suggested here WebApi 请求得到正确解决,但 ODataController 请求最终无法通过 HTTP 400 找到:

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

详细错误信息:
模块 IIS Web Core
通知 MapRequestHandler
处理程序 尚未确定
错误代码 0x80070002

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

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

  • 自定义odata函数调用: http://localhost:xxxx/myProject/odata/SomeModels/MyNamespace.MyCustomFunction(parameterA=123,parameterB=123)
  • 本机 odata GET 调用: http://localhost:xxxx/myProject/odata/SomeModels
  • 本机 web api GET 调用: 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 */);
        }
}

我的 odata 控制器:

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");

【问题讨论】:

  • 您好 John-Philip,您可以发布您的 Api 控制器、WebApiConfig 和 http 请求吗?
  • 嗨@FrancescoBozzi,为了清楚起见,我编辑了我的答案。尽管如此,我已经找到了一个解决方案 (see my answer),而我更喜欢一个更具体的解决方案。

标签: c# asp.net asp.net-web-api asp.net-web-api2


【解决方案1】:

一个可能的解决方案as proposed here 是在web.config 文件中将&lt;modules runAllManagedModulesForAllRequests="true" /&gt; 添加到&lt;system.webServer&gt;

 <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>

尽管如此,我对这个解决方案并不满意,因为我不知道&lt;modules runAllManagedModulesForAllRequests="true" /&gt; 会产生什么影响。

【讨论】:

    【解决方案2】:

    从我之前的answer开始,我创建了一个新模型(AnotherModel)和一个新的ApiController(AnotherModelsController)

    另一个模型.cs

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

    AnotherModelsController.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 的“路径”设置更改为 *,但这很好。 我建议您从头开始创建一个新项目并与您的项目进行比较。

    【讨论】:

      猜你喜欢
      • 2015-09-19
      • 2016-05-11
      • 1970-01-01
      • 2014-09-29
      • 2017-06-17
      • 1970-01-01
      • 1970-01-01
      • 2012-11-14
      • 2015-04-02
      相关资源
      最近更新 更多