6

ASP.NET / Mono MVC4 Web API v.1 application.

How to catch calls to undefined api methods. Calling http://localhost:52216/erp/api/undefinedmethod returns error to browser:

<Error>
<Message>
No HTTP resource was found that matches the request URI 'http:// localhost:52216/erp/api/undefinedmethod'.
</Message>
<MessageDetail>
No type was found that matches the controller named 'undefinedmethod'.
</MessageDetail>
</Error>

How to catch this error for logging to database? I tried code from question

How do I log ALL exceptions globally for a C# MVC4 WebAPI app?

but Application_Error and exception filter code is still not executed, error is returned to browser. How to catch this error ?

If url is without api like

'http://localhost:52216/erp/undefinedmethod'

Application_Error is executed properly.

WebAPI configuration from VS2013 WebAPI project template is used:

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

 }

Update

I tried changed answer. API controllers are using Forms authorication and are decorated with standard [Authorize] attribute. If authorization fails, standard xml api error message

<Error>
<Message>Authorization has been denied for this request.</Message>
</Error>

occurs. How to catch this error also ?

Community
  • 1
  • 1
Andrus
  • 26,339
  • 60
  • 204
  • 378
  • I guess, you receive an HTTP 404 when calling this URL. You could create custom error page for HTTP 404 and log the error in the default action of the respective controller. – Carsten Nov 26 '13 at 10:25
  • api methods and other controllers can also return 404 result pages. They provide json content in this pages explaining 404 error which shuld passed to caller exactly in this form. Those are business errors which should not logged. Creating global 404 error page disables those method results. – Andrus Nov 26 '13 at 10:42

1 Answers1

5

Imran Baloch wrote an article on exactly how to achieve this. Basically you need to create your own HttpControllerSelector and HttpActionSelector. You can find the article here.

EDIT:

If your application uses routes other than those registered in the WebApiConfig you will need to make some changes to the routing. Instead of defining the Error404 route at the end of the Register method, define a new method (RegisterNotFound) to register the route:

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

    public static void RegisterNotFound(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "Error404",
            routeTemplate: "{*url}",
            defaults: new { controller = "Error", action = "Handle404" }
        );
    }
}

And then in the Global.asax register call this method last:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    WebApiConfig.RegisterNotFound(GlobalConfiguration.Configuration);


    GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector), 
        new HttpNotFoundAwareDefaultHttpControllerSelector(GlobalConfiguration.Configuration));
    GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionSelector), 
        new HttpNotFoundAwareControllerActionSelector());

}
Jon Susiak
  • 4,948
  • 1
  • 30
  • 38
  • I tried to use it but now every url returns 404 error. I updated question. – Andrus Nov 26 '13 at 15:58
  • I tried it but if authorization fails, error is still not catched. I updated question. – Andrus Nov 27 '13 at 17:38
  • Your original question was about catching undefined routes. Authorization occurs later in the pipeline and is a different issue. If you want to intercept authorization issues or other errors I suggest you raise a separate question after closing this one. – Jon Susiak Nov 28 '13 at 08:48
  • I marked and upvoted your answer and posted separate question in http://stackoverflow.com/questions/20271302/how-to-catch-forms-authorization-error-in-web-api-in-asp-net-mvc4 – Andrus Nov 28 '13 at 16:54
  • I'd like to add for anyone getting a "The given key was not present in the dictionary", in the `HttpNotFoundAwareControllerActionSelector`, add a `routeDataValues.Clear();`. For some reason, there was a key in there named `MS_SubRoutes` that was messing things up. – Alex Lein Jul 02 '19 at 15:09