{"id":2024,"date":"2012-11-16T21:56:56","date_gmt":"2012-11-16T21:56:56","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/webdev\/2012\/11\/16\/capturing-unhandled-exceptions-in-asp-net-web-apis-with-elmah\/"},"modified":"2022-08-10T05:55:43","modified_gmt":"2022-08-10T12:55:43","slug":"capturing-unhandled-exceptions-in-asp-net-web-apis-with-elmah","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/capturing-unhandled-exceptions-in-asp-net-web-apis-with-elmah\/","title":{"rendered":"Capturing Unhandled Exceptions in ASP.NET Web API&#8217;s with ELMAH"},"content":{"rendered":"<p>I&#8217;m a fan of using ELMAH to track unhandled exceptions in my ASP.NET applications. If you haven&#8217;t tried <a href=\"http:\/\/code.google.com\/p\/elmah\/\" target=\"_blank\" rel=\"noopener noreferrer\">ELMAH<\/a>, you should definitely check it out. There&#8217;s even an <a href=\"http:\/\/nuget.org\/packages\/elmah\" target=\"_blank\" rel=\"noopener noreferrer\">ELMAH NuGet package<\/a> so it&#8217;s trivial to install.<\/p>\n<p>Now that I&#8217;m getting my feet wet with Web API, I&#8217;d like to have any Web API unhandled exceptions be directed to ELMAH as well so that I have a one stop shop for viewing all unhandled exceptions in my application. Without a bit of work though, this won&#8217;t happen.<\/p>\n<p>Here&#8217;s why:<\/p>\n<p>ELMAH records unhandled exceptions by tapping into the <strong>Application_Error<\/strong> event of ASP.NET applications, but when a Web API endpoint throws an unhandled exception, <u>this event isn&#8217;t triggered<\/u> because the exception is intentionally swallowed higher in the Web API call stack. This enables Web API to send a response to the client like &#8220;500 &#8211; Internal Server Error&#8221;. If the exception went unhandled, Web API wouldn&#8217;t send any response to the client.<\/p>\n<p>If you have a Web API that throws an unhandled exception, ELMAH shows:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2012\/11\/4341.image_thumb_482F1C5D.png\"><img decoding=\"async\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2012\/11\/4341.image_thumb_482F1C5D.png\" alt=\"image\" width=\"694\" height=\"224\" border=\"0\" \/><\/a><\/p>\n<p>So how do we catch these unhandled Web API exceptions and route them to ELMAH?<\/p>\n<p>One good option is to use an <a href=\"http:\/\/www.asp.net\/web-api\/overview\/web-api-routing-and-actions\/exception-handling#exception_filters\" target=\"_blank\" rel=\"noopener noreferrer\">Exception Filter<\/a>. If you&#8217;re familiar with exception filters in MVC, it&#8217;s the same idea, but instead of implementing <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.web.mvc.iexceptionfilter(v=vs.98).aspx\" target=\"_blank\" rel=\"noopener noreferrer\">System.Web.Mvc.IExceptionFilter<\/a>, we need to implement <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/hh835806(v=vs.108).aspx\" target=\"_blank\" rel=\"noopener noreferrer\">System.Web.Http.Filters.IExceptionFilter<\/a> (note the namespace difference), and creating a derived class from <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.web.http.filters.exceptionfilterattribute(v=vs.108).aspx\" target=\"_blank\" rel=\"noopener noreferrer\">System.Web.Http.Filters.ExceptionFilterAttribute<\/a> is an easy approach.<\/p>\n<p>In our derived class, we&#8217;ll simply override the OnException method and make an explicit log call to ELMAH.<\/p>\n<p>Then, we wire-up our custom exception filter globally by adding our filter:<\/p>\n<p>Now when one of our Web API&#8217;s throws an unhandled exception, ELMAH picks it up.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2012\/11\/5811.image_thumb_0CFB4092.png\"><img decoding=\"async\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2012\/11\/5811.image_thumb_0CFB4092.png\" alt=\"image\" width=\"697\" height=\"293\" border=\"0\" \/><\/a><\/p>\n<p>Hope this helps,\nMark<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m a fan of using ELMAH to track unhandled exceptions in my ASP.NET applications. If you haven&#8217;t tried ELMAH, you should definitely check it out. There&#8217;s even an ELMAH NuGet package so it&#8217;s trivial to install. Now that I&#8217;m getting my feet wet with Web API, I&#8217;d like to have any Web API unhandled exceptions [&hellip;]<\/p>\n","protected":false},"author":455,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197],"tags":[34],"class_list":["post-2024","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","tag-asp-net-web-api"],"acf":[],"blog_post_summary":"<p>I&#8217;m a fan of using ELMAH to track unhandled exceptions in my ASP.NET applications. If you haven&#8217;t tried ELMAH, you should definitely check it out. There&#8217;s even an ELMAH NuGet package so it&#8217;s trivial to install. Now that I&#8217;m getting my feet wet with Web API, I&#8217;d like to have any Web API unhandled exceptions [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/2024","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/455"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=2024"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/2024\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=2024"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=2024"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=2024"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}