How to redirect to another Action / Controller in MVC3 from VOID method?

I have a controller method that returns void because it creates an Excel report for user to download. The third-party Excel library that we use records the response itself. The method looks something like this:

[HttpGet] public void GetExcel(int id) { try { var report = _reportService.GetReport(id); var table = _reportService.GetReportTable(id); var excelReport = new ExcelReport(table, report.Name); excelReport.DownloadReport(System.Web.HttpContext.Current.Response); } catch (Exception ex) { // This is wrong, of course, because I'm not returning an ActionResult Response.RedirectToRoute("/Report/Error/", new { exceptionType = ex.GetType().Name }); } } 

There are several security checks that throw exceptions if the user does not meet certain credentials to receive the report. I want to redirect to another page and pass some exception information, but I cannot figure out how to do this in MVC3 ....

Any ideas?

+7
source share
4 answers

You can do

 Response.Redirect(Url.Action("Error", "Report", new { exceptionType = ex.GetType().Name }); 

But did you take a look at FilePathResult or FileStreamResult ?

+8
source

Instead of letting the 3rd part library write the answer directly, use the usual ActionResult to get the contents and return File(...) for the actual file or RedirectToAction(...) (or RedirectToRoute(...) ) if an error occurs. If your third-party library can only write in Response, you may need to use some tricks to output it.

 [HttpGet] public ActionResult GetExcel(int id) { try { var report = _reportService.GetReport(id); var table = _reportService.GetReportTable(id); var excelReport = new ExcelReport(table, report.Name); var content = excelReport.MakeReport(System.Web.HttpContext.Current.Response); return File(content, "application/xls", "something.xls"); } catch (Exception ex) { RedirectToRoute("/Report/Error/", new { exceptionType = ex.GetType().Name }); } } 
+2
source

You can return EmptyActionResult :

 [HttpGet] public ActionResult GetExcel(int id) { try { var report = _reportService.GetReport(id); var table = _reportService.GetReportTable(id); var excelReport = new ExcelReport(table, report.Name); excelReport.DownloadReport(System.Web.HttpContext.Current.Response); return new EmptyResult(); } catch (Exception ex) { return RedirectToAction("Error", "Report", rnew { exceptionType = ex.GetType().Name }); } } 

Not sure if it works, have not tested it.

+2
source

Another approach would be to use an exception filter:

 public class MyExceptionFilter : FilterAttribute, IExceptionFilter { public void OnException(ExceptionContext filterContext) { var routeValues = new RouteValueDictionary() { { "controller", "Error" }, { "action", "Report" } }; filterContext.Result = new RedirectToRouteResult(routeValues); filterContext.ExceptionHandled = true; // Or I can skip the redirection and render a whole new view //filterContext.Result = new ViewResult() //{ // ViewName = "Error" // //.. //}; } } 
0
source

All Articles