Ravi Rajindu
Ravi Rajindu

Reputation: 390

ASP.NET Web API - 405 (Method Not Allowed)

When I test my API with postman, It works well. But when I call API from Client application It gives 405 - Method Not Allowed error. And also if I remove [Authorize] from controller it works with client application too. I have tried almost everything in the stack overflow and also other sites, But still couldn't find the correct solution.

story - I want to create a separate client application using only Jquery and html. And it should consume an API created with .NET Web API. And API is secured with OWIN.

call from Client -

$.ajaxSetup({
        headers: {
            'Authorization': authHeaders
        }
    });

    this.$.get('http://localhost:62461/api/member/GetMember', function (response, status, jqxhr) {
        alert('ok');
    });

API web.config -

    <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
        <add name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS, PUT, DELETE" />
      </customHeaders>
    </httpProtocol>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="FormsAuthentication" />

      <remove name="WebDAVModule"/>
      <remove name="UrlRoutingModule"/>
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </modules>

    <handlers accessPolicy="Read, Script">
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />          
      <remove name="WebDAV" />

      <add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web,Version=2.0.0.0, Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a"/>
      <remove name="ExtensionlessUrl-Integrated-4.0" />
      <add name="ExtensionlessUrl-Integrated-4.0"
           path="*."
           verb="GET,HEAD,POST,DEBUG,DELETE,PUT"
           type="System.Web.Handlers.TransferRequestHandler"
           preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>

API Startup.cs -

public void Configuration(IAppBuilder app)
{
    ConfigureAuth(app);
    app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.UseCookieAuthentication(new CookieAuthenticationOptions());
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

    PublicClientId = "self";

    OAuthOptions = new OAuthAuthorizationServerOptions
    {
        TokenEndpointPath = new PathString("/Token"),
        Provider = new ApplicationOAuthProvider(PublicClientId),
        AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
        // In production mode set AllowInsecureHttp = false
        AllowInsecureHttp = true
    };
    app.UseOAuthAuthorizationServer(OAuthOptions); 
}

Method -

[RoutePrefix("api/Member")]
[Authorize]
public class MemberController : ApiController
{
    [Route("GetMember")]
    [HttpGet]        
    public string GetMember()
    {            
        return "Member 1";
    }
}

Upvotes: 0

Views: 989

Answers (2)

SharmaPattar
SharmaPattar

Reputation: 2664

I think pre-flight request will be your problem. Browser will not allow to access to 3rd party domains by default. Either use JSONP in your jquery or enable CORS in your API. In your HTTP config section use,

config.EnableCors();

Otherwise decorate your controller with

[EnableCors(origins: "http://api name.com", headers: "*", methods: "*")]

To use these methods you need to install package from nuget,

Microsoft.AspNet.WebApi.Cors

Please make sure [Authorize] attribute. From your comment this one is the culprit. One thing you need to make sure is the return response from this function should include all headers that the api framework generates, like header related to 'Access-Control-Allow-Origin'. This header should present there to choose the browser to initiate the original request after preflight. So your preflight request response doesn't contains the allow origin related information. Please make sure that is presented or not. You can use fiddler or any proxy client. So actually from the browser you can see 2 requests one for preflight and one for the original request. I think your preflight request response header is not contains the relevant information.

Upvotes: 0

Saurabh Solanki
Saurabh Solanki

Reputation: 2204

I had the same exception. My problem was that I had used wrong namespace:

using System.Web.Mvc; // Wrong namespace for HttpGet attribute !!!!!!!!!
    [HttpGet]
    public string Blah()
    {
        return "blah";
    }

and that should be :

 using System.Web.Http; // Correct namespace for HttpGet attribute !!!!!!!!!
[HttpGet]
public string Blah()
{
    return "blah";
}

that solves my exception. see if it helps to you..

Upvotes: 2

Related Questions