I am writting an API for some data manipulation these days and I have faced a question that I cannot answer myself :D
I have made an exception class that extends the .net Application Exception class because I want to add some functionality there to be executed everytime the API throws an exception.
For example I want to alert the error message and stacktrace via sms and email and I want to log the inner exception via Log4net. I don't know if this is a good aproach to use with the custom exception class or if I overused the meaning of the custom exceptions.
I have read this article about how to extend the Exception in c#
so here we go with my example of code :
public class CustomExceptionClass : Exception
{
/// <summary>
/// I use custom functionality here everytime this exception occures
/// </summary>
/// <param name="errorMessage">error message</param>
/// <param name="innerEx">Inner exception that cause this exception</param>
public MyCustomException(string errorMessage, Exception innerEx) : base(errorMessage, innerEx)
{
//log exception
_log.ErrorFormat(errorMessage, innerEx);
//alert via sms and email
AlertMailer.SendAlertMessage(errorMessage, innerEx, innerEx.Message);
}
}
I think that doing logging and alerting by throwing a custom exception is a valid technique.
However, you shouldn't do the logging and alerting in the exception constructor. Instead you should catch the custom exception in all entry-points to your API and do the logging and alerting in the catch block. For example:
void MyApiFunction()
{
try
{
// do data manipulation
}
catch(MyCustomException ex)
{
_log.ErrorFormat(ex.ErrorMessage, ex.InnerEx);
AlertMailer.SendAlertMessage(ex.ErrorMessage, ex.InnerEx);
}
}
I would recomend you to use AOP instead.
PostSharp exception handling
Custom exceptions should be used to define different types of exception.
Exceptions from the database
Exceptions from file io
Exceptions from web services
They should be very simple, and contain no other logic than assigning variables. Why? Because if the exception constructor throws another exception you are going to have a hard time tracing it.
The ways i handle those exceptions are:
AOP (Spring.NET)
Specific try/catches
The global exception handler
In a program
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
try {
//do something
} catch(Exception e) {
//log error
}
}
}
}
Or in a web site
public class ApplicationErrorModule : IHttpModule {
public void Init(HttpApplication context) {
context.Error += new EventHandler(context_Error);
}
private void context_Error(object sender, EventArgs e) {
//log error
}
}
Heavy treatments like logging and sending an email don't belong in the constructor of the exception. You should instead handle the exception using AOP as #petro suggested, or in a catch statement.
Related
When certain exceptions are thrown in controllers, I want to catch those exceptions and do some extra logic.
I was able to achieve this with a custom IExceptionFilter that is added to the global filters list.
However, I preffer to handle these exception within a custom Owin middleware.
My middleware looks like this:
try
{
await Next.Invoke(context);
}
catch (AdalSilentTokenAcquisitionException e)
{
//custom logic
}
This piece of code does not work, it looks like the exception is already catched and handled in MVC.
Is there a way to skip the exception processing from MVC and let the middleware catch the exception?
Update: I've found a cleaner approach, see my updated code below.
With this approach, you don't need a custom Exception Filter and best of all, you don't need the HttpContext ambient service locator pattern in your Owin middleware.
I have a working approach in MVC, however, somehow it doesn't feel very comfortable, so I would appreciate other people's opinion.
First of all, make sure there are no exception handlers added in the GlobalFilters of MVC.
Add this method to the global asax:
protected void Application_Error(object sender, EventArgs e)
{
var lastException = Server.GetLastError();
if (lastException != null)
{
HttpContext.Current.GetOwinContext().Set("lastException", lastException);
}
}
The middleware that rethrows the exception
public class RethrowExceptionsMiddleware : OwinMiddleware
{
public RethrowExceptionsMiddleware(OwinMiddleware next) : base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
await Next.Invoke(context);
var exception = context.Get<Exception>("lastException");
if (exception != null)
{
var info = ExceptionDispatchInfo.Capture(exception);
info.Throw();
}
}
}
There's no perfect way to do this (that I know of), but you can replace the default IExceptionHandler with one that just passes the error through to the rest of the stack.
I did some extensive digging about this, and there really doesn't seem to be a better way for now.
My DAL doesn't handle exceptions and it will be propagated up to the calling method in the presenter classes where the exception will be handled.
I'm using a single handler called ExecutAction(Action action) so I'm catching exceptions in one place rather than repeating in every method.
At the moment, I'm not logging errors. Just alert the user for an action and try to keep the system alive if possible.
When showing messages to users, Presenters will use a static class called MessagingService. (ShowErrorMessage()). So that I can customize all massage boxes in one place.
private void Search()
{
ExecutAction(() =>
{
var info = _DataService.GetByACNo(_model.AccountNumber);
if (info != null)
{
_Model = info ;
this.SetViewPropertiesFromModel(_Model, _View);
}
else
{
MessageBox.Show ("Bank account not found");
}
});
}
private void ExecutAction(Action action)
{
try
{
action();
}
catch (NullReferenceException e) { MessagingService.ShowErrorMessage(e.Message); }
catch (System.Data.SqlTypes.SqlTypeException e) { MessagingService.ShowErrorMessage(e.Message); }
catch (System.Data.SqlClient.SqlException e) { MessagingService.ShowErrorMessage(e.Message); }
}
}
Should I include general exception handler to this, to be able to handle any unforeseen exceptions?
Also could you show me a better way to handle showing messages than using a static?
Does use of lambda statements in every method call (ExecutAction(() =>) degrade code readability?
When showing user messages how to show a custom message like "Check the server connection" etc. first and then if the user wants more information (like StackTrace / technical details) he /she could press a button like More Info which is in the MessageBox dialog?
I agree with jeffrey about trying to incorporate IoC for your message service. You could define an abstract base presenter class that has a dependency on an interface for your message service. The base class would be responsible for handling the delegate execution + exception logging.
public interface IMessageService
{
void ShowErrorMessage(Exception e);
}
public abstract class PresenterBase
{
private readonly IMessageService _messageService;
public PresenterBase(IMessageService messageService)
{
this._messageService = messageService;
}
protected void ExecuteAction(Action action)
{
try
{
action();
}
catch (Exception e) { this._messageService.ShowErrorMessage(e); }
}
}
public class SearchPresenter: PresenterBase
{
public SearchPresenter(IMessageService messageService)
: base(messageService)
{
}
public void Search()
{
this.ExecuteAction(() =>
{
//perform search action
});
}
}
Regarding your question about catching all exeptions. Unless you are doing something special for specific types of exceptions, I would suggest just handling all the same. The example I provided passes the exception to the message service so that the formatting specifics can be handled by your message service.
If you have not yet incorporated any sort of IoC container, you can always start by using the interface injection and then passing the instance explicitly from the child class constructor.
public class SearchPresenter: PresenterBase
{
public SearchPresenter()
: base(new SomeMessageService())
{
}
...
}
This is at least removes the static dependency and is not too dificult to swap out later if you ever introduce an IoC container.
I think your approach is good enough for your work. Wrapping logics by ExecuteAction is an acceptable way to me. As another option, I might use AOP for centralized exception handling in practice.
Also, I might use a MessagingService resolved from dependency injection container rather than a static one.
Regarding how to display the error, that's totally depend on your business purpose. For example, you could simply log the error and tell the user "something's wrong", or show them the complete stacktrace including the environment information so they could simply copy & paste in the email.
Is there a better way to catch exceptions? I seem to be duplicating a lot of code. Basically in every controller I have a catch statement which does this:
try
{
Do something that might throw exceptions.
}
catch (exception ex)
{
Open database connection
Save exception details.
If connection cannot be made to the database save exception in a text file.
}
I have 4 controllers and around 5-6 actions methods in each controller which is a lot of code duplication. How can I trim down on the amount of line in the try catch statement above?
You could make use of Extension methods here.
Create an extension method in a new class.
public static class ExtensionMethods
{
public static void Log(this Exception obj)
{
// log your Exception here.
}
}
And use it like:
try
{
}
catch (Exception obj)
{
obj.Log();
}
You don't need to put try/catch blocks on every method. That's tedious and painful! Instead you can use the Application_Error event of Global.asax for logging the exceptions. The code below is the sample implementation which can be used to catch exceptions that occur in your web application.
protected void Application_Error(object sender, EventArgs e)
{
var error = Server.GetLastError();
if (!string.IsNullOrWhiteSpace(error.Message))
{
//do whatever you want if exception occurs
Context.ClearError();
}
}
I would like also to stress that "Handled exception" especially trying to put try/catch blocks on most methods is one of the "Top 3 silent performance killers for IIS / ASP.NET apps" as explained in this blog http://mvolo.com/fix-the-3-high-cpu-performance-problems-for-iis-aspnet-apps/
What you are trying to do is called a cross-cutting concern. You are trying to log any error that happens anywhere in your code.
In ASP.NET MVC cross-cutting concerns can be achieved by using Filters. Filters are attributes that can be applied globally, to a controller or to a method. They run before an action method executes or after it.
You have several types of filters:
Authorization filters, they run to check if the user is allowed to access a resource.
Action filters, these run before and after an action method executes.
Result filters, these can be used to change the result of an action method (for example, add some extra HTMl to the output)
Exception filters run whenever an exception is thrown.
In your case, you are looking for exception filters. Those filters only run when an exception happens in in an action method. You could apply the filter globally so it will automatically run for all exceptions in any controller. You can also use it specifically on certain controllers or methods.
Here in the MSDN documentation you can find how to implement your own filters.
Personally, since I greatly dislike try/catch blocks, I use a static Try class that contains methods that wrap actions in reusable try/catch blocks. Ex:
public static class Try {
bool TryAction(Action pAction) {
try {
pAction();
return true;
} catch (Exception exception) {
PostException(exception);
return false;
}
}
bool TryQuietly(Action pAction) {
try {
pAction();
return true;
} catch (Exception exception) {
PostExceptionQuietly(exception);
return false;
}
}
bool TrySilently(Action pAction) {
try {
pAction();
return true;
} catch { return false; }
}
// etc... (lots of possibilities depending on your needs)
}
I have used a special class in my applications that is called ExceptionHandler, in the class that is static I have some methods to handle application's exceptions. It gives me an opportunity to centralize exception handling.
public static class ExceptionHandler
{
public static void Handle(Exception ex, bool rethrow = false) {...}
....
}
In the method you can log the exception, rethrow it, replace it with another kind of exception, etc.
I use it in a try/catch like this
try
{
//Do something that might throw exceptions.
}
catch (exception ex)
{
ExceptionHandler.Handle(ex);
}
As Wouter de Kort has rightly stated in his answer, it is cross-cutting concern, so I've put the class in my Application Layer and have used it as a Service. If you defined the class as an interface you would be able to have different implementations of it in different scenarios.
Also you can use Singleton pattern:
sealed class Logger
{
public static readonly Logger Instance = new Logger();
some overloaded methods to log difference type of objects like exceptions
public void Log(Exception ex) {}
...
}
And
Try
{
}
Catch(Exception ex)
{
Logger.Instance.Log(ex);
}
Edit
Some peoples don't like Singleton for reasonable grounds.instead of singleton we can use some DI:
class Controller
{
private ILogger logger;
public Controller(ILogger logger)
{
this.logger = logger;
}
}
And use some DI library that will inject one instance of ILogger into your controllers.
I like the answers suggesting general solutions, however I would like to point out another one which works for MVC.
If you have a common controller base (wich you should anyways, it's a Best Practice IMO). You can simply override the OnException method:
public class MyControllerBase : Controller
{
protected override void OnException(ExceptionContext filterContext)
{
DoSomeSmartStuffWithException(filterContext.Exception);
base.OnException(filterContext);
}
}
Then simply inherit your normal controllers from your common base instead of Controller
public class MyNormalController : MyControllerBase
{
...
If you like this you can check out the Controller class for other handy virtual methods, it has many.
In ASP .NET MVC you can implement your own HandleErrorAttribute to catch all the exceptions that occur in all controllers:
public class CustomHandleErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
var ex = filterContext.Exception;
// Open database connection
// Save exception details.
// If connection cannot be made to the database save exception in a text file.
}
}
Then register this filter:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomHandleErrorAttribute());
}
}
And of-course call the register method on application start-up:
public class MvcApplication : HttpApplication
{
protected override void OnApplicationStarted()
{
// ...
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
// ...
}
}
Wouter de Kort has already explained the concept behind this in his answer.
How do I catch all unhandled exceptions that occur in ASP.NET Web Api so that I can log them?
So far I have tried:
Create and register an ExceptionHandlingAttribute
Implement an Application_Error method in Global.asax.cs
Subscribe to AppDomain.CurrentDomain.UnhandledException
Subscribe to TaskScheduler.UnobservedTaskException
The ExceptionHandlingAttribute successfully handles exceptions that are thrown within controller action methods and action filters, but other exceptions are not handled, for example:
Exceptions thrown when an IQueryable returned by an action method fails to execute
Exceptions thrown by a message handler (i.e. HttpConfiguration.MessageHandlers)
Exceptions thrown when creating a controller instance
Basically, if an exception is going to cause a 500 Internal Server Error to be returned to the client, I want it logged. Implementing Application_Error did this job well in Web Forms and MVC - what can I use in Web Api?
This is now possible with WebAPI 2.1 (see the What's New):
Create one or more implementations of IExceptionLogger. For example:
public class TraceExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
Trace.TraceError(context.ExceptionContext.Exception.ToString());
}
}
Then register with your application's HttpConfiguration, inside a config callback like so:
config.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());
or directly:
GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());
To answer my own question, this isn't possible!
Handling all exceptions that cause internal server errors seems like a basic capability Web API should have, so I have put in a request with Microsoft for a Global error handler for Web API:
https://aspnetwebstack.codeplex.com/workitem/1001
If you agree, go to that link and vote for it!
In the meantime, the excellent article ASP.NET Web API Exception Handling shows a few different ways to catch a few different categories of error. It's more complicated than it should be, and it doesn't catch all interal server errors, but it's the best approach available today.
Update: Global error handling is now implemented and available in the nightly builds! It will be released in ASP.NET MVC v5.1. Here's how it will work: https://aspnetwebstack.codeplex.com/wikipage?title=Global%20Error%20Handling
The Yuval's answer is for customizing responses to unhandled exceptions caught by Web API, not for logging, as noted on the linked page. Refer to the When to Use section on the page for details. The logger is always called but the handler is called only when a response can be sent. In short, use the logger to log and the handler to customize the response.
By the way, I am using assembly v5.2.3 and the ExceptionHandler class does not have the HandleCore method. The equivalent, I think, is Handle. However, simply subclassing ExceptionHandler (as in Yuval's answer) does not work. In my case, I have to implement IExceptionHandler as follows.
internal class OopsExceptionHandler : IExceptionHandler
{
private readonly IExceptionHandler _innerHandler;
public OopsExceptionHandler (IExceptionHandler innerHandler)
{
if (innerHandler == null)
throw new ArgumentNullException(nameof(innerHandler));
_innerHandler = innerHandler;
}
public IExceptionHandler InnerHandler
{
get { return _innerHandler; }
}
public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
Handle(context);
return Task.FromResult<object>(null);
}
public void Handle(ExceptionHandlerContext context)
{
// Create your own custom result here...
// In dev, you might want to null out the result
// to display the YSOD.
// context.Result = null;
context.Result = new InternalServerErrorResult(context.Request);
}
}
Note that, unlike the logger, you register your handler by replacing the default handler, not adding.
config.Services.Replace(typeof(IExceptionHandler),
new OopsExceptionHandler(config.Services.GetExceptionHandler()));
You can also create a global exception handler by implementing the IExceptionHandler interface (or inherit the ExceptionHandler base class). It will be the last to be called in the execution chain, after all registered IExceptionLogger:
The IExceptionHandler handles all unhandled exceptions from all
controllers. This is the last in the list. If an exception occurs, the
IExceptionLogger will be called first, then the controller
ExceptionFilters and if still unhandled, the IExceptionHandler
implementation.
public class OopsExceptionHandler : ExceptionHandler
{
public override void HandleCore(ExceptionHandlerContext context)
{
context.Result = new TextPlainErrorResult
{
Request = context.ExceptionContext.Request,
Content = "Oops! Sorry! Something went wrong."
};
}
private class TextPlainErrorResult : IHttpActionResult
{
public HttpRequestMessage Request { get; set; }
public string Content { get; set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
HttpResponseMessage response =
new HttpResponseMessage(HttpStatusCode.InternalServerError);
response.Content = new StringContent(Content);
response.RequestMessage = Request;
return Task.FromResult(response);
}
}
}
More on that here.
You may have existing try-catch blocks that you're not aware of.
I thought my new global.asax.Application_Error method wasn't being consistently called for unhandled exceptions in our legacy code.
Then I found a few try-catch blocks in the middle of the call stack that called Response.Write on the Exception text. That was it. Dumped the text on the screen then killed the exception stone dead.
So the exceptions were being handled, but the handling was doing nothing useful. Once I removed those try-catch blocks the exceptions propagated to the Application_Error method as expected.
I'm building a API for my pet software and I'm in the following situation:
A service that use another service. I have a service that use another service for load a Assembly, should I throw a exception in the service that load a assembly or on the service that use that service?
AssemblyService:
public class AssemblyService : IAssemblyService
{
public Assembly Load(string assemblyName)
{
Assembly assembly;
try
{
assembly = Assembly.Load(assemblyName);
}
catch
{
assembly = null;
}
return assembly;
}
...
}
Service that use AssemblyService:
public class CommandService : ICommandService
{
private readonly IAssemblyService assemblyService;
public CommandService(IAssemblyService assemblyService)
{
this.assemblyService = assemblyService;
}
public CommandOutput Process(string inputCommand, string requestInfo)
{
string commandName = GetAssemblyName(inputCommand);
string args = GetArgs(inputCommand);
Assembly assembly = assemblyService.Load(commandName);
if (assembly == null) throw new UnknownCommandException(commandName);
ICommand command = assemblyService.GetCommand(assembly);
return command.Execute(args, requestInfo);
}
#region Private methods
...
#endregion
}
Should I throw the exception in AssemblyService or CommandService like the above example?
I'm trying to learn how to handle a exception, in the above example the line assembly = Assembly.Load(assemblyName); can throw ArgumentNullException, ArgumentException, FileNotFoundException, FileLoadException and BadImageFormatException. Should I handle all these exceptions?
UnknownCommandException(commandName) is a custom exception.
Other question: Anyone who's using my API could know when a method could throw a exception? I see placing the mouse over any methods of .Net Framework you will see if the method could throw a exception. Could this works with methods of my API?
Your title is about throwing exceptions but you actually seem to be talking about catching exceptions. You should generally not catch exceptions unless you can do something meaningful to rectify the condition that caused the exception to be thrown in the first place, and in that case you should only catch the explicit exception types that you can handle.
There are two things to think about here:
Will the normal flow of the application be abruptly halted to the point where it will no longer work? Exceptions are exactly that - a notification that something exceptional (out of the ordinary, abnormal, etc.) has happened. If it isn't exceptional, don't throw an exception. If the user can continue to use the program without noticing, don't use an exception.
How you comment the method declaration will affect this. There should be some markup tags for the comments that will allow you to explain what exception will be thrown and under what circumstances it will be thrown. They look like this:
/// <exception cref="ExceptionTypeGoesHere"></exception>
I normally try and avoid using exceptions to control the flow of the program. Your program uses an exception to convert it to a result variable and then converts that back to an exception. Why not stick with exceptions all the way? I would change it as follows:
public class AssemblyService : IAssemblyService
{
public Assembly Load(string assemblyName)
{
return Assembly.Load(assemblyName);
}
}
public class CommandService : ICommandService
{
private readonly IAssemblyService assemblyService;
public CommandService(IAssemblyService assemblyService)
{
this.assemblyService = assemblyService;
}
public CommandOutput Process(string inputCommand, string requestInfo)
{
string commandName = GetAssemblyName(inputCommand);
try
{
string args = GetArgs(inputCommand);
Assembly assembly = assemblyService.Load(commandName);
ICommand command = assemblyService.GetCommand(assembly);
return command.Execute(args, requestInfo);
}
catch (Exception ex)
{
//Log original exception or add to inner exception
throw new UnknownCommandException(commandName);
}
}
}
api as the name suggests is the gateway to an application. if an error occurs in the api, it is most useful for the api to tell the consumer why, where and when the error happened i.e. api throws the exception out. it is up to the consumer to catch this and tell its users what to do or if the business logic is defined well the consumer will calculate alternative execution paths. this is my rule of thumb
in the example above the assembly load service should throw the error out. If you handle this in the api, then the consumer will never learn :)
for general guidelines to exception handling look here in Msdn