重复 ViewComponent 数据
Repeating ViewComponent data
我有一个客户视图模型,其中包含用于选择国家、地区和语言的下拉列表。我正在使用 ViewComponent 为下拉菜单加载必要的数据,它的工作非常顺利。我的问题是,当它们是页面上的多个客户端模型时,我多次调用外部 API 以接收相同的数据。我试图将 Component.InvokeAsync 部分放在缓存标签助手中,但它也保留了第一次调用中的元素命名并弄乱了模型绑定。有没有办法避免多次调用相同的数据?
这是代码的样子。没什么特别的。视图只是绑定属性,并没有什么特别之处。
[ViewComponent(Name = "LocationSelector")]
public class LocationSelector : ViewComponent
{
private readonly ILocationService locationsService;
public LocationSelector(ILocationService locationService)
{
this.locationsService = locationService;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var locationManager = new LocationSelectorViewModel();
locationManager.Areas = await this.locationsService.GetAreas();
locationManager.Countries = await this.locationsService.GetCountries();
return View("Default", locationManager);
}
}
然后在客户模型中调用组件,就像这样。问题是我的页面中可能有多个客户,他们都会向服务请求完全相同的数据。
@await Component.InvokeAsync(nameof(LocationSelector))
您应该考虑缓存数据。您可以使用 IMemoryCache 实现。我更喜欢创建自己的抽象层,我会在任何需要的地方使用它。
public interface ICache
{
T Get<T>(string key, Func<T> updateExpression = null, int cacheDuration=0);
}
public class InMemoryCache : ICache
{
readonly IMemoryCache memoryCache;
public InMemoryCache(IMemoryCache memoryCache)
{
this.memoryCache = memoryCache;
}
public T Get<T>(string key, Func<T> updateExpression = null,int cacheDuration=0)
{
object result;
if (memoryCache.TryGetValue(key,out result))
{
return (T) result;
}
else
{
if (updateExpression == null)
{
return default(T);
}
var data = updateExpression();
if (data != null)
{
var options = new MemoryCacheEntryOptions
{
AbsoluteExpiration = DateTime.Now.AddSeconds(cacheDuration)
};
this.memoryCache.Set(key, data, options);
return data;
}
return default(T);
}
}
}
现在在您的启动 class 的 ConfigureServices 方法中,启用缓存并定义我们的自定义 ICache-InMemoryCache 映射。
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ICache, InMemoryCache>();
services.AddMemoryCache();
}
现在您可以将 ICache
注入任何 class 并将其用于 get/store 数据。
public class LocationSelector : ViewComponent
{
private readonly ILocationService locationsService;
private readonly ICache cache;
public LocationSelector(ILocationService locationService,ICache cache)
{
this.locationsService = locationService;
this.cache = cache;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var locationManager = new LocationSelectorViewModel();
var areas = await this.cache.Get(CacheKey.Statuses, () =>
this.locationsService.GetAreas(),360);
locationManager.Areas = areas;
return View("Default", locationManager);
}
}
我有一个客户视图模型,其中包含用于选择国家、地区和语言的下拉列表。我正在使用 ViewComponent 为下拉菜单加载必要的数据,它的工作非常顺利。我的问题是,当它们是页面上的多个客户端模型时,我多次调用外部 API 以接收相同的数据。我试图将 Component.InvokeAsync 部分放在缓存标签助手中,但它也保留了第一次调用中的元素命名并弄乱了模型绑定。有没有办法避免多次调用相同的数据?
这是代码的样子。没什么特别的。视图只是绑定属性,并没有什么特别之处。
[ViewComponent(Name = "LocationSelector")]
public class LocationSelector : ViewComponent
{
private readonly ILocationService locationsService;
public LocationSelector(ILocationService locationService)
{
this.locationsService = locationService;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var locationManager = new LocationSelectorViewModel();
locationManager.Areas = await this.locationsService.GetAreas();
locationManager.Countries = await this.locationsService.GetCountries();
return View("Default", locationManager);
}
}
然后在客户模型中调用组件,就像这样。问题是我的页面中可能有多个客户,他们都会向服务请求完全相同的数据。
@await Component.InvokeAsync(nameof(LocationSelector))
您应该考虑缓存数据。您可以使用 IMemoryCache 实现。我更喜欢创建自己的抽象层,我会在任何需要的地方使用它。
public interface ICache
{
T Get<T>(string key, Func<T> updateExpression = null, int cacheDuration=0);
}
public class InMemoryCache : ICache
{
readonly IMemoryCache memoryCache;
public InMemoryCache(IMemoryCache memoryCache)
{
this.memoryCache = memoryCache;
}
public T Get<T>(string key, Func<T> updateExpression = null,int cacheDuration=0)
{
object result;
if (memoryCache.TryGetValue(key,out result))
{
return (T) result;
}
else
{
if (updateExpression == null)
{
return default(T);
}
var data = updateExpression();
if (data != null)
{
var options = new MemoryCacheEntryOptions
{
AbsoluteExpiration = DateTime.Now.AddSeconds(cacheDuration)
};
this.memoryCache.Set(key, data, options);
return data;
}
return default(T);
}
}
}
现在在您的启动 class 的 ConfigureServices 方法中,启用缓存并定义我们的自定义 ICache-InMemoryCache 映射。
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ICache, InMemoryCache>();
services.AddMemoryCache();
}
现在您可以将 ICache
注入任何 class 并将其用于 get/store 数据。
public class LocationSelector : ViewComponent
{
private readonly ILocationService locationsService;
private readonly ICache cache;
public LocationSelector(ILocationService locationService,ICache cache)
{
this.locationsService = locationService;
this.cache = cache;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var locationManager = new LocationSelectorViewModel();
var areas = await this.cache.Get(CacheKey.Statuses, () =>
this.locationsService.GetAreas(),360);
locationManager.Areas = areas;
return View("Default", locationManager);
}
}