1

同样的问题不断出现。我有一个没有任何持久支持的 viewModel。它只是一个用于生成搜索输入表单的 ViewModel。

我想根据用户输入的值构建一个大的 where 子句。如果 Action 接受作为参数 SearchViewModel 如何在不将 viewModel 传递给服务层的情况下执行此操作?服务不应该知道 ViewModel 对吗?哦,如果我序列化它,那么它将是一个大字符串,并且键/值将是强类型的。

SearchViewModel这只是一个片段。

[Display(Name="Address")]
  public string AddressKeywords { get; set; }

        /// <summary>
        ///     Gets or sets the census.
        /// </summary>
        public string Census { get; set; }

        /// <summary>
        ///     Gets or sets the lot block sub.
        /// </summary>
        public string LotBlockSub { get; set; }

        /// <summary>
        ///     Gets or sets the owner keywords.
        /// </summary>
        [Display(Name="Owner")]
        public string OwnerKeywords { get; set; }

在我的控制器动作中,我正在考虑这样的事情。但我认为所有这些逻辑都不属于我的控制器。

ActionResult GetSearchResults(SearchViewModel model){
    var query = service.GetAllParcels();
    if(model.Census != null){
    query = query.Where(x=>x.Census == model.Census);
    }
    if (model.OwnerKeywords != null){
    query = query.Where(x=>x.Owners == model.OwnerKeywords);
    }
    return View(query.ToList());
    }
4

3 回答 3

2

您在这里所做的是使用 LINQ 代替更严格的 OO“规范模式”。如果您的应用程序分层允许这样做(即,如果您可以从 Web 前端直接访问数据库,并非所有架构都这样做),那没有错,尽管您可能希望将其推入“服务”类而不是执行控制器中有很多查询逻辑。您希望对这些事物的分离有多严格取决于您的应用程序的大小和复杂性。

引入一些抽象的一种方法是让您的视图模型实现一个接口(例如:ISearchSpecification),该接口定义了可以在查询谓词中使用的属性。然后,您可以创建对接口进行操作的类或扩展方法。

public interface IMySearchSpec 
{
   string City { get; }
   string State { get; }
}

public class MyViewModel : IMySearchSpec
{
   ...implement IMySearchSpec and perhaps other things...
}

public static class QueryExtensions
{
   public static IQueryable<T> ApplyPredicate(this IQueryable<T> query, IMySearchSpec searchSpec) 
   {
        if (searchSpec.City != null )
        {
            query = query.Where( x => x.City == searchSpec.city );
        }
        // ..etc..
       return query;
   }
}

// then, in your controller
var filteredQuery = query.ApplyPredicate(viewModel);

您也可以以类似的方式应用分页/排序逻辑。

于 2013-06-25T19:05:02.927 回答
2

如何在不将 viewModel 传递给服务层的情况下执行此操作?服务不应该知道 ViewModel 对吗?

没错,视图模型是表示层对象,因此将它们排除在服务层或持久层之外是个好主意。此外,控制器应该精简且没有太多逻辑,因此我认为将此代码分解到其他地方是正确的方法。以下是您的情况的一些替代方案:

  • 将您的值从控制器传递到您的服务层
  • 创建一个为您创建字符串的助手类
  • 将您的视图模型映射到另一个类/实体并将其传递给您的服务层
于 2013-06-25T19:09:13.267 回答
1

通常,您不会将视图模型作为视图的参数,而是;视图模型从控制器传递到视图。

我的逻辑背后的原因是,如果大型(大量数据)视图模型从控制器传递到视图,然后从视图传递回控制器可能会成为问题(性能);特别是如果您不需要控制器操作中的所有信息。我想您可以将视图创建的视图模型发送到控制器(原始较大视图模型的子集)。我对这个问题的理解是他想在控制器-> 视图-> 控制器之间来回传递相同的视图模型。

来自stackoverflow问题在MVC中,什么是ViewModel?

ViewModel 还可以执行从您的模型携带的数据类型到您的视图可以方便地使用的数据类型的转换;这甚至可能意味着 ViewModel 不直接携带模型,而是其他容器以更合适的格式携带相同信息(可能是其子集)。

考虑一下您可以有一个聚合专辑和 DVD 的库模型——这种模型和相应的 ViewModel 之间的区别恰恰在于,模型不关心(甚至不知道)视图,而 ViewModel 的明确目的是促进它。

将控制器操作的参数更改为类,例如 SearchParameters。可以将 SearchParameters 传递给您的服务层。

于 2013-06-25T18:56:53.583 回答