删除不工作在 WCF 休息服务抛出 (405) 方法不允许

Posted

技术标签:

【中文标题】删除不工作在 WCF 休息服务抛出 (405) 方法不允许【英文标题】:Delete not Working in WCF rest service throwing (405) Method Not Allowed 【发布时间】:2012-01-13 07:25:46 【问题描述】:

我创建了 WCF RESTful 服务,它使用简单的数据库,只是尝试处理放置、获取、发布和删除项目。现在发布,放置和获取正在工作。但是删除不起作用。一些论坛告诉我需要禁用 WebDAV 模块。我这样做了,然后我让 PUT 开始工作。但我无法让 DELETE 工作。每当我通过我的服务调用 DELETE 动词时,我都会收到以下错误:

远程服务器返回意外响应:(405) Method Not Allowed。

谁能帮我解决这个问题?

【问题讨论】:

【参考方案1】:

*** 上似乎已经有一些类似的问题:

WCF Service 405 Method Not Allowed Exception

WCF The request failed with HTTP status 405: Method Not Allowed

WCF Service Returning "Method Not Allowed"

希望其中一位能有所帮助。

【讨论】:

【参考方案2】:

我在客户端使用WebChannelFactory 方法来使用REST 服务。我使用普通的“添加服务参考”方法创建了服务参考。这不会添加[WebGet(UriTemplate = "/")]

在我为客户端代理类上的所有操作添加这些之后,就像服务合同一样,它开始工作了。

【讨论】:

【参考方案3】:

我还没有找到一个全面的答案来解决 PUT 和 DELETE 被覆盖并在其他任何地方返回 405 以获得宁静的 WCF 服务,所以我将在此处发布。

通过角色管理器(在服务器上)或通过添加/删除 Windows 功能从机器上卸载 WebDAV 即可轻松解决此问题。如果这是可以接受的方法,您现在可以停止阅读。

这里通常推荐的修复方法是简单地从您的站点中删除 WebDAV 模块,将以下内容附加到您的 web.config:

  <system.webServer>
        <modules>
            <remove name="WebDAVModule" />
        </modules>
  </system.webServer>

这里的问题是,现在您的 WCF 应用程序根本无法知道如何处理 PUT 和 DELETE。所以为了解决这个问题,一些解决方案建议进行以下修改:

<modules runAllManagedModulesForAllRequests="true">
 <system.webServer>
       <modules>
           <remove name="WebDAVModule" />
       </modules>
 </system.webServer>

这对大多数人来说可能是令人满意的,但我不喜欢让我们的服务在不必要的时候为每次调用无用地加载所有内容的想法。因此,我通过手动将无扩展 URL 处理程序映射到所有 HTTP 动词来稍微改进了该方法(可能可以改进为必要的)

  <system.webServer>
        <modules>
            <remove name="WebDAVModule" />
        </modules>
        <handlers>
            <remove name="WebDAV" />
            <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
            <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
        </handlers>
  </system.webServer>

我只在 R2 64 和 7 64 上测试过这个,所以 ymmv。但希望这会有所帮助。

【讨论】:

【参考方案4】:

向 Web.config 文件添加代码

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </configSections>
    <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
    </appSettings>
    <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5" />
    </system.web>
    <system.serviceModel>
        <behaviors >
            <serviceBehaviors>
                <behavior  name="http">
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                </behavior>
            </serviceBehaviors>
            <endpointBehaviors>
                <behavior name="www">
                    <webHttp/>
                </behavior>
            </endpointBehaviors>
        </behaviors>
        <protocolMapping>
            <add binding="basicHttpsBinding" scheme="https" />
        </protocolMapping>
        <services>
            <service behaviorConfiguration="http" name="REST.CRUD.Alternativ">
                <endpoint address=""
                                    binding="webHttpBinding"
                                    behaviorConfiguration="www"
                                    contract="REST.CRUD.IAlternativ"
                                    bindingConfiguration="rest">
                </endpoint>
                <endpoint address="mex"
                                    binding="mexHttpBinding"
                                    contract="IMetadataExchange">
                </endpoint>
            </service>
        </services>
        <bindings>
            <webHttpBinding>
                <binding allowCookies="true" name="rest">
                    <security mode="None"></security>
                </binding>
            </webHttpBinding>
        </bindings>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true" />
        <directoryBrowse enabled="true" />
        <security>
            <requestFiltering>
                <verbs>
                    <add verb="GET" allowed="true" />
                    <add verb="POST" allowed="true" />
                    <add verb="DELETE" allowed="true" />
                    <add verb="PUT" allowed="true" />
                </verbs>
            </requestFiltering>
        </security>
    </system.webServer>
    <entityFramework>
        <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
            <parameters>
                <parameter value="v11.0" />
            </parameters>
        </defaultConnectionFactory>
        <providers>
            <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
        </providers>
    </entityFramework>
    <connectionStrings>
        <add name="KendoDB" connectionString="Data Source=(localDB)\v11.0;Initial Catalog=Kendo;Integrated Security=True;Pooling=False" providerName="System.Data.SqlClient" />
    </connectionStrings>
</configuration>

PersonDTO

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;

namespace REST.CRUD

    public class PersonDTO
    
        public int ID  get; set; 
        public string firstName  get; set; 
        public string lastName  get; set; 
    

    public class KendoContext : DbContext
    
        public  KendoContext():base("KendoDB")
        public DbSet<PersonDTO> PersonDTOs  get; set; 
    

IAlternativ.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Web.Services;


namespace REST.CRUD

    [ServiceContract]
    public interface IAlternativ
    
        [WebInvoke(Method = "POST",
            BodyStyle = WebMessageBodyStyle.WrappedRequest,
            RequestFormat = WebMessageFormat.Json,
            ResponseFormat = WebMessageFormat.Json)]
        [OperationContract]
        List<PersonDTO> GetAll();

        [WebInvoke(Method = "GET",
            BodyStyle = WebMessageBodyStyle.WrappedRequest,
            RequestFormat = WebMessageFormat.Json,
            ResponseFormat = WebMessageFormat.Json)]
        [OperationContract]
        PersonDTO Get(int ID, string f, string l);

        [WebInvoke(Method = "DELETE", 
            BodyStyle = WebMessageBodyStyle.WrappedRequest,
            RequestFormat = WebMessageFormat.Json,
            ResponseFormat = WebMessageFormat.Json)]
        [OperationContract]
        String Delete(int ID, string f, string l);

        [WebInvoke(Method = "PUT", 
            BodyStyle = WebMessageBodyStyle.WrappedRequest,
            RequestFormat = WebMessageFormat.Json,
            ResponseFormat = WebMessageFormat.Json)]
        [OperationContract]
        String Update(int ID, string f, string l);
    

Alternativ.svc.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Web.Script.Services;
using System.Web.Services;


namespace REST.CRUD

    public class Alternativ : IAlternativ
    
        public List<PersonDTO> GetAll()
        
            var db = new KendoContext();
            return db.PersonDTOs.Select(c => c).ToList();
        

        public PersonDTO Get(int ID, string f, string l)
        
            var db = new KendoContext();
            return db.PersonDTOs.Where(c => c.ID == ID).Select(c => c).First();
        

        public String Delete(int ID, string f, string l)
        
            //Delete Code
            return "OK";
        

        public String Update(int ID, string f, string l)
        
            //Update Code
            return "OK";
        
    

[构建并运行 WCF 项目(F5)]。

将 jquery 添加到 DOM 以进行测试(粘贴到控制台)

(function() 
  if (! window.jQuery ) 
    var s = document.createElement('script');
    s.type = 'text/javascript';
    s.async = true;
    s.src = '//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js'; 
    (document.getElementsByTagName('head')[0] ||
      document.getElementsByTagName('body')[0]).appendChild(s);
  
());

向控制台添加功能

function POST()
$.ajax(
      type: "POST", //GET,POST,PUT or DELETE verb
      url: "/Alternativ.svc/GetAll", // Location of the service
      data: '"ID":"1"', //Data to be sent to server
      dataType: "json", // content type sent to server
      contentType: "application/json; charset=utf-8", //Expected data format from server
      processdata: false, //True or False
      success: function (response) 
        console.log(response);
      ,
      error: function (xhr, ajaxOptions, thrownError) 
        alert(xhr.statusText);
      
);

function GET()
$.ajax(
      type: "GET", //GET,POST,PUT or DELETE verb
      url: "/Alternativ.svc/Get", // Location of the service
      data: ID:1, //Data to be sent to server
      dataType: "json", // content type sent to server
      contentType: "application/json; charset=utf-8", //Expected data format from server
      processdata: true, //True or False
      success: function (response) 
        console.log(response);
      ,
      error: function (xhr, ajaxOptions, thrownError) 
        alert(xhr.statusText);
      
);

function DELETE()
$.ajax(
      type: "DELETE", //GET,POST,PUT or DELETE verb
      url: "/Alternativ.svc/Delete", // Location of the service
      data: '"ID":"1"', //Data to be sent to server
      dataType: "json", // content type sent to server
      contentType: "application/json; charset=utf-8", //Expected data format from server
      processdata: false, //True or False
      success: function (response) 
        console.log(response);
      ,
      error: function (xhr, ajaxOptions, thrownError) 
        alert(xhr.statusText);
      
);

function PUT()
$.ajax(
      type: "PUT", //GET,POST,PUT or DELETE verb
      url: "/Alternativ.svc/Update", // Location of the service
      data: '"ID":"1"', //Data to be sent to server
      dataType: "json", // content type sent to server
      contentType: "application/json; charset=utf-8", //Expected data format from server
      processdata: false, //True or False
      success: function (response) 
        console.log(response);
      ,
      error: function (xhr, ajaxOptions, thrownError) 
        alert(xhr.statusText);
      
);

调用函数

DELETE();
PUT();
GET();
POST();

【讨论】:

以上是关于删除不工作在 WCF 休息服务抛出 (405) 方法不允许的主要内容,如果未能解决你的问题,请参考以下文章

部署后 Socket.io 不工作 - 抛出错误 - 405(不允许)

使用 IIS 时方法不允许 405

WCF 请求失败,HTTP 状态为 405:不允许方法

Restful WCF IIS 7.5 405 方法不允许间歇

WCF 错误:405 方法不允许

WCF REST 服务返回 405:jQuery AJAX GET 不允许的方法