如何同时传递强类型模型和模型列表到视图

3

我的最终目标是从控制器同时传递一个强类型模型(用于填充下拉菜单)和一个基于搜索查询的模型列表到视图。我要传递到的视图是“Clear()”视图。目前在我的HomeController.cs中,代码如下:

public ActionResult Clear()
    {
        var states = GetAllStates();

        var model = new ProjectClearanceApp.Models.Project();

        model.States = GetSelectListItems(states);

        return View(model);
    }

    private IEnumerable<string> GetAllStates()
    {
        return new List<string>
        {
            "AL",
             // ... (you get the point)
            "WY",
        };
    }

    private IEnumerable<SelectListItem> GetSelectListItems(IEnumerable<string> elements)
    {
        var selectList = new List<SelectListItem>();

        foreach (var element in elements)
        {
            selectList.Add(new SelectListItem
            {
                Value = element,
                Text = element
            });
        }

        return selectList;
    }

我在某处读到,这是获取下拉菜单选项列表的最佳方法。现在我也想通过搜索查询向同一视图(Clear.cshtml)传递模型列表。我正在阅读这篇微软教程,通过添加控制器操作来搜索该视图。
public ActionResult Index(string searchString)
{
    var movies = from m in db.Movies
                 select m;

    if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }

    return View(movies);
}

如何从控制器传递下拉选项列表和符合搜索条件的模型列表到视图中(或者,如何在不从控制器传递这两个列表的情况下实现相同的效果)?


5
通过另一个将它们两个都封装起来的模型。 - Nkosi
2
从 y 中选择 x 写成 from x in y select x 是没有必要的。 - SLaks
@SLaks 这是一个很好的观点。我该如何重写select语句来在选择时进行搜索,而不是从数据库获取完整的电影列表,然后再搜索呢? - B. Fitzgerald
@B.Fitzgerald var movies = db.Movies.AsQueryable(); - Nkosi
@B.Fitzgerald:只需使用 db.Movies,并将其声明为 IQueryable<T> - SLaks
显示剩余3条评论
2个回答

1
为了实现您的最终目标,即传递模型列表,根据我的经验,使用viewmodel将是最好的解决方案。
关于viewmodel的一些要点:
ViewModel类是视图和模型之间的桥梁。每个View类都有一个对应的ViewModel类。ViewModel从Model中检索数据,并将其操作成View所需的格式。如果模型中的基础数据发生更改,它会通知View,并在响应View的UI事件时更新Model中的数据。
ViewModel类确定用户操作是否需要修改Model中的数据,并在需要时对Model进行操作。例如,如果用户按下按钮以更新某个部件的库存数量,则View仅通知ViewModel发生了此事件。ViewModel从View中检索新的库存量并更新Model。这将View与Model解耦,并将业务逻辑整合到ViewModel和Model中,可以进行测试。
官方定义/来源:https://msdn.microsoft.com/en-us/library/ff798384.aspx 附加信息及示例:

http://www.dotnettricks.com/learn/mvc/understanding-viewmodel-in-aspnet-mvc

请告诉我您的想法或反馈意见。
谢谢。
卡尔蒂克。

0

Model 是一个术语,它真正描述了数据应该绑定到视图上,以及当您从视图请求/响应时模型绑定器将处理哪些数据。因为我不确定您如何使用 Index 和 Clear,所以我会一般性地进行存根。如果我错过了您问题的要点,请告诉我:

如果您在将 List<Movies> movieModel(或任何其他值)与您的 List<SelectListItem> selectedStates 一起传递到视图时遇到问题,这里有两种常见的方法可以解决。

  1. ViewModel方法 -- 创建一个包含“主”模型以及视图中需要的任何其他属性、列表等的模型类。 例如:

    public Class MyViewModelClass
    {
       List<Movie> MoviesList {get;set;}
       List<SelectListItem> StatesList {get;set;}
       //一些其他属性/方法也可以放在这里...
    }
    
    //在控制器中
    {
        MyViewModelClass model = new MyViewModelClass();
        model.StatesList = <构建您的选择列表>;
        model.MovieList = <构建您的电影列表>;
    
        return View(model);
    }
    
在控制器中,您将创建一个新的实例MyViewModelClass model(显然是不同的名称),并填充您的电影列表、状态列表和任何其他属性,将它们分配给模型属性,并将整个内容作为return View(model);返回。
这很好,因为传递给视图的所有数据都可以在一个地方。
  • ViewBag方法 -- 保持单一模型或列表,并在ViewData或ViewBag中传递与视图相关的数据(例如下拉列表或状态布尔值)。 例如:

    //来自控制器
    public ActionResult SomeMethod()
    {
       var states = GetAllStates();
       var model = <输入电影查询>;
       ViewBag.StatesList = GetSelectListItems(states);
       //现在可以在视图中访问此变量
    
       return View(model);
    }
    
    //在视图中:
    @{
        List<SelectListItem> StatesList =  (List<SelectListItem>)ViewBag.StatesList; // 现在可以使用此变量绑定到DropDownList等。
     }
    
  • 对于大部分情况,我更喜欢使用ViewModel来添加所需的一切。首先,ViewBag/ViewData需要进行一些类型转换,并且依赖于“魔术字符串”,因此您无法在Intellisense中得到Visual Studio的提示,以便知道是否输入有误。话虽如此,两者都是可行的。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接