4

We are at the stage of deploying a project to our client's test server but unfortunately, we are receiving 405 errors every time our application tries to make calls to any of the Web Api methods we have made available.

My WebApi calls are defined as follows:

public class TourController : ApiController
{
  [HttpPost]
  public JsonCollection RequestTours([FromBody] DateRequest request){
    // Implementation goes here
  }

  [HttpPost]
  public GroupTour RequestTour([FromBody] int request){
    // Implementation goes here
  }
}

My WebApi routing is as follows:

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }

These calls work as defined when run locally though Visual Studio with no ammendments however, when we place them on our client's IIS test server we are consistently receiving 405 errors when calling the methods via AJAX (primary method) or via URL.

As suggested in other posts, we have tried defining the following in system.webServer:

<modules runAllManagedModulesForAllRequests="true" />
    <handlers>
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>

We have also tried adding the following to no avail:

<modules runAllManagedModulesForAllRequests="true">
    <remove name="WebDAVModule"/> <!-- add this -->
</modules>

<handlers>
    <remove name="WebDAV" />
    ...
</handlers>

We are currently at a loss as we have tried most of the suggestions offered on similar Stack Overflow posts around the same subject. Any help or suggestions on this issue would be greatly appreciated!

N.B.

Just for the record, my calling method via Javascript / JQuery is doing the following:

function populateInstances(date) {
                var $container = $('#id-tour_4');
                $.ajax({
                    url: '/api/tour/requesttours',
                    type: 'POST',
                    data: { Date: date },
                    dataType: 'json',
                    success: function (data) {
                        var htmlstring = '';
                        $container.empty();
                        if (data.Results.length > 0) {
                            for (var i = 0; i < data.Results.length; i++) {
                                htmlstring += '<div class="book-title">' + data.Results[i].Name + '</div>';
                                htmlstring += '<div class="tour_select_list_div">';
                                htmlstring += '<ul class="tour_select_list">';
                                for (var j = 0; j < data.Results[i].Instances.length; j++) {
                                    htmlstring += '<li><label for="id-tour_4_' + j + '"><input id="id-tour_4_' + j + '" type="radio" value="' + data.Results[i].Instances[j].TourId + '" name="BookTour.Instance" data-availability="' + data.Results[i].Instances[j].Availability + '" data-adultprice="' + data.Results[i].Instances[j].AdultPrice + '" data-childprice="' + data.Results[i].Instances[j].ChildPrice + '">';
                                    htmlstring += data.Results[i].Instances[j].StartTime + ' - ' + data.Results[i].Instances[j].Title + '</label></li>';
                                }
                                htmlstring += '</ul>';
                                htmlstring += '</div>';
                            }
                        } else {
                            htmlstring += 'There are no tours departing on this date';
                        }
                        $container.append(htmlstring);
                    }
                });
            }
jezzipin
  • 4,110
  • 14
  • 50
  • 94
  • What kind of `ApplicationPool` is running the application in the customer environment? Specifically, what is the framework version and are you using `Integrated` or `Classic` pipeline? Also, which IIS version? And yet one more question, which http `verbs` are causing troubles? – user1429080 May 17 '16 at 08:50
  • Framework version is 4.5 and it is an integrated pipeline. I think. I don't know enough about that side of things to comment really. – jezzipin May 17 '16 at 08:52
  • You need to see how the application is deployed. Most likely your handlers for extensionless urls are being ignored. Possibly because the `ApplicationPool` is not correctly configured for your app... Or there may be other handler registered that interfere with the request. – user1429080 May 17 '16 at 09:15
  • I have same problem .tanks if you can help me https://stackoverflow.com/questions/46485219/http-405-errors-after-publishing-web-api-2-applications – mohsen Sep 30 '17 at 08:45

3 Answers3

1

Herewith, find a couple of options that might be of assistance in solving production problems

The check list:

  1. Try adding a [Route] attribute
 [HttpPost]
 [Route("api/tour/requesttours")]
 public JsonCollection RequestTours([FromBody] DateRequest request)
   You can try removing `[HttpPost]` when applying the `[Route]` attribute
  1. Ensure that CORS is enabled

  2. Check that you are using System.Web.Http with the HttpPost and not the Mvc namespace equivalent.

Conrad Lotz
  • 8,200
  • 3
  • 23
  • 27
0

Ensure your client method performs the actual ACTION VERB your endpoint is expecting.

That is to say that is your endpoint is a POST, your client must POST to it and not PUT.

Please confirm.

Sunny Okoro Awa
  • 523
  • 4
  • 9
  • My client method is doing the following: $.ajax({ url: '/api/tour/requesttours', type: 'POST', so definitely a post – jezzipin May 17 '16 at 09:10
0

This could be a firewall or loadbalancer issue. If your client follows a strict least privilege policy you may have to ensure that the actual verb is allowed on a firewall/loadbalancer layer. Can you let your sysadmin check that?

Can you else confirm that the request reaches your service? Do you have any logging (in your application or at least the IIS logs that notice every request to your site) which confirms that the request comes through? Did you already put a web debugging proxy like fiddler in between the communication to get more detailed Infos?

Jan Köhler
  • 5,817
  • 5
  • 26
  • 35