我正在学习ASP.NET Core
,我对加载大量记录有一些疑问,让我更好地解释一下。
我想做什么
在我的应用程序中,登录执行后,用户将重定向到Dashboard Home View
。 Dashboard
是包含用户所有功能的地方。 Dashboard Controller
也有其他Views
像:
现在每个View
需要向用户显示一个包含Table
列表的Products
,在这个Table
的底部有View
的内容。
问题
第一个问题:是Table
冗余码,我解决了创建一个_PartialView
,其中包含html
的Table
,其中包含要显示的产品。来自c#+ WPF,我使用了UserControl
的相同逻辑,所以这对我来说是一个很好的解决方案。
第二个问题:在Table
内显示的产品,这些产品是从API
下载的,现在正如我之前所说,这些记录必须始终显示在产品Table
(使用View
可以在不同的_PartialView
中获得)。想象一下,每次用户点击Dashboard
项目(加载Dashboard View
)时,Dashboard Controller
都会调用此方法:
public async Task<List<Products>> GetProducts(string date)
{
var client = new RestClient(Url);
var request = new RestRequest("product/get_products/{date}", Method.GET);
request.AddUrlSegment("date", date);
var cancellationTokenSource = new CancellationTokenSource();
var response = await client.ExecuteTaskAsync(request, cancellationTokenSource.Token);
List<Products> products = JsonConvert.DeserializeObject<List<Product>>(response.Content);
return products;
}
对我来说,这不是一个很好的做法,因为每次_PartialView
都会调用这个方法并重新加载数据,所以我需要以某种方式存储这些数据(临时存储)。每次调用_PartialView
时,如何在不重新加载的情况下将这些记录存储到用户会话中?
之间,我对API
方法有一些疑问:我应该将所有API
调用放在Service
文件夹中吗? Repository
文件夹?还是Controller
文件夹?
文件夹树
View <- Folder
Dashboard <- Folder
Home
Analysis
Performance
_ProductsTable
View
Home, Analysis, Performance
以下列方式加载_ProductsTable
:
@await Html.PartialAsync("_LeftSidebar")
使用视图组件。它们本质上是自包含的返回视图的功能模块,您可以将其嵌入到其他视图中,而无需主视图或操作必须知道任何视图。
首先,创建一个目录调用ViewComponents
。在里面添加新类,如ProductsViewComponent
。那么,你会想要这样的东西:
public class ProductsViewComponent : ViewComponent
{
private readonly HttpClient _client;
public ProductsViewComponent(HttpClient client)
{
_client = client ?? throw new ArgumentNullException(nameof(client));
}
public async Task<IViewComponentResult> InvokeAsync(string date)
{
using (var response = await _client.GetAsync($"/"product/get_products/{date}"))
{
response.EnsureSuccessStatusCode();
var products = await response.Content.ReadAsAsync<List<Product>>();
return View(products);
}
}
}
然后,创建视图Views\Shared\Components\Products\Default.cshtml
。在里面,添加HTML以呈现您的产品列表。最后,在您希望产品表显示的位置添加:
@await Component.InvokeAsync("Products", new { date = myDate })
上面的代码使用HttpClient
而不是RestClient
,因为老实说,此时完全没有必要使用单独的库来进行HTTP调用。 HttpClient
是内置的,并且已经扩展了Core中的功能,使这更容易,例如上面使用的ReadAsAsync
方法,它将JSON响应透明地反序列化为泛型类型参数。此外,你现在有像IHttpClientFactory
这样的东西,可以确保你有适当的范围HttpClient
实例。因此,上面的代码还假设在Startup.cs
中添加如下内容:
services.AddHttpClient<ProductsViewComponent>(c =>
{
c.BaseAddress = new Uri('https://api.myservice.com');
// add default headers and such if you need them
});
然后,您还可以使用Polly集成来设置自动重试,断路器等,允许您处理各种API方案,例如暂时不可用,速率限制等。有关更多信息,请参阅IHttpClientFactory
及其Polly integration的完整文档。 。
最后,如果这是您不需要实时数据的情况,您还可以将IDistributedCache
的实例注入到视图组件中,并添加逻辑以设置API调用的结果,并在此之前从中检索它再次拨打电话,可以显着降低应用和API的负载(特别是如果有适用速率限制的话)。