The remote server returned an error: (405) Method Not Allowed. WCF REST Service
Solution 1
First thing is to know the exact URL for your REST Service. Since you have specified http://localhost:2517/Service1/Create
now just try to open the same URL from IE and you should get method not allowed as your Create
Method is defined for WebInvoke and IE does a WebGet.
Now make sure that you have the SampleItem in your client app defined in the same namespace on your server or make sure that the xml string you are building has the appropriate namespace for the service to identify that the xml string of sample object can be deserialized back to the object on server.
I have the SampleItem defined on my server as shown below:
namespace SampleApp
{
public class SampleItem
{
public int Id { get; set; }
public string StringValue { get; set; }
}
}
The xml string corresponding to my SampleItem is as below:
<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>
Now i use the below method to perform a POST to the REST service :
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;
}
Now i call the above method as shown:
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);
I have the SampleItem object defined in the client side as well. If you want to build the xml string on the client and pass then you can use the below method:
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;
}
And the call to the above method would be as shown below:
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);
NOTE: Just make sure that your URL is correct
Solution 2
Are you running WCF application for the first time?
run below command to register wcf.
"%WINDIR%\Microsoft.Net\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe" -r
Solution 3
After spending 2 days on this, using VS 2010 .NET 4.0, IIS 7.5 WCF and REST with JSON ResponseWrapped, I finally cracked it by reading from "When investigating further..." here https://sites.google.com/site/wcfpandu/useful-links
The Web Service Client code generated file Reference.cs doesn't attribute the GET
methods with [WebGet()]
, so attempts to POST
them instead, hence the InvalidProtocol, 405 Method Not Allowed. Problem is though, this file is regenerated when ever you refresh the service reference, and you also need a dll reference to System.ServiceModel.Web
, for the WebGet attribute.
So I've decided to manually edit the Reference.cs file, and keep a copy. Next time I refresh it, I'll merge my WebGet()s
back in.
The way I see it, it's a bug with svcutil.exe not recognising that some of the service methods are GET
and not just POST
, even though the WSDL and HELP that the WCF IIS web service publishes, does understand which methods are POST
and GET
??? I've logged this issue with Microsoft Connect.
Praneeth
I am a developer interested in exploring better ways to code.
Updated on August 19, 2020Comments
-
Praneeth over 3 years
This question is already asked elsewhere but those things are not the solutions for my issue.
This is my service
[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(); }
I have this code to call the above service
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();
I get an exception at the last line:
The remote server returned an error: (405) Method Not Allowed. Not sure why this is happening i tried changing the host from VS Server to IIS also but no change in result. Let me know if u need more information
-
Praneeth about 12 yearsI am getting The remote server returned an error: (405) Method Not Allowed.
-
Rajesh about 12 yearsHow is your service hosted? Do you have an entry in the global.asax. Also check if you have the help page enabled and from it try to find the url for the method you are trying to post and see that the url is correct
-
Praneeth about 12 yearshelp is working i can see the services in the browser and get is working in the browser. Service is hosted through VS Server and I have routes registered in the global.asax
-
Rajesh about 12 yearsCan you remove the empty URITemplate attribute and see if that works. Also your help page would give the URL for the CREATE method during POST
-
Praneeth about 12 yearspage is giving create url during help. I removed URi Template but still i get a 405 exception
-
Rajesh about 12 yearsCan you use just that without any Create in your URI?
-
Praneeth about 12 yearsI dont have create in the URI