ASP.Net core redirect to an action which return FileStreamResult

801 Views Asked by At

I have to actions in a controller:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{

    [HttpGet("redirect1")]
    public IActionResult Redirect1()
    {
        var r = RedirectToAction(nameof(GetStream));
        return r;
    }


    [HttpGet("stream")]
    public IActionResult GetStream()
    {
        var ms = new MemoryStream(Encoding.UTF8.GetBytes("Hello Word"));
        return File(ms, "application/octet-stream", "test.xyz", true);            
    }
}

When I typed https://localhost:44352/api/values/redirect1, the save as dialog is open for download but the url in browser is not changed to https://localhost:44352/api/values/stream. Is a way to change also the url. In case the GetStream action return a json the url is changed to https://localhost:44352/api/values/stream. How is possible also to change the url in case I return FileStreamResult.

Is possible to have something in the view like "waiting..." and return FileStreamResult

2

There are 2 best solutions below

8
itminus On

How is possible also to change the url in case I return FileStreamResult?

You can return a HTML to make it:

public IActionResult Redirect1()
{
    var r = RedirectToAction(nameof(GetStream));
    return r;                                   
    var url = this.Url.Action(nameof(GetStream));    
    return Content(
        $"<script>history.pushState({{}},'downloading','{url}');history.go()</script>",
        "text/html"
    );
}

The key is spelling the magic from JavaScript so that you can change the browser behavior as you like.

Is possible to have something in the view like "waiting..." and return FileStreamResult

Again, you can do that by a HTML Content. Lets' say you want to display a waiting... message and trigger the downloading in 1 second:

public IActionResult Redirect1()
{
    var url = this.Url.Action(nameof(GetStream));
    return Content($"<div id='msg'>waiting...</div><script>history.pushState({{}},'downloading','{url}'); setTimeout(function(){{document.getElementById('msg').textContent='';history.go();}}, 1000);</script>","text/html");
}

What if your javascript goes more complicated? Simply create a cshtml View and put the content within a View file.

0
Toader Ioan On

Thanks, Maybe I have to describe more my problem. I Have an action which return a FileFileStreamResult and is authorized using OpenIdConnect and IdentityServer4 Authority. This action is called from angular web application in a new tab. If the browser know the mime type will display the content of stream if not will show the save dialog and the tab is closed by the browser. This work perfect unless first time when the authentication is done the tab is not closed automatically by the browser becouse the url of the browser is not updated. The URLs sequence in dev tools are:

  1. https://taxmart-portal-dev-v2.taxmaxng.eu/api/active-data-marts/21933e46-c4e5-44cc-b49b-a6bf3636ba44/objects/11/content
  2. https://taxmart-identity-dev-v2.taxmaxng.eu/connect/authorize?client_id=...
  3. https://taxmart-portal-dev-v2.taxmaxng.eu/signin-oidc
  4. https://taxmart-portal-dev-v2.taxmaxng.eu/api/active-data-marts/21933e46-c4e5-44cc-b49b-a6bf3636ba44/objects/11/content

but the browser display the URL from point 2.

Can somebody know how to do to be display the URL from point 4.

Ioan Toader

Thanks