开发者

Return either a file OR an ajax alert in MVC

Let's say I have a form with multiple options on the home page. One of these is a partial view that takes a customerID. If the customerID is valid and has products, I return a CSV file like so:

    public ActionResult CustomerProductsExport(string CustomerId)
    {

        var export = "\"ProductID\"\n";

        IEnumerable<int> products = CustomerFactory.GetProducts(CustomerId);

        export += string.Join("\n", products);

        var aFileContent = Encoding.ASCII.GetBytes(export);
        var aMemoryStream = new MemoryStream(aFileContent);
        return File(aMemoryStream, "text/plain",
                    string.Format("{0}.csv", CustomerId));

    }

There are, however, a couple cases where this will fail: either the customer ID doesn't exist, or they have no products. I would like to just return a javascript alert to indicate either of these cases. I've tried both FormMethod.Get and .Post with this:

return Javascript("alert('foo');");

But that always results in a literal string instead of running my javascript. How can I get my desired behavior or either delivering the file or giving a javascript alert wit开发者_Python百科hout the post? I've also tried both a submit button vs an ActionLink... same results.


In this kind of situation, I would return JSON that indicates the result; if successful, you then make a second request to get the actual file resource.

You would do something like this:

public ActionResult SomeMethod()
{
    if(EverythingIsOk)
      return Json(new { IsError = false, Url = "http://someUrl/" });

    return Json(new { IsError = true, Error = "You're doing it wrong" });
}

Your client receives the Json, and then checks to see if there is an error. If not, then it takes the Url and requests that resource (thus, downloading the file).


It should work if you set the content-type to application/javascript

public ActionResult CustomerProductsExport(string CustomerId)
{
    var export = "\"ProductID\"\n";
    var products = CustomerFactory.GetProducts(CustomerId);
    if (products == null)
    {
        return new ContentResult { 
            Content = "alert('Invalid customer id');",
            ContentType = "application/javascript"
        };
    }

    export += string.Join("\n", products);

    var fileContent = Encoding.ASCII.GetBytes(export);
    var stream = new MemoryStream(fileContent);
    return File(stream, "text/plain",
                string.Format("{0}.csv", CustomerId));

}

Edit

The JavascriptResult uses the obsolete application/x-javascript header which might be the cause of it not working as expected. That's why the code above should work.

See these questions:

  • Difference between application/x-javascript and text/javascript content types
  • When serving JavaScript files, is it better to use the application/javascript or application/x-javascript
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜