Blazor WebAssembly app does not recognize file download after getting published

Tonrin17 1 Reputation point
2022-09-28T12:51:44.89+00:00

Hi,

I develop Blazor WebAssemly application.

One of the application feature is to allow to download files from API service.

In the API controller that provides files to download I have following method:

public async Task<IActionResult> DownloadApplicationAsync([FromQuery] string sessionId, [FromRoute] string applicationIdentifier)  
{  
    return File(Content, "application/zip", FileName);  
}  

In the WebAssembly client there is button with link to the application to download:

<a class="btn btn-secondary downloadlink" style="background-color:green" href="@GenerateDownloadLinkForApplication(application)">Download</a>  

GenerateDownloadLinkForApplication method returns:

https://localhost:5556/Application/s8ds8emmjkjre/Download?sessionId=o23nW96RL842ZLKGJ80wr4M1

When the code is built and run using Visual Studio, click on the Download button triggers File/Folder selection dialog to select location and filename for the file.

This is expected result.

Unfortunately, when I publish the application to folder the behaviour is different.

Click on the Download button causes application to open page (that obviously does not exists) from the Url above instead of triggering the download dialog.

Here is my publish profile:
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<DeleteExistingFiles>true</DeleteExistingFiles>
<ExcludeApp_Data>false</ExcludeApp_Data>
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Development</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>bin\Development\net6.0\publish\</PublishUrl>
<WebPublishMethod>FileSystem</WebPublishMethod>
<_TargetId>Folder</_TargetId>
<SiteUrlToLaunchAfterPublish />
<TargetFramework>net6.0</TargetFramework>
<ProjectGuid>2cf9b043-c1da-4bb2-8cf0-a5e8f768737f</ProjectGuid>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>

Additional results:

  1. Run the application from build output
    • Download button triggers download dialog to save file
    • Paste the link into a browser url bar triggers download dialog to save file
    • Right click on the download button and select "Save target as..." triggers download dialog to save the file
  2. Run the application from published files
    • Download button causes application to open a different page that does not exists
    • Paste the link into a browser url bar causes application to open a different page that does not exists
    • Right click on the downlaod button and select "Save target as..." triggers download dialog to save the file
    • Adding "www" into url and paste the link into a browser url bar triggers download dialog to save file

Why publishing changes this behaviour? Do I need to change any configuration to make application to work with results from first case?

Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,419 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 57,886 Reputation points
    2022-09-29T20:09:30.91+00:00

    to implement page navigation, blazor (via a javascript routine) catches browser navigation requests. it then determines if it is a blazor route or external navigation route. if blazor route than the url is passed to blazor otherwise the routine lets the browser navigate.

    the easiest fix is to put a target="_blank" on the link, so routing is bypassed. this will also allow error display without unloading the blazor app.


  2. Tonrin17 1 Reputation point
    2022-10-05T12:27:26.11+00:00

    After opening an issue on GitHub I got answer on this question.
    https://github.com/dotnet/aspnetcore/issues/44368

    Since I do not need any files to be cached, I commented out one line (line 6) from service-worker.published.js file.

    async function onInstall(event) {  
        console.info('Service worker: Install');  
      
        // Fetch and cache all matching items from the assets manifest  
        const assetsRequests = self.assetsManifest.assets  
            //.filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))  
            .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))  
            .map(asset => new Request(asset.url, { integrity: asset.hash, cache: 'no-cache' }));  
        await caches.open(cacheName).then(cache => cache.addAll(assetsRequests));  
    }  
    
    0 comments No comments