【问题标题】:The remote server returned an error: (405) Method Not Allowed. WCF REST Service远程服务器返回错误:(405) Method Not Allowed。 WCF REST 服务
【发布时间】:2012-04-13 02:48:06
【问题描述】:

这个问题已经在别处问过了,但这些东西不是我的问题的解决方案。

这是我的服务

[WebInvoke(UriTemplate = "", Method = "POST")]
public SampleItem Create(SampleItem instance)
{
    // TODO: Add the new instance of SampleItem to the collection
    // throw new NotImplementedException();
    return new SampleItem();
}

我有这段代码可以调用上面的服务

XElement data = new XElement("SampleItem",
                             new XElement("Id", "2"),
                             new XElement("StringValue", "sdddsdssd")
                           ); 

System.IO.MemoryStream dataSream1 = new MemoryStream();
data.Save(dataSream1);

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:2517/Service1/Create");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
// You need to know length and it has to be set before you access request stream
request.ContentLength = dataSream1.Length;

using (Stream requestStream = request.GetRequestStream())
{
    dataSream1.CopyTo(requestStream);
    byte[] bytes = dataSream1.ToArray();
    requestStream.Write(bytes, 0, Convert.ToInt16(dataSream1.Length));
    requestStream.Close();
}

WebResponse response = request.GetResponse();

最后一行出现异常:

远程服务器返回错误:(405) Method Not Allowed。不知道为什么会发生这种情况,我也尝试将主机从 VS Server 更改为 IIS,但结果没有变化。如果您需要更多信息,请告诉我

【问题讨论】:

  • 你的路线是什么样的?
  • 请添加您正在使用的任何绑定配置配置/代码。
  • 您将 contenttype 设置为 "application/x-www-form-urlencoded" 。但是您正在发送 xml 数据。能否将内容类型设置为“application/xml”
  • 我没有任何绑定配置

标签: c# .net wcf rest


【解决方案1】:

首先要知道 REST 服务的确切 URL。由于您已指定 http://localhost:2517/Service1/Create,现在只需尝试从 IE 打开相同的 URL,您应该得到不允许的方法,因为您的 Create 方法是为 WebInvoke 定义的,而 IE 会执行 WebGet。

现在确保您的客户端应用程序中的 SampleItem 定义在服务器上的同一命名空间中,或者确保您正在构建的 xml 字符串具有适当的命名空间,以便服务识别样本对象的 xml 字符串可以被反序列化回服务器上的对象。

我在我的服务器上定义了 SampleItem,如下所示:

namespace SampleApp
{
    public class SampleItem
    {
        public int Id { get; set; }
        public string StringValue { get; set; }            
    }    
}

我的SampleItem对应的xml字符串如下:

<SampleItem xmlns="http://schemas.datacontract.org/2004/07/SampleApp" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Id>6</Id><StringValue>from client testing</StringValue></SampleItem>

现在我使用以下方法对 REST 服务执行 POST:

private string UseHttpWebApproach<T>(string serviceUrl, string resourceUrl, string method, T requestBody)
        {
            string responseMessage = null;
            var request = WebRequest.Create(string.Concat(serviceUrl, resourceUrl)) as HttpWebRequest;
            if (request != null)
            {
                request.ContentType = "application/xml";
                request.Method = method;
            }

            //var objContent = HttpContentExtensions.CreateDataContract(requestBody);
            if(method == "POST" && requestBody != null)
            {
                byte[] requestBodyBytes = ToByteArrayUsingDataContractSer(requestBody);
                request.ContentLength = requestBodyBytes.Length;
                using (Stream postStream = request.GetRequestStream())
                    postStream.Write(requestBodyBytes, 0, requestBodyBytes.Length);                    
            }

            if (request != null)
            {
                var response = request.GetResponse() as HttpWebResponse;
                if(response.StatusCode == HttpStatusCode.OK)
                {
                    Stream responseStream = response.GetResponseStream();
                    if (responseStream != null)
                    {
                        var reader = new StreamReader(responseStream);

                        responseMessage = reader.ReadToEnd();                        
                    }
                }
                else
                {
                    responseMessage = response.StatusDescription;
                }
            }
            return responseMessage;
        }

private static byte[] ToByteArrayUsingDataContractSer<T>(T requestBody)
        {
            byte[] bytes = null;
            var serializer1 = new DataContractSerializer(typeof(T));            
            var ms1 = new MemoryStream();            
            serializer1.WriteObject(ms1, requestBody);
            ms1.Position = 0;
            var reader = new StreamReader(ms1);
            bytes = ms1.ToArray();
            return bytes;
        }

现在我调用上面的方法如图:

SampleItem objSample = new SampleItem();
objSample.Id = 7;
objSample.StringValue = "from client testing";
string serviceBaseUrl = "http://localhost:2517/Service1";
string resourceUrl = "/Create";
string method="POST";

UseHttpWebApproach<SampleItem>(serviceBaseUrl, resourceUrl, method, objSample);

我在客户端也定义了 SampleItem 对象。如果您想在客户端构建xml字符串并通过,那么您可以使用以下方法:

private string UseHttpWebApproach(string serviceUrl, string resourceUrl, string method, string xmlRequestBody)
            {
                string responseMessage = null;
                var request = WebRequest.Create(string.Concat(serviceUrl, resourceUrl)) as HttpWebRequest;
                if (request != null)
                {
                    request.ContentType = "application/xml";
                    request.Method = method;
                }

                //var objContent = HttpContentExtensions.CreateDataContract(requestBody);
                if(method == "POST" && requestBody != null)
                {
                    byte[] requestBodyBytes = ASCIIEncoding.UTF8.GetBytes(xmlRequestBody.ToString());
                    request.ContentLength = requestBodyBytes.Length;
                    using (Stream postStream = request.GetRequestStream())
                        postStream.Write(requestBodyBytes, 0, requestBodyBytes.Length);                    
                }

                if (request != null)
                {
                    var response = request.GetResponse() as HttpWebResponse;
                    if(response.StatusCode == HttpStatusCode.OK)
                    {
                        Stream responseStream = response.GetResponseStream();
                        if (responseStream != null)
                        {
                            var reader = new StreamReader(responseStream);

                            responseMessage = reader.ReadToEnd();                        
                        }
                    }
                    else
                    {
                        responseMessage = response.StatusDescription;
                    }
                }
                return responseMessage;
            }

对上述方法的调用如下所示:

string sample = "<SampleItem xmlns=\"http://schemas.datacontract.org/2004/07/XmlRestService\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><Id>6</Id><StringValue>from client testing</StringValue></SampleItem>";   
string serviceBaseUrl = "http://localhost:2517/Service1";
string resourceUrl = "/Create";
string method="POST";             
UseHttpWebApproach<string>(serviceBaseUrl, resourceUrl, method, sample);

注意:请确保您的网址正确

【讨论】:

  • 我得到远程服务器返回错误:(405)方法不允许。
  • 您的服务是如何托管的?你在 global.asax 中有一个条目吗?还要检查您是否启用了帮助页面,并从中尝试查找您尝试发布的方法的 url,并查看该 url 是否正确
  • 帮助正在运行,我可以在浏览器中看到服务并且获取正在浏览器中运行。服务通过 VS Server 托管,我在 global.asax 中注册了路由
  • 您能否删除空的 URITemplate 属性,看看是否有效。此外,您的帮助页面将在 POST 期间提供 CREATE 方法的 URL
  • 页面在帮助期间提供创建 URL。我删除了 URi 模板,但仍然收到 405 异常
【解决方案2】:

您是第一次运行 WCF 应用程序吗?

运行下面的命令来注册 wcf。

"%WINDIR%\Microsoft.Net\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe" -r

【讨论】:

    【解决方案3】:

    在这上面花了 2 天时间,使用 VS 2010 .NET 4.0、IIS 7.5 WCF 和 REST 和 JSON ResponseWrapped,我终于通过阅读“进一步调查时...”https://sites.google.com/site/wcfpandu/useful-links

    来破解它

    Web 服务客户端代码生成的文件 Reference.cs 没有将 GET 方法与 [WebGet()] 关联,因此尝试将 POST 他们改为,因此 InvalidProtocol, 405 Method Not Allowed。 问题是,当您刷新服务引用时,此文件会重新生成,并且您还需要一个对 System.ServiceModel.Web 的 dll 引用,用于 WebGet 属性。

    所以我决定手动编辑 Reference.cs 文件,并保留一份副本。下次我刷新它时,我会将我的WebGet()s 合并回来。

    在我看来,这是一个 svcutil.exe 的错误,它没有识别出某些服务方法是 GET 而不仅仅是 POST,即使 WCF IIS Web 服务发布的 WSDL 和 HELP 确实如此了解POSTGET分别是哪些方法???我已经用 Microsoft Connect 记录了这个问题。

    【讨论】:

      【解决方案4】:

      当它发生在我身上时,我只是简单地添加了post这个词 到函数名,它解决了我的问题。也许它也会对你们中的一些人有所帮助。

      【讨论】:

        【解决方案5】:

        在我遇到的情况下,还有另一个原因:底层代码试图执行WebDAV PUT。 (如果需要,此特定应用程序可配置为启用此功能;我不知道该功能已启用,但未设置必要的 Web 服务器环境。

        希望这对其他人有帮助。

        【讨论】:

          【解决方案6】:

          我已经解决了这个问题,因为您的服务是通过带有用户名和密码的登录凭据来保护的,请尝试在请求中设置用户名和密码,它将起作用。祝你好运!

          【讨论】:

            猜你喜欢
            • 2014-08-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-12-02
            • 2012-10-14
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多