从Asp.net-mvc控制器操作返回文件或错误消息的最佳方法是什么?

时间:2014-01-03 02:24:28

标签: jquery asp.net-mvc powerpoint fileresult

我的asp.net-mvc项目中有以下javascript代码和控制器操作:

使用Javascript:

$("#exportPPT").live('click', function (e) {
    window.location.href = "/Initiative/GenerateFile" + GenerateParams();
});

C#Controller:

    public ActionResult GenerateFile(MyParams myParams)
    {
        var template = Server.MapPath(PPT_ROOT + "/template.pptx");
        IEnumerable<Order> orders = Model.GetOrders(myparams);
        var pptResults = GeneratePowerpointFile(orders);
        return File(pptResults.Content, "application/vnd.ms-powerpoint", pptResults.FileName);
    }

但在某些条件下,让我们说当orders.Count()为0时,我宁愿向用户发回一条错误消息,说明你有错误。

根据上述代码,实现此目标的最佳方法是什么?我想把它改成ajax调用,但我不知道如何在json请求中下载我的Fie()和包(如果支持的话)。

有什么建议吗?

7 个答案:

答案 0 :(得分:10)

我会向另一个检查订单计数的控制器操作发起$ .get请求。返回该值,并在适当的情况下返回错误消息。在需要时显示错误消息,否则处理重定向以下载文件。这是对控制器的额外调用,但它允许您完全控制并处理错误的可能性,而无需重定向您的用户。

$("#exportPPT").live('click', function (e) {
  $.get( "/Initiative/CheckForOrders" + GenerateParams(), function( data ) {
    if (data.IsValid) {
      window.location.href = "/Initiative/GenerateFile" + GenerateParams();
    } else {
      alert(data.ErrorMessage); // or show a div containing error message
    }
  });
});

控制器操作:

public ActionResult CheckForOrders(MyParams myParams)
{
  IEnumerable<Order> orders = Model.GetOrders(myparams);
  if (orders.Any())
    return Json(new { IsValid=true }, JsonRequestBehavior.AllowGet);

  return Json(new { IsValid=false, ErrorMessage="No orders" }, JsonRequestBehavior.AllowGet);
}

答案 1 :(得分:5)

我会返回一个状态,表示资源不存在并返回null?然后你可以在你的javascript中相应地处理它而不用担心做多个ajax调用来检查一个是否可用,或者如果有人绕过这样的检查就会产生安全隐患。

例如......

<强>控制器

public ActionResult GenerateFile(MyParams myParams)
{
    var template = Server.MapPath(PPT_ROOT + "/template.pptx");
    IEnumerable<Order> orders = Model.GetOrders(myparams);

    if(!orders.Any()){
        Response.StatusCode = (int)HttpStatusCode.NotFound
        Response.StatusDescription = HttpStatusCode.NotFound.ToString();
        Response.TrySkipIisCustomErrors = true;
        return EmptyResult;
    } 

    var pptResults = GeneratePowerpointFile(orders);
    return new File(pptResults.Content, "application/vnd.ms-powerpoint", pptResults.FileName);
}

答案 2 :(得分:1)

if (count==0) return View();
else return File(...)

不能这样吗?

答案 3 :(得分:1)

如果orders.Count()为0或发生其他错误,我建议重定向用户。 这样的事情。

public ActionResult GenerateFile(MyParams myParams)
{
    var template = Server.MapPath(PPT_ROOT + "/template.pptx");
    IEnumerable<Order> orders = Model.GetOrders(myparams);
    if(orders.Count() == 0){
       return RedirectToAction("Orders","ordersError",new { ID = "Error message"});
    }else{
       var pptResults = GeneratePowerpointFile(orders);
       return File(pptResults.Content, "application/vnd.mspowerpoint",pptResults.FileName);
    }
}

所以你做了一个信息性的ordersError视图,显示你的错误信息。

答案 4 :(得分:1)

如果您必须处理内部服务器错误,则必须设置自定义过滤器,将其应用于您的控制器方法,该方法拦截磁盘相关错误或任何错误,并正常处理,并返回您的视图一些有意义的数据消息。

请参阅这篇文章,关于创建asp.net mvc过滤器以及相关的javascript代码。

ASP.NET MVC Ajax Error handling

答案 5 :(得分:1)

也许这篇文章可能有用: Download File Using Javascript/jQuery

我相信JQuery File Download plugin值得一些关注,它会优雅地处理错误:)看一看它的在线演示......

答案 6 :(得分:1)

@Anthony Shaw 的答案很好,但有两个问题:

  1. 如果您使用 try{} catch{} 那么您在导出文件过程中遇到错误会怎样?
  2. 如何在保持当前页面的同时更友好地返回消息?

答案是您应该使用 Ajax 分两步实现:

  1. 您应该调用 ajax 来生成一个文件,并将该内存数据存储到 SessionTempData 中。

Ajax

$ajax({
    cache: false,
    url: '/Initiative/GenerateFile',
    data: GenerateParams(), 
    success: function (data){
         var response = JSON.parse(data);
         if(response.IsSuccesful) {
           window.location = '/Initiative/DownloadFile?fileGuid=' + response.FileGuid 
                           + '&filename=' + response.FileName;
         }else{
           alert(response.ErrorMessage);
         }
    }
});

控制器

    public ActionResult GenerateFile(MyParams myParams)
    {
        IEnumerable<Order> orders = Model.GetOrders(myparams);
        if (orders.Count() == 0)
        {
            return new JsonResult
            {
                Data = new { IsSuccesful = false, ErrorMessage = "No orders" }
            };
        }
        try
        {
            var pptResults = GeneratePowerpointFile(orders);
            var guid = Guid.NewGuid().ToString();
            TempData[guid] = pptResults.Content;
            return new JsonResult
            {
                Data = new { IsSuccesful = true, FileGuid = guid, FileName = pptResults.FileName }
            };
        }
        catch (Exception err)
        {
            return new JsonResult
            {
                Data = new { IsSuccesful = false, ErrorMessage = err }
            };
        }

    }
  1. 创建一个新的 DownloadFile 操作来读取 TempData[guid],然后也返回该文件。

    [HttpGet]
    public virtual ActionResult DownloadFile(string fileGuid, string fileName)
    {
        if (TempData[fileGuid] != null)
        {
            var data = TempData[fileGuid] as byte[];
            return File(data, "application/vnd.ms-powerpoint", fileName);
        }
        else
        {
            return new EmptyResult();
        }
    }
    

值得阅读的好文章Download Excel file via AJAX MVC