Reputation: 171
I have a Web Api controller. It behaves very strange. When I use PostMan I can access the POST method on the Web Api but when I use HttpWebRequest from .net it returns (405) Method Not Allowed. I put the Web Api code here:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
namespace MyProject.Controllers
{
public class TestController : ApiController
{
[HttpPost]
public int buy(OrderResult value)
{
try
{
if (value.InvoiceDate != null && value.Result == 1)
{
return 0;
}
}
catch{}
return -1;
}
}
public class OrderResult
{
public int Result { get; set; }
public long InvoiceNumber { get; set; }
public string InvoiceDate { get; set; }
public long TimeStamp { get; set; }
}
}
Here is my WebApiConfig.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace MyProject
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { action = RouteParameter.Optional, id = RouteParameter.Optional }
);
}
}
}
This is how I send the POST request from another .NET project:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
namespace MyProject.Controllers
{
public static class WebReq
{
public static string PostRequest(string Url, string postParameters)
{
try
{
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(Url);
myReq.Method = "POST";
myReq.Timeout = 30000;
myReq.Proxy = null;
byte[] postData = Encoding.UTF8.GetBytes(postParameters);
myReq.ContentLength = postData.Length;
myReq.ContentType = "application/x-www-form-urlencoded";
using (Stream requestWrite = myReq.GetRequestStream())
{
requestWrite.Write(postData, 0, postData.Length);
requestWrite.Close();
using (HttpWebResponse webResponse = (HttpWebResponse)myReq.GetResponse())
{
if (webResponse.StatusCode == HttpStatusCode.OK)
{
using (Stream str = webResponse.GetResponseStream())
{
using (StreamReader sr = new StreamReader(str))
{
return sr.ReadToEnd();
}
}
}
return null;
}
}
}
catch (Exception e)
{
var message = e.Message;
return null;
}
}
}
}
I already added the following code in my web.config:
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
It is strange because I can send POST request successfully from PostMan. The PostMan send this code to the API.
POST /api/Test/buy HTTP/1.1
Host: domain.com
Cache-Control: no-cache
Postman-Token: 9220a4e6-e707-5c5f-ea61-55171a5dd95f
Content-Type: application/x-www-form-urlencoded
InvoiceDate=28012016&Result=1
I will appreciate any suggestion to solve the problem.
Upvotes: 14
Views: 35598
Reputation: 109
In my case I had a physical folder inside the project with the same name as the route (ex. sandbox) and any POST request was intercepted by the static files handler in IIS (obviously), instead of the WebAPI runtime.
Getting a misleading 405 error instead of the more expected 404, was the reason it took me some time to troubleshoot.
Not easy to fall-into this, but is possible. Hope it helps someone.
Upvotes: 1
Reputation: 480
I know this is an old post, but maybe this might help someone else. I just had a similar issue, getting a 405 error "Get not allowed" when I was clearly doing a post in postman. Turned out, I was submitting to the URL using http instead of https. Changing to https fixed it.
Upvotes: 20
Reputation: 171
I found the solution.
I checked the request by Fiddler.When I send a POST request to API it automatically redirect to the same address with this new parameter AspxAutoDetectCookieSupport=1
How to remove AspxAutoDetectCookieSupport=1
Finally I changed the cookieless="AutoDetect"
in web.config to cookieless="UseCookies"
and the problem solved.
Upvotes: 3
Reputation: 1259
Catch your request with fiddler or something similar, you are probably sending "OPTIONS" method.
That's related to CORS, so I think solution for you will be to Enable Cors on WebAPI
http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
Upvotes: -2
Reputation: 33118
byte[] postData = Encoding.UTF8.GetBytes(postParameters);
myReq.ContentLength = postData.Length;
myReq.ContentType = "application/x-www-form-urlencoded";
using (Stream requestWrite = myReq.GetRequestStream())
{
requestWrite.Write(postData, 0, postData.Length);
You're most likely not sending a proper x-www-form-urlencoded request. You're likely not encoding the data properly from whatever is passed in as postParameters. See Post form data using HttpWebRequest
Since you're not generating a valid OrderResult object according to x-www-form-urlencoded, the route selector does not select your Buy
action. This is why you get POST is not allowed.
You would likely get to the controller if you changed OrderResult value = null
as it is now an optional parameter. However this isn't what you want, unless you're going to have a weird controller that behaves like:
Buy(OrderResult value = null)
{
if(value== null)
value = MyCustomDeserializeFromRequestBody(RequestContext)
...
}
Ultimately you just really shouldn't use this class there are much better constructs for modern development https://stackoverflow.com/a/31147762/37055 https://github.com/hhariri/EasyHttp off the top of my head
Upvotes: 2