簡體   English   中英

如何繞過blazor wasm路由系統並調用服務器

[英]How to bypass blazor wasm routing system and make calls to the server

我有一個 blazor wasm 托管應用程序,用戶可以在其中通過填寫表格來創建帳戶。 創建帳戶后,會向用戶發送一個 email,其中包含一個鏈接,用戶必須點擊該鏈接以確認他/她對 email 地址的所有權。 該鏈接指向我服務器中的一個操作方法。 同一台服務器托管 blazor wasm 應用程序和 API。

問題是,當用戶單擊該鏈接時,請求不會發送到服務器。 相反,blazor 會攔截調用並嘗試路由到頁面。

我怎樣才能使這項工作? 我怎樣才能創建一個指向我服務器中的操作的鏈接,在單擊時實際上將它發送到服務器? 換句話說,如果可能的話,如何繞過 blazor 的路由系統?

更新:

  • 我使用 Identity 作為后備存儲(這與我遇到的問題無關)。
  • 我使用基礎中的 Url 屬性生成鏈接 controller Url.Action("actionName", "controllerName", actionParam, Request.Scheme); . 該鏈接目前看起來像https://localhost:5001/api/user/confirmaemail?confirmationtoken=xyz&useremail=abc
  • 該動作是一個后期動作。
  • 當 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 阻止了單擊鏈接時調用服務器。 問題是如何解決這個問題? 如果不可能,我還有哪些其他選擇來實施此流程?

所以我通過將 Action 方法設置為 GET 方法而不是 POST 來解決問題。 仔細想想,這很合乎邏輯:當用戶點擊他/她通過 email 收到的鏈接時,將發出 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");
        });

我遇到過同樣的問題。 我使用 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 中添加以下 function。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM