如何绕过 blazor wasm 路由系统并调用服务器

Posted

技术标签:

【中文标题】如何绕过 blazor wasm 路由系统并调用服务器【英文标题】:How to bypass blazor wasm routing system and make calls to the server 【发布时间】:2021-06-02 14:38:20 【问题描述】:

我有一个 blazor wasm 托管应用程序,用户可以通过填写表格来创建帐户。创建帐户后,会向用户发送一封电子邮件,其中包含他/她必须遵循的链接以确认他/她对电子邮件地址的所有权。该链接指向我的服务器中的一个操作方法。同一台服务器托管 blazor wasm 应用和 API。

问题是,当用户单击该链接时,请求不会发送到服务器。相反,blazor 会拦截调用并尝试路由到页面。

我怎样才能做到这一点?如何创建指向我服务器中的操作的链接实际上在单击时将其发送到服务器?换句话说,如果可能的话,如何绕过 blazor 的路由系统?

更新:

我使用 Identity 作为后备存储(但这与我遇到的问题无关)。 我使用基本控制器Url.Action("actionName", "controllerName", actionParam, Request.Scheme); 中的Url 属性生成链接。目前,该链接看起来像 https://localhost:5001/api/user/confirmaemail?confirmationtoken=xyz&useremail=abc Action 是一个发布操作。 当 blazor 尝试重定向到页面时,它显然不能,因为我没有具有这种路由的页面。因此会显示<NotFound /> 组件(App.razor 文件)中的内容。

注意: 这不是错误。这是 balzor wasm 的正常行为。如果应用托管在www.foo.com,那么所有对foo.com(例如www.foo.com/bar)的调用实际上都不会发送到foo.com,而是会被blazor拦截并视为应用中页面的路由.但是,这阻止了我,因为我的 API 与应用程序具有相同的基地址(该应用程序目前位于 localhost:5001/,API 位于 localhost:5001/api/xyz),因此,blazor 阻止调用服务器时我点击链接。问题是如何解决这个问题?如果不可能,我还需要哪些其他选项来实现此流程?

【问题讨论】:

您在项目中使用身份吗?此链接如何请求服务器(获取或发布)?重定向到其他页面时是否有任何错误? @Karney。我更新了帖子以回答您的问题。 这能回答你的问题吗? What are the ways for client side blazor to fetch data from server? @GSerg 不是。您指向的问题更多是关于 blazor wasm(客户端)和 blazor 服务器端之间的区别。 它告诉你必须使用 HttpClient 或排序从客户端 Blazor 进行 POST 调用。 【参考方案1】:

所以我通过将 Action 方法设置为 GET 方法而不是 POST 来解决问题。仔细想想,这很合乎逻辑:当用户点击他/她通过电子邮件收到的链接时,将发出 GET,而不是 POST。

我还了解到,仅当您在地址栏中输入地址时,blazor 才会将您路由到页面。如果您单击链接,将发出请求。我认为 blazor 拦截请求的原因是因为单击链接会将我重定向到一个页面,但实际上,它只是一种后备机制。您可以在configure 方法中看到它:

app.UseEndpoints(endpoints =>
        
            endpoints.MapRazorPages();
            endpoints.MapControllers();

            // the link clicked issues a GET. My action is a POST.
            // So no action is found. It falls back to the index.html
            // which is the entery point of my app. Blazor takes over 
            // from here and tries to find a page for the url requested.
            endpoints.MapFallbackToFile("index.html");
        );

【讨论】:

【参考方案2】:

我有同样的问题。我使用 JS Interop 来修复它。代码如图所示。

在 /wwwroot/index.html 中添加以下脚本。

<script>
        function downloadfile(filename, fileContent) 
            var element = document.createElement('a');
            element.setAttribute('href', fileContent);
            element.setAttribute('download', filename);
            document.body.appendChild(element);
            element.click();
            document.body.removeChild(element);
        
</script>

在 Blazor WASM Razor 组件中,在 @code 中添加以下函数。

private async void DownloadFile(string fileName)

    //Get the file from the Server Side
    //Convert fileName string to String Content
    var response = await httpService.PostAsync(
       url:"/api/download", content:fileNameStringContent);

    if (response.IsSuccessStatusCode)
    
       var content = await response.Content.ReadAsStringAsync();
       await JSRuntime.InvokeVoidAsync("downloadfile", fileName, content);
    
  

在服务器中添加下面的Controller.Action

[HttpPost("download")]
public async Task<string> Download(string fileName)

    var fileContent = GetFileAsBytes(fileName);
    
    var base64String = "data:application/pdf;base64," + Convert.ToBase64String(fileContent);
    
    return base64String;


private async Task<byte[]> GetFileAsBytes(string fileName)

    try
    
        var folderPath = Path.Combine(_env.ContentRootPath, "folder");\
        if (!Directory.Exists(folderPath))
            return null;

        var filePath = Path.Combine(folderPath, fileName);
        if (!File.Exists(filePath))
            return null;

        var fileBytes = await File.ReadAllBytesAsync(filePath);
        return fileBytes;
    
    catch
    
        return null;
    

【讨论】:

以上是关于如何绕过 blazor wasm 路由系统并调用服务器的主要内容,如果未能解决你的问题,请参考以下文章