What is the best way to return File or ErrorMessage from Asp.net-mvc controller action?

leora picture leora · Jan 3, 2014 · Viewed 8.6k times · Source

I have the following javascript code and controller action in my asp.net-mvc project:

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

but under certain conditions, lets say when orders.Count() is 0 then instead of generating a file, i would rather have an error message back to the user saying that you have an error.

What is the best way to achieve this given the code above? I thought of changing it to an ajax call but i wasn't sure how to download my Fie() and package that inside a json request (or if that was supported).

Any suggestions?

Answer

Anthony Shaw picture Anthony Shaw · Jan 14, 2014

I would initiate a $.get request to another controller action that would check for the order count. Return that value, along with an error message if appropriate. Display the error message when it's needed, otherwise process your redirect to download your file. It's an extra call to the controller but it allows you to have full control and handle the possibility of an error without redirecting your user.

$("#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
    }
  });
});

Controller Action:

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