3

I have looked throw all StackOverflow, but didn`t find solution for my case I have 405 HttpStatusCode calling API/Regions/Create action Here is my baseController method:

 [HttpPost]
        public virtual IHttpActionResult Create([FromBody]T entity)
        {
            try
            {
                repository.Create(entity);

                return Ok(entity);
            }
            catch (HttpException e)
            {
                return new ExceptionResult(e, this);
            }
        }

RegionController.cs

public class RegionsController : BaseController<Region, RegionRepository>
{
    public RegionsController()
    { }
    public RegionsController(RegionRepository _repository)
    {
        RegionRepository repository = new RegionRepository();//_repository;
    }

    RegionRepository repository = new RegionRepository();

    [HttpGet]
    [Route("api/regions/{name}")]
    public IHttpActionResult Get(string name)
    {
        try
        {
            var region = repository.Get(name);

            return Ok(region);
        }
        catch (HttpException e)
        {
            return new ExceptionResult(e, this);
        }
    }
}

WebApi config:

      public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            // Configure Web API to use only bearer token authentication.
            // Web API configuration and services
            var cors = new EnableCorsAttribute("*", "*", "*");
            config.EnableCors(cors);


            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));


            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

Global.asax:

    public class WebApiApplication : System.Web.HttpApplication
        {
            private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
            protected void Application_Start()
            {
                logger.Info("Application Start");
                AreaRegistration.RegisterAllAreas();
                GlobalConfiguration.Configure(WebApiConfig.Register);
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);

               //GlobalConfiguration.Configuration.MessageHandlers.Add(new CorsHandler());
            }

            //protected void Application_BeginRequest(object sender, EventArgs e)
            //{
            //    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
            //    //if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
            //    //{
            //        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE");

            //        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
            //        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
            //        HttpContext.Current.Response.End();
            // //   }
            //}

            private void Application_Error(object sender, EventArgs e)
            {

                var lastException = Server.GetLastError();

                NLog.LogManager.GetCurrentClassLogger().Error(lastException);

            }


        }
}

and Web.Config:

      <system.web>
    <authentication mode="None" />
    <compilation debug="true" targetFramework="4.5.2" />
    <httpRuntime targetFramework="4.5.2" />
    <httpModules>
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
    </httpModules>
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
    </modules>
    <handlers>
      <remove name="WebDAV" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>

Any suggestions what might be wrong?

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197

3 Answers3

1

You should call API/Regions on your POST request, not API/Regions/Create, unless you specify API/Regions/Create in a Route attribute on the action. WebApi will know what method to search for to handle the request.

martennis
  • 882
  • 11
  • 20
  • 1
    You have a route `[Route("api/regions/{name}")]` as HttpGet route. I think the framework is matching the requested route first, then checks if POST is allowed, instead of first looking up all POST-available routes, then checking which route matches. – martennis Jul 18 '16 at 07:17
0

To get the framework to recognize the inherited attributes you need to override the DefaultDirectRouteProvider as outlined here

and used in an answer here

WebAPI controller inheritance and attribute routing

public class WebApiCustomDirectRouteProvider : DefaultDirectRouteProvider {
    protected override System.Collections.Generic.IReadOnlyList<IDirectRouteFactory>
        GetActionRouteFactories(System.Web.Http.Controllers.HttpActionDescriptor actionDescriptor) {
        // inherit route attributes decorated on base class controller's actions
        return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(inherit: true);
    }
}

and apply that to the web api configuration.

// Attribute routing. (with inheritance)
config.MapHttpAttributeRoutes(new WebApiCustomDirectRouteProvider());

Hope this helps

Community
  • 1
  • 1
Nkosi
  • 235,767
  • 35
  • 427
  • 472
0

Can you try changing the line to below in your web.config:

<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
Bhupinder Singh
  • 254
  • 2
  • 15