ASP.NET Web Api returns 200 OK when it should return 404

asp.net, asp.net-web-api, routes

Solution

In your Global.asax.cs file where your `protected void Application_Start(object sender, EventArgs e)` is, add the following:

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
    }

All server requests should come through here.

Add these using if not there.

using System.Web.Compilation;
using System.Reflection;

Then in the begin request call add this code to list out all of the active routes.

        string Items = "";
        IEnumerable<Assembly> Assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>();

        foreach (Assembly FoundAssembly in Assemblies)
        {
            string AssemblyName = FoundAssembly.FullName;
            IEnumerable<TypeInfo> Types = FoundAssembly.DefinedTypes.Where(type => type != null && type.IsPublic && type.IsClass && !type.IsAbstract && typeof(ApiController).IsAssignableFrom(type));
            foreach (TypeInfo ControllerType in Types)
            {
                System.Web.Http.Controllers.ApiControllerActionSelector ApiControllerSelection = new System.Web.Http.Controllers.ApiControllerActionSelector();
                System.Web.Http.Controllers.HttpControllerDescriptor ApiDescriptor = new System.Web.Http.Controllers.HttpControllerDescriptor(new System.Web.Http.HttpConfiguration(), ControllerType.Name, ControllerType);
                ILookup<string, System.Web.Http.Controllers.HttpActionDescriptor> ApiMappings = ApiControllerSelection.GetActionMapping(ApiDescriptor);

                foreach (var Maps in ApiMappings)
                {
                    foreach (System.Web.Http.Controllers.HttpActionDescriptor Actions in Maps)
                    {
                        Items += "[ controller=" + ControllerType.Name + " action=" + ((System.Web.Http.Controllers.ReflectedHttpActionDescriptor)(Actions)).MethodInfo + "]";
                    }
                }
            }
        }

This will list all controllers and their signatures. If your URL does not fit into any of these you may have to expand the list to include non controller routes.

Problem

I have the following action methods on a controller in an ASP.NET Web API project: ``` [Route("api/v2/project/{projectId}/stuff"), HttpGet] public IHttpActionResult Get(int projectId) [Route("api/v2/project/{projectId}/stuff/{id:guid}"), HttpGet] public IHttpActionResult Get(int projectId, [FromUri] Guid id) [Route("api/v2/project/{projectId}/stuff"), HttpPost] public IHttpActionResult Post(int projectId, [Required] Stuff stuff) [Route("api/v2/project/{projectId}/stuff/{id:guid}"), HttpPut] public IHttpActionResult Put(int projectId, [FromUri] Guid blastId, Stuff stuff) [Route("api/v2/project/{projectId}/stuff/{id:guid}"), HttpDelete] public IHttpActionResult Delete(int projectId, [FromUri] Guid id) ``` Due to a javascript error, I made a `DELETE` request to ``` api/v2/project/1234/stuff/undefined ``` i.e. instead of a `GUID` for the id, I got the string `"undefined"`. As far as I can tell, this shouldn't match any of my routes, but instead of a `404 Not found` (or even `405 Method not allowed`), I got a `200 OK` as response. I set a breakpoint in each of these action methods and repeated the request using Fiddler, but none of the breakpoints was hit. I also tried installing the WebApiRouteDebugger package from nuget, but we're using a custom controller factory which hooks things up through our DI container, so I couldn't get it to work at all. I even tried throwing the following exception from one of my globally registered filters: ``` throw new Exception(actionContext.ControllerContext.ControllerDescriptor.ControllerName + " " + actionContext.ActionDescriptor.ActionName); ``` but the `DELETE` request still goes through to `200 OK` (no requests to valid urls seem to do that). How else can I troubleshoot this? What could be the root cause?

Original source

Related problems