Reputation: 77876
Was working on logging using NLOG and there is separate class @ global level from where logging happens. Per requirement, have to redirect to "Error" view (Error.cshtml
) from that class after logging is over.
But it's a non-controller class and hence can't use usual methods like RedirectToAction()
or simply return View("Error")
.
Is there any way possible of doing that? I tried Response.Redirect()
but doesn't do anything.
HttpContext.Current.Response.Redirect("/Help/Error",true);
Error.cshtml
is a plain HTML file with text like There is some error ... please contact admin which is present under Views/Shared/*
folder.
Logging class is present in a separate folder say logging
under root folder.
On every call to Action method if any exception occurs then the logger gets invoked automatically which does it's stuff of logging and finally should redirect to the error view.
Upvotes: 1
Views: 2196
Reputation: 218732
You can create your own base controller and handle the exceptions in the onexception event
public class BaseController : Controller
{
protected override void OnException(ExceptionContext filterContext)
{
//Do your logging
// and redirect / return error view
filterContext.ExceptionHandled = true;
// If the exception occured in an ajax call. Send a json response back
// (you need to parse this and display to user as needed at client side)
if (filterContext.HttpContext.Request.Headers["X-Requested-With"]=="XMLHttpRequest")
{
filterContext.Result = new JsonResult
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new { Error = true, Message = filterContext.Exception.Message }
};
filterContext.HttpContext.Response.StatusCode = 500; // Set as needed
}
else
{
filterContext.Result = new ViewResult { ViewName = "Error.cshtml" };
//Assuming the view exists in the "~/Views/Shared" folder
}
}
}
Now for your other controllers, inherit from this bascontroller.
public class ProductsController : BaseController
{
public ActionResult Die()
{
throw new Exception("I lost!");
}
}
If you want to do a redirect (a new GET call) to your Error action method, you can replace the ViewResult with a RedirectToRouteResult
.
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary {
{"controller", "Home"}, {"action", "Error"}
};
Upvotes: 2
Reputation: 38367
You don't say how the logging code is called automatically "the logger gets invoked automatically". So I'm going to recommend a HandleErrorAttribute. This requires you have a Error.cshtml in your shared views folder, but you could specify a different view in filterContext.Result
public class CustomErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;// This causes the webconfig httpErrors section to be ignored, since we are handling the exception
filterContext.ExceptionHandled = true;
//... log error
filterContext.HttpContext.Response.ClearContent();// Removes partially rendered content
// just information to be passed in the view model, this does NOT define which view is displayed next. It tells us where the error came from.
var controllerName = (string)filterContext.RouteData.Values["controller"];
var actionName = (string)filterContext.RouteData.Values["action"];
var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
// This presents an error page view. By default if a View is not passed to the Attribute, then this is Error.cshtml in Shared.
filterContext.Result = new ViewResult
{
ViewName = View, // View & Master are parameters from the attribute e.g. [ErrorAttribute(View="OtherErrorView")], by default the view is the "Error.cshtml" view
MasterName = Master,
ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
TempData = filterContext.Controller.TempData
};
filterContext.Exception = null;
}
}
Upvotes: 1