I'm pretty new to MVC ASP.NET. I read about OnException override method. I'm thinking, whether I should put try catch {throw} on Controller or Model in order for OnException to be invoked. OR, I try catch not required, OnException will be invoked autmatically if any exception occurs?
Thanks Heaps.
"Called when an unhandled exception occurs in the action."
http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.onexception.aspx
If you don't handle (i.e. "catch") an exception, the OnException method should be called.
I ended up doing this:
Created LogAndRedirectOnErrorAttribute class that uses abstract class FilterAttribute and implements IExceptionFilter as shown below:
public class LogAndRedirectOnErrorAttribute : FilterAttribute,IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
//Do logging here
Util.LogError(Utility.GetExceptionDetails(filterContext.Exception), TraceEventType.Critical.ToString());
//redirect to error handler
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(
new { controller = "Error", action = "Index" }));
// Stop any other exception handlers from running
filterContext.ExceptionHandled = true;
// CLear out anything already in the response
filterContext.HttpContext.Response.Clear();
}
}
And on Each Controller Class where necessary, use the above attribute:
[LogAndRedirectOnError]
public class AccountController:Controller
{
.....
}
Related
I use javax.mail dependency spring-boot-starter-mail and i want to override the error message that user get when they provide wrong email or email with domain that dose not exist. How can i override the error message of javax.mail.SendFailedException from the method getInvalidAddresses?
I want to override and pass the user a nice error message. I have my own GlobalExceptionClass which i use for all diffrent Exceptions inside my app:
#ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler({SendFailedException.class})
private ResponseEntity<MessageResponse> handleSendFailException(SendFailedException sfe){
if (sfe.getInvalidAddresses() != null) {
System.out.println("INVALID ADRESSS");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new
MessageResponse("adress is inavlid"));
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new
MessageResponse("invalidadress"));
}
}
My Controller Class
#PostMapping("/offers")
public ResponseEntity<MessageResponse> mailOffer(#Valid #RequestBody OffersDto offersDto) throws
MessagingException {
String succMessage = "success.";
offersService.addOffer(offersDto);
offersService.sendMail(offersDto);
return ResponseEntity.ok(new MessageResponse(succMessage));
}
Services class
public Offers sendMail(OffersDto offersDto) throws MessagingException {
///messaging methods, attributes
}
i just replicated this exception handling the same as for other methods, but above code dose not overrides the exception message
You have to try/catch checked exception and in catch or finally block throw new unchecked custom exception, after that handle your Custom exception(you must add attributes of MessagingException to your custom exception for checking statements)
#ExceptionHandler({CustomException.class})
We have a global.asax.cs file which contains this code...
Approach One
public class WebApiApplication : System.Web.HttpApplication
{
TelemetryClient _telemetry = new TelemetryClient(new Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration() {
InstrumentationKey = EnvironmentHelper.InstrumentationKey,
ConnectionString = EnvironmentHelper.AppInsightsConnectionString
});
protected void Application_Start()
{
HttpConfiguration config = GlobalConfiguration.Configuration;
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
I am concerned that this will not log every and all exceptions to Insights. Would it be better to use this code?...
Approach Two
public class WebApiApplication : System.Web.HttpApplication
{
TelemetryClient _telemetry = new TelemetryClient(...);
protected void Application_Start()
{
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Filters.Add(new CustomExceptionFilter()); // ADDED LINE
GlobalConfiguration.Configure(WebApiConfig.Register);
}
protected void Application_Error(Object sender, EventArgs e) // ADDED METHOD
{
Exception appException = Server.GetLastError();
_telemetry.TrackException(appException);
}
}
// ADDED CLASS
public class CustomExceptionFilter : ExceptionFilterAttribute
{
TelemetryClient _telemetry = new TelemetryClient(...);
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
_telemetry.TrackException(actionExecutedContext.Exception);
base.OnException(actionExecutedContext);
}
}
Are these approaches equal or is one more reliable?
Not sure what do you mean all exceptions get logged.
Actually, Application Insights will auto collect unhandled exceptions thrown in the controller methods automatically for WebAPI 2+, exception the following scenario:
Exceptions thrown from controller constructors.
Exceptions thrown from message handlers.
Exceptions thrown during routing.
Exceptions thrown during response content serialization.
Exception thrown during application start-up.
Exception thrown in background tasks.
And For the other exceptions which are handled by application, still need to be tracked manually. You can use the telemetryclient to track these exceptions.
The referenced doc is here.
I am new to String, SpringBoot.
Can we suppress thrown exception in a method annotated with #AfterThrowing?
I mean when an exception is thrown, it will suppress that and will return a default value on behalf of the invoking method?
Say, I have a controller -
#RestController
public class MyRestController implements IRestController{
#Override
#GetMapping("hello-throw")
public String mustThrowException(#RequestParam(value = "name")final String name) throws RuntimeException {
System.out.println("---> mustThrowException");
if("Bakasur".equals(name)) {
throw new RuntimeException("You are not welcome here!");
}
return name + " : Welcome to the club!!!";
}
}
I have created a #AspectJ, as follows -
#Aspect
#Component
public class MyAspect {
#Pointcut("execution(* com.crsardar.handson.java.springboot.controller.IRestController.*(..))")
public void executionPointcut(){
}
#AfterThrowing(pointcut="executionPointcut()",
throwing="th")
public String afterThrowing(JoinPoint joinPoint, Throwable th){
System.out.println("\n\n\tMyAspect : afterThrowing \n\n");
return "Exception handeled on behalf of you!";
}
}
If I run this & hit a ULR like - http://localhost:8080/hello-throw?name=Bakasur
I will get RuntimeException, but, I want to return a default message like - Exception handeled on behalf of you!, can we do it using #AfterThrowing?
I know it can be done using #Around, but around will be called on every hit of the url, that I do not want
What you want to do is Exception Handling on the controller. You don't need to build it yourself, Spring already supports you with some annotations like #ExceptionHandler and #ControllerAdvice. Best would be to follow this example: https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc#using-controlleradvice-classes
#ControllerAdvice
class GlobalControllerExceptionHandler {
#ResponseStatus(HttpStatus.CONFLICT) // 409
#ExceptionHandler(DataIntegrityViolationException.class)
public void handleConflict() {
// Nothing to do
}
}
#ControllerAdvice
class GlobalDefaultExceptionHandler {
public static final String DEFAULT_ERROR_VIEW = "error";
#ExceptionHandler(value = Exception.class)
public ModelAndView
defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
// If the exception is annotated with #ResponseStatus rethrow it and let
// the framework handle it - like the OrderNotFoundException example
// at the start of this post.
// AnnotationUtils is a Spring Framework utility class.
if (AnnotationUtils.findAnnotation
(e.getClass(), ResponseStatus.class) != null)
throw e;
// Otherwise setup and send the user to a default error-view.
ModelAndView mav = new ModelAndView();
mav.addObject("exception", e);
mav.addObject("url", req.getRequestURL());
mav.setViewName(DEFAULT_ERROR_VIEW);
return mav;
}
}
You should use the fully qualified name of the class before method's name when you're referring to a pointcut. So, you should change #AfterThrowing something like this.
#AfterThrowing(pointcut="packageName.MyAspect.executionPointcut()",
throwing="th")
Please note that packageName is full package name of MyAspect.
I have the following RESTful Services method :
#PostMapping("/ajouterNewField")
public String ajouterField(#Valid #ModelAttribute("field") Fields field, Model model) throws IOException {
fieldDao.save(field);
// SOME CODE
return displayListeChamps( model);
}
The method is working fine and my question is how to handle any error (database not connected ...) or every issue that can happen durring the execution of this RESTful Services method.
You can use #ControllerAdvice
Refer to the code below
#ControllerAdvice
public String NyExceptionHandlerAdvice {
private final Logger logger = ...;
#ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
#ExceptionHandler({MyRunTimeException.class})
public void handleMyRunTimeException(Exception e) {
logger.error("Exception : ", e);
}
return MY_ERROR_STRING;
}
Best Practice is:
You can have your code throw RunTimeExceptions and handle all of them together or separately in handler methods similar to handleMyRunTimeException above.
You can decide what status code your request should return upon exception.
Basically you'll have to a sort of exception handler for any kind of exception your method might throw:
public class FooController{
// ...
#ExceptionHandler({ CustomException1.class, CustomException2.class })
public void handleException() {
//
}
}
Here's a nice article about that: https://www.baeldung.com/exception-handling-for-rest-with-spring
I have a long time polling controller in my MVC3 project. It has its timeout set to 30 seconds. I have a HandleErrorAttribute implementation that handles logging of all errors.
Since the timout throws a TimeoutException it means these will be presented in the log.
I need to intercept this error before my HandleErrorAttribute class gets it and return a json object instead of the 500 error page. Whats the best approach for this?
I did this and it works
public class HandleTimeout : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
if(filterContext.Exception is TimeoutException)
{
filterContext.Result = new { Timeout = true }.AsJson();
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.StatusCode = 200;
}
base.OnException(filterContext);
}
}
Best approach?
I went with this route, the difference from my above code is that I also check if the Controller is Async, because we only want to handle Timeouts in this fashion if we are in a long time polling scenarios.
public class HandleTimeout : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
if(filterContext.Exception is TimeoutException && filterContext.Controller is AsyncController)
{
filterContext.HttpContext.Response.StatusCode = 200;
filterContext.Result = new { Timeout = true }.AsJson();
filterContext.ExceptionHandled = true;
}
base.OnException(filterContext);
}
}
The notion of best is very subjective. I prefer not to talk about it as different people have different definition of it. For me using a custom exception filter is a very good approach to handle this case without polluting your controller with exception handling code.