在 IIS 服务器上的 PUT API 调用期间未触发 Application_BeginRequest

Posted

技术标签:

【中文标题】在 IIS 服务器上的 PUT API 调用期间未触发 Application_BeginRequest【英文标题】:Application_BeginRequest not being fired during PUT API Calls on IIS Server 【发布时间】:2014-10-30 12:00:33 【问题描述】:

背景

我有一个带有 WebAPI 组件的 MVC 应用程序。我正在使用 jQuery 和 AJAX 从 WebAPI 传递和接收数据。我依靠在每次调用期间触发的 Application_BeginRequest 来执行一些平凡的任务。

问题

Application_BeginRequest 总是在对 WebAPI 的 GET 和 POST 调用中触发。但是,当我对 WebAPI 进行 PUT 调用时,Application_BeginRequest 确实 not 触发,导致应用程序无法运行任务。实际收到的是PUT调用,因为控制器中对应的方法正在执行。

我在我的 web.config 文件中启用了 PUT(如下)。如何启用 PUT 方法调用以触发 Application_BeginRequest 方法?

注意: Application_BeginRequest 在使用 IIS Express 时触发 PUT 调用,但在使用完整版 IIS 时不会触发。

项目:完整的项目可以在这里下载:BeginRequestFail.zip

Web.Config

<?xml version="1.0" encoding="utf-8"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.html" />
        <add namespace="System.Web.Optimization" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
  </system.web>
  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="PassThrough">
      <remove statusCode="404" subStatusCode="-1" />
      <remove statusCode="403" subStatusCode="-1" />
      <remove statusCode="500" subStatusCode="-1" />
      <error statusCode="404" path="/Error/404" responseMode="ExecuteURL" />
      <error statusCode="403" path="/Error/403" responseMode="ExecuteURL" />
      <error statusCode="500" path="/Error/500" responseMode="ExecuteURL" />
    </httpErrors>
    <validation validateIntegratedModeConfiguration="false" />
    <modules>
      <remove name="UrlRoutingModule-4.0" />
      <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
      <remove name="WebDAVModule"/>
    </modules>
    <handlers>
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="DotNetOpenAuth.Core" publicKeyToken="2780ccd10d57b246" />
        <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="DotNetOpenAuth.AspNet" publicKeyToken="2780ccd10d57b246" />
        <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
      </dependentAssembly>
        <dependentAssembly>
          <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
          <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
        </dependentAssembly>
      </assemblyBinding>
  </runtime>
</configuration>

Global.asax.cs

protected void Application_BeginRequest(object sender, EventArgs e) //Not triggered with PUT
        
            Application["BeginRequest"] = _Scounter++;
        

【问题讨论】:

IIS 中设置了什么托管管道模式? Managed Pipeline Mode设置为Integrated,.Net Framework为4.0。 什么版本的 IIS? 版本为IIS7和7.5 也许我遗漏了一些东西,但看起来您的 put 调用正在另一个应用程序上下文中完成。我对 WebAPI 不是很熟悉,但是您有一个单独的 api 应用程序类,没有请求事件处理程序。 【参考方案1】:

转到 IIS 功能模式 --> 单击处理程序映射 --> 滚动列表并找到无扩展 URL 处理程序 --> 检查该处理程序之前的所有处理程序,以查看是否有任何其他东西被注册到处理程序 PUT 请求从而劫持PUT 在它到达无扩展 url 处理程序之前。希望有帮助

【讨论】:

【参考方案2】:

您的代码有效。不确定您的计数器,所以我将其更改为:

public class MvcApplication : System.Web.HttpApplication

    public static int BeginRequestCounter = 0;

    protected void Application_BeginRequest(object sender, EventArgs e)
    
        BeginRequestCounter++;
    

(删除其他代码以指出我所做的更改)

<p>@BeginRequestFail.MvcApplication.BeginRequestCounter</p>

请记住,当您执行 AJAX 调用时,页面上的计数器不会更新 - 页面刷新后,您会看到计数器已正确递增。

不确定为什么要在 Mvc 项目中引用 WebApi 项目?我要么将它们分开,要么将它们合二为一,以避免任何奇怪。就我个人而言,我的 WebApi 将是完全独立的,因为它不应该与任何其他网络应用程序有任何关系 - 至少这是我设计数据 API 的方式。

【讨论】:

以上是关于在 IIS 服务器上的 PUT API 调用期间未触发 Application_BeginRequest的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Web API - 不允许 PUT 和 DELETE 动词 - IIS 8

请求部署在 IIS7.5 上的 REST 服务的 Put/Post/Delete 操作发生 HTTP Error 405.0 - Method Not Allowed 错误之解决

在破坏调用期间从另一个线程未定义的行为调用对象上的方法?

IIS7.5上的REST服务的Put操作发生HTTP Error 405.0 - Method Not Allowed 解决方法

IIS 7.5 405 方法不允许从 StaticFileModule 进行 PUT

如何在 IIS 中授予 Web api 应用程序写入权限?