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

I have the following controller action methods 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 javascript error, I made a DELETE request for

 api/v2/project/1234/stuff/undefined 

i.e. instead of the GUID for id, I got the string "undefined" . As far as I can tell, this should not match any of my routes, but instead of 404 Not found (or even 405 Method not allowed ) I got a 200 OK response.

I set a breakpoint in each of these action methods and retried the request using Fiddler, but none of the breakpoints were deleted. I also tried installing the WebApiRouteDebugger package from nuget, but we use a custom factory controller that intercepts things through our DI container, so I could not get it to work at all. I even tried to make the following exception from one of my global filters:

 throw new Exception(actionContext.ControllerContext.ControllerDescriptor.ControllerName + " " + actionContext.ActionDescriptor.ActionName); 

but the DELETE request still passes up to 200 OK (no requests for valid URLs seem to do this).

How else can I fix this problem? What could be the main reason?

+7
asp.net-web-api routing
source share
3 answers

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

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

All server requests should go here.

Add them if not there.

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

Then, in the start request call, add this code to display all 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 + "]"; } } } } 

All controllers and their signatures are listed here. If your URL doesn’t match any of these, you might need to expand the list to include non-controller routes.

+3
source share

I had the same problem. In my startup.cs, I had a method

 app.Run(async context => { context.Response.ContentType = "text/plain"; await context.Response.WriteAsync("My Api"); }); 

This led to all routes receiving a 200 response along with the line. I just wanted to show this answer at startup. It was a decision.

  app.MapWhen(ctx => ctx.Request.Path.Value == "/", StartupPage); 

Along with a method in the same launch class

  private void StartupPage(IAppBuilder app) { app.Run(async (context) => { context.Response.ContentType = "text/plain"; await context.Response.WriteAsync("My Api"); }); } 

I only return a 200 OK message when the request is made at the base URL.

+1
source share

I'm not sure about your routing, but I think you have a routing that does not include actions in the mapping:

 api/v2/project/1234/stuff/undefined 

Check the web api configuration for this: api/{controller}[/{action}]/{id} . I think you can do another action with an action (like GET).

PS send the configuration of your route to update the response.

0
source share

All Articles