C# Asp MVC中在ViewModel中填充查找值的最佳实践

C# Asp MVC中在ViewModel中填充查找值的最佳实践,c#,asp.net-mvc,asp.net-core,viewmodel,C#,Asp.net Mvc,Asp.net Core,Viewmodel,我有一个小的web mvc虚拟应用程序,其中有一个创建表单(使用viewmodel)。视图模型具有有界值和无界值(例如查找)。但首先,您可以看到下面的示例代码: // ///我是持久层的模型。 /// 公共类产品 { 公共产品() { } 公共产品(int-id,字符串名称) { Id=Id; 名称=名称; } 公共int Id{get;set;} 公共字符串名称{get;set;} } /// ///我最适合观看。 ///您可以给我一个名称并选择一种产品。 /// 公共类DummyVie

我有一个小的web mvc虚拟应用程序,其中有一个创建表单(使用viewmodel)。视图模型具有有界值和无界值(例如查找)。但首先,您可以看到下面的示例代码:

//
///我是持久层的模型。
/// 
公共类产品
{
公共产品()
{
}
公共产品(int-id,字符串名称)
{
Id=Id;
名称=名称;
}
公共int Id{get;set;}
公共字符串名称{get;set;}
}
/// 
///我最适合观看。
///您可以给我一个名称并选择一种产品。
/// 
公共类DummyViewModel
{
[Microsoft.AspNetCore.Mvc.HiddenInput()]
公共int Id{get;set;}
公共字符串名称{get;set;}
public int ProductId{get;set;}
公共IEnumerable ProductLookup{get;set;}
}
公共类DummyController:Controller
{
[HttpGet]
public IActionResult Create()
{
var dummyViewModel=新的dummyViewModel()
{
Name=“新建虚拟”,
};
UpdateLookupsOnViewModel(dummyViewModel);
返回视图(dummyViewModel);
}
/// 
///如果客户填写了创建表单,我将使用pingback操作方法。
///如果给定的viewmodel无效或保存失败
///将返回给定的viewmodel。
///如果发生这种情况,那么它将丢失所有查找。
///因此,在这两种情况下,它们必须再次更新。
/// 
[HttpPost]
公共IActionResult创建(DummyViewModel虚拟机)
{
if(vm==null | |!ModelState.IsValid)
{
//1.给定的viewmodel无效,请更新查找。
UpdateLookupsOnViewModel(vm);
返回视图(vm);
}
尝试
{
//存进回购。
抛出新异常(“伪异常,它在保存时模拟错误。”);
返回重定向(“stackoverflow.com”);
}
抓住
{
//2.保存失败,请更新查找。
UpdateLookupsOnViewModel(vm);
返回视图(vm);
}
}
私有void UpdateLookupsOnViewModel(DummyViewModel虚拟机)
{
if(vm为null)
{
抛出新ArgumentNullException(nameof(vm));
}
vm.ProductLookup=GetProductsFromRepository()
.Select(o=>newselectListItem(o.Name,o.Id.ToString());
}
/// 
///我模拟对数据库的访问。
/// 
私有IEnumerable GetProductsFromRepository()
{
返回新的[]
{
新产品(1,“我的产品”),
新产品(2,“BB Super”),
新产品(3,“Jooooe”),
新产品(4,“Igel”),
};
}
}
下面可以看到ASP HTML视图

@使用experience.Web.ViewModels
@模型DummyViewModel
我的问题您可以在注释中看到,但简而言之:viewmodel(ProductLookup)中的非限定值

如果客户端使用HTTP Get请求创建表单,则会创建一个新的DummyViewModel。如果他填写了所有必需的值,他将使用HTTP-POST并将DummyViewModel发送给控制器操作。 如果控制器操作检测到给定的viewmodel无效或保存过程失败,则控制器会将给定的viewmodel发送回客户端。 如果发生这种情况,所有非有界值都将丢失,因此必须在viewmodel上再次更新这些值

我的查找值存储在数据库中(在real app中)。所以这可能是一个性能问题

现在我想知道其他人是如何处理这种情况的。你使用缓存吗?当我在返回之前忘记调用UpdateLookupsOnViewModel时会发生什么情况? 你有一些有帮助的编码风格或任何模式吗


谢谢你的阅读

我认为没有这样的最佳实践,只有不同的方法

就我个人而言,我认为你的
UpdateLookupsOnViewModel
方法是最好的选择;但是,如果您的存储库中的I/O性能是一个问题,您可以使用
TempData
Session
将这些值保存在内存中。另一种方法是将值存储在隐藏字段中,可能是JSON或分隔字符串,然后将其发回并重建列表


不幸的是,HTTP是无状态的,所以这些只是模拟应用程序中状态的不同方式。

当我们谈论web时,我调用一个方法来填充查找两次:一个用于
GET
(通常)另一个用于“异常”(
POST
-无效提交的数据,等等)。但是,这会降低性能,因为我一直在使用DB

我找到的解决办法是。但是,为了定义缓存策略,您需要考虑您拥有什么样的查找数据(它的更改频率、大小、应该在缓存中保留多长时间等等)

我对缓存的一般规则是使用不同的缓存键(“cache\u prod”、“cache\u prod\u type”)将所有查找分隔开,这样您就可以只重建发生更改时发生的查找

您可能可以这样做:

private void UpdateLookupsOnViewModel(DummyViewModel vm)
{
    if (vm is null)
    {
        throw new ArgumentNullException(nameof(vm));
    }

    vm.ProductLookup = GetProductFromCache("cache_product");
}
private Product GetProductFromCache(string cacheKey)
{
    IMemoryCache _memoryCache;
    Product product;
    if (!_memoryCache.TryGetValue(cacheKey, out product))
    {
        product = GetProductsFromRepository()
                    .Select(o => new SelectListItem(o.Name, o.Id.ToString()));
    }

    return product;
}
方法
GetProductFromCache
大致如下:

private void UpdateLookupsOnViewModel(DummyViewModel vm)
{
    if (vm is null)
    {
        throw new ArgumentNullException(nameof(vm));
    }

    vm.ProductLookup = GetProductFromCache("cache_product");
}
private Product GetProductFromCache(string cacheKey)
{
    IMemoryCache _memoryCache;
    Product product;
    if (!_memoryCache.TryGetValue(cacheKey, out product))
    {
        product = GetProductsFromRepository()
                    .Select(o => new SelectListItem(o.Name, o.Id.ToString()));
    }

    return product;
}

如果你有一个像Kendo这样的工具,你可以让它自己调用AJAX来填充下拉列表。