Search code examples
asp.net-mvcasp.net-mvc-4iis-7asp.net-web-api

Web Api calls return 404 on Server


I'm aware this has been asked a lot of times on this site and others, but no solution i've seen so far is working, so here I am.

I have some web api routes set up in an mvc 4 project. Here's a sample:

routes.MapHttpRoute(name: null, routeTemplate: "Client/Accounts/Save", defaults: new { controller = "AccountsApi", action = "SaveAccount" });

Corresponding to the following controller and action:

public class AccountsApiController : ApiController
{
    [HttpPost]
    public object SaveAccount([FromBody] Account input)
    {
      .....

This works when running in the built in VS web server, and on a local (windows 7) installation of IIS7.5, with no fancy stuff done to it, but gives a 404 when running in IIS7 on Server 2008 R2.

Info:

  • MVC4 is installed on the server
  • The application is in an app pool with integrated mode and framework v4

What i've tried:

  • Played with routes enough to know it's not a routing issue
  • Have <modules runAllManagedModulesForAllRequests="true" /> set (is the default anyway)
  • Looked at this
  • Done the aspnet_regiis -ir dance
  • Custom errors off, compilation debug=false - if those make any difference.
  • There are only custom api routes, no catch all.
  • IIS Logs just indicate a 404, as you'd expect; nothing in system event logs

The api uses only GET and POST requests, neither of which are working. Might also be worth mentioning that the calls are all made via ajax.

system.web, system.webServer,runtime sections from config:

<system.web>
    <compilation debug="false" targetFramework="4.0" />
    <customErrors mode="Off" />
    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login" timeout="2880" />
    </authentication>
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
  </system.web>

<system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <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" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

Any suggestions hugely appreciated. Thanks.

Update

I reimplemented one of my controllers to use only HttpResponseMessage and HttpRequestMessage

[HttpGet]
public HttpResponseMessage GetAccount(HttpRequestMessage message)
{
    message.CreateResponse(....

and again this works as expected when running locally (both cassini and full IIS local install on Win7), but fails when pushed onto the server.


Solution

  • Wasn't able to fix this issue. Almost certainly down to some obscure thing not installed or switched on on the server. Very frustrating as other Web Apis are already working on the same box.

    Couldn't spend any more time on it, so just reimplemented using Service Stack instead, which just works.