![](/img/trans.png)
[英]Is there a way to persist data in my Blazor Server application from within the Startup.cs file itself?
[英]How do I access data within a scoped service, annotated in Startup.cs, from a .CS file NOT a .RAZOR file using Blazor?
在我的 Blazor 應用程序中,我有一個范圍服務:
下載文件.cs
namespace MyNamespace {
public class DownloadingFile
{
public byte[] theFile { get; set; }
}
}
我在 Startup.cs 中對其進行了注釋:
啟動文件
services.AddScoped<DownloadingFile>();
我可以從 .RAZOR 文件成功訪問它:
我的文件.razor
<div @onclick="MyTask">Click Me</div>
@code {
[Inject]
private NavigationManager navigationManager { get; set; }
[Inject]
DownloadingFile downloadingFile { get; set; }
private async Task MyTask(){
APIResponse apiResponse = await APIResponse.getResponse();
downloadingFile = apiResponse.data;
navigationManager.NavigateTo("/api/Download/DownloadFile?filename=" + apiResponse.filename, true);
}
}
我有一個下載控制器:
MyNamespace
`- Controllers
`- DownloadController.cs
下載控制器.cs
namespace MyNamespace.Controllers {
[Route("api/[controller]")]
[ApiController]
public class DownloadController : ControllerBase
{
[HttpGet("[action]")]
public IActionResult DownloadFile(string filename)
{
byte[] theByteArray = new byte[] {1, 2, 3, 4, ... };
return File(theByteArray, "application/zip", filename);
}
}
}
如果我按原樣運行 Blazor 應用程序,則一切正常。
但是,如您所料,我不能在theByteArray
硬編碼,它需要是動態的。 如果我更改我的下載控制器:
namespace MyNamespace.Controllers {
[Route("api/[controller]")]
[ApiController]
public class DownloadController : ControllerBase
{
// TO THIS
private DownloadingFile downloadingFile;
public DownloadController(DownloadingFile downloadingFile)
{
this.downloadingFile = downloadingFile;
}
// OR THIS
private DownloadingFile downloadingFile;
public DownloadController() {
downloadingFile = new DownloadingFile();
}
[HttpGet("[action]")]
public IActionResult DownloadFile(string filename)
{
return File(downloadingFile.theFile, "application/zip", filename);
}
}
}
DownloadingFile
在DownloadingFile
始終為null
。
編輯:澄清一下,我通過在控制器中實例化 DownloadingFile 創建的對象不為空,它是我期望在那里的字節數組為空。
如果我可以將字節數組從 .RAZOR 文件獲取到 .CS 文件,一切都會好起來的。 我該怎么做?
讓我們看看你的代碼:
APIResponse apiResponse = await APIResponse.getResponse();
downloadingFile = apiResponse.data;
navigationManager.NavigateTo("/api/Download/DownloadFile?filename=" + apiResponse.filename, true);
為什么將downloadingFile
設置為APIResponse.data
? 這是一個注入的服務。 你不要重新分配它。
在控制器的第二個版本中
private DownloadingFile downloadingFile;
public DownloadController(DownloadingFile downloadingFile)
{
this.downloadingFile = downloadingFile;
}
您正在注入DownloadingFile
,但這與 Blazor 會話中的實例不同。 它是為服務器端調用控制器而創建的新實例,並且downloadingFile.theFile
為空。
您可以執行以下操作來跟蹤服務實例:
public class ScopedService
{
public Guid ID => Guid.NewGuid();
public ScopedService()
{
Debug.WriteLine($"New ScopedService ID:{ID}");
}
}
“我該怎么做?” 從您的代碼中看不出您實際下載的是什么以及從何處下載,因此很難回答。
正如MrC aka Shaun Curtis所說:由於客戶端和服務器是不同的范圍,並且您將DownloadingFile
服務作為范圍服務注入,因此您設置downloadingFile = apiResponse.data
的DownloadingFile
實例與您嘗試檢索的實例不同這就是文件為NULL
。
在我看來,您的目標是向用戶提供文件下載。 現在(假設您的代碼有效)您正在前端下載一個文件並嘗試將其設置為后端服務,然后在 HTTP 響應中將其返回給用戶。 如果不首先實際發送 HTTP 請求,這顯然是不可能的。
相反,您應該簡單地導航到您想要的文件所在的 URL。 為此,您需要將按鈕換成瀏覽器的標簽以允許它。
<a class="btn" href="https://myapiurl.com/filename" role="button">Click Me</a>
嘗試安裝此擴展BlazorDownloadFile
然后注冊它的服務
builder.Services.AddBlazorDownloadFile(ServiceLifetime.Scoped);
如果在此階段您已經擁有文件字節:
APIResponse apiResponse = await APIResponse.getResponse();
downloadingFile = apiResponse.data;
假設您的文件是 pdf,您可以:
@inject IBlazorDownloadFileService _blazorDownloadFile
APIResponse apiResponse = await APIResponse.getResponse();
_blazorDownloadFile.DownloadFile("myFile.pdf", apiResponse.data, "application/pdf");
如果需要,您可以處理更多MIME 類型。
冒着向這條破碎的記錄添加另一個跳過的風險:您的剃刀組件和您的控制器使用不同的范圍。 您可能在一個代碼庫中擁有所有內容,但框架的不同模塊對作用域的處理方式不同。
控制器的范圍僅限於單個 HTTP 請求。 每次發出請求時都會實例化和處理服務。 在 Blazor 服務器中,服務的范圍僅限於客戶端和服務器之間的 SignalR 連接/電路。
這些范圍不共享。 引用 Blazor 文檔中關於依賴注入的內容(粗體強調我的):
應用程序的 Razor 頁面或MVC 部分正常處理范圍服務,並在頁面或視圖之間導航或從頁面或視圖導航到組件時在每個 HTTP 請求上重新創建服務。 在客戶端上的組件之間導航時,不會重建范圍服務,其中與服務器的通信是通過用戶電路的 SignalR 連接而不是通過 HTTP 請求進行的。
我仍然不確定您為什么要以這種方式做事,但我認為在 ASP.NET Core DI 基礎結構的上下文中您的要求是不可能的,除非您使您的服務成為單例。
我會遵循其他海報的建議,並將用戶指向 API,以與在組件中相同的方式獲取文件。 如果存在安全問題,是否將其設為受保護的端點?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.