TechTotal
TechTotal

Reputation: 171

ASP.NET WebApi : (405) Method Not Allowed

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

Answers (5)

Panos Roditakis
Panos Roditakis

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

Paul Reedy
Paul Reedy

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

TechTotal
TechTotal

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

IMujagic
IMujagic

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

Chris Marisic
Chris Marisic

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

Related Questions