Asp.net mvc 如何从VOID方法重定向到MVC3中的另一个操作/控制器?

Asp.net mvc 如何从VOID方法重定向到MVC3中的另一个操作/控制器?,asp.net-mvc,model-view-controller,asp.net-mvc-3,Asp.net Mvc,Model View Controller,Asp.net Mvc 3,我有一个控制器方法,它返回一个void,因为它正在生成一个Excel报告供用户下载。我们正在使用的Excel第三方库正在写入响应本身。方法如下所示: [HttpGet] public void GetExcel(int id) { try { var report = _reportService.GetReport(id); var table = _reportService.GetReportTable(id); var excelReport = new

我有一个控制器方法,它返回一个void,因为它正在生成一个Excel报告供用户下载。我们正在使用的Excel第三方库正在写入响应本身。方法如下所示:

[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 });
  }
}
如果用户不满足获取报告的某些凭据,则有几种安全检查会引发异常。我想重定向到另一个页面,并传递一些有关异常的信息,但我不知道如何在MVC3中做到这一点


有什么想法吗?

不要让第三部分库直接写入响应,而是使用常规的
ActionResult
并返回实际文件的
文件(…)
,或者错误时返回
重定向到操作(…)
(或者
重定向到路由(…)
)。如果您的第三方库只能写响应,您可能需要使用一些技巧来捕获它的输出

[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  });
  }
}

您可以使用以下代码

Response.Redirect(Url.Action("Error", "Report", new { exceptionType = ex.GetType().Name }));
但是您看过or吗?

您可以返回:


不确定它是否有效,但尚未对其进行测试。

另一种方法是使用异常过滤器:

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"
        //    //..
        //};
    }
}
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"
        //    //..
        //};
    }
}