Reputation: 60574
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?
Upvotes: 7
Views: 3167
Reputation: 159
I had the same issue. In my startup.cs I had the method
app.Run(async context =>
{
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync("My Api");
});
This was causing all routes to receive a 200 response along with the string. I only wanted to show this response on startup. This was the solution.
app.MapWhen(ctx => ctx.Request.Path.Value == "/", StartupPage);
Along with a method in the same Startup class
private void StartupPage(IAppBuilder app)
{
app.Run(async (context) =>
{
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync("My Api");
});
}
I only return the 200 OK message when a request is made on the base url.
Upvotes: 2
Reputation: 4353
I'm am not sure of your routing but I think you have a routing that does not include actions in mapping:
api/v2/project/1234/stuff/undefined
Check web api config for this: api/{controller}[/{action}]/{id}
. I think you might hit another route action with your action(like a GET).
P.S. post your route config to update answer.
Upvotes: 0
Reputation: 2896
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.
Upvotes: 3