【问题标题】:Showing a list of results under a search form, which uses a ViewModel在使用 ViewModel 的搜索表单下显示结果列表
【发布时间】:2023-06-26 14:56:01
【问题描述】:

继续之前的帖子:Adding a search form using a DateTime template

我也尝试按照此处的搜索示例:http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application

...但这并没有像我上一篇文章的答案中所建议的那样使用 ViewModel。

我正在尝试帮助搜索 from,这将需要两个日期(从/到),基于以下 ViewModel:

public class SearchViewModel
{
    [Required]
    public DateTime From { get; set; }
    [Required]
    public DateTime To { get; set; }
}

我的视图/搜索/Index.cshtml 是:

@model ttp.Models.SearchViewModel
@{
    ViewBag.Title = "Search Availability";
}
<h2>Search Availability</h2>
@using (Html.BeginForm()) 
{ 
    <div class="row">
        <div class="span2">@Html.LabelFor(x => x.From)</div>
        <div class="span2">@Html.EditorFor(x => x.From)</div>
        <div class="span2">@Html.ValidationMessageFor(x => x.From)</div>
        </div>

    <div class="row">
        <div class="span2">@Html.LabelFor(x => x.To)</div>
        <div class="span2">@Html.EditorFor(x => x.To)</div>
        <div class="span2">@Html.ValidationMessageFor(x => x.To)</div>
    </div>

     <div class="row">
        <div class="span2 offset2"><button type="submit">Search</button></div>
     </div>
} 

Get: /Search/Index 控制器是:

    //
    // GET: /Search/

    public ActionResult Index()
    {
        SearchViewModel svm = new SearchViewModel();
        svm.From = DateTime.Today;
        svm.To = DateTime.Today;
        return View(svm);
    }

到目前为止一切顺利 - 我的视图显示日期默认为今天的文本框(使用 DateTime Helper)。当我点击 Search 时,代码转到 SearchController // Post: / Search 如下:

    //
    // Post: /Search/
    [HttpPost]
    public ActionResult Index(SearchViewModel searchViewModel)
    {
        if (!ModelState.IsValid)
        {
            // Not valid, so just return the search boxes again
            return View(searchViewModel);
        }

        // Get the From/To of the searchViewModel

        DateTime dteFrom = searchViewModel.From;
        DateTime dteto = searchViewModel.To;

        // Query the database using the posted from/to dates

        IQueryable<Room> rooms = db.Rooms.Where(r => r.Clients.Any(c => c.Departure >= dteFrom && c.Departure < dteTo));

        // This is where I'm unsure

        ViewBag.Rooms = rooms.ToList();
        return View(rooms.ToList());

        }

我现在不确定 Post 控制器的最后几行 - 我如何返回 IQueryable 房间中的房间列表 - 并在屏幕上显示房间列表?我是否重定向到另一个视图(如果是,我如何将房间列表传递给该视图)?如果我只是尝试运行上面的代码,我会收到错误:

The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[ttp.Models.Room]', but this dictionary requires a model item of type 'ttp.Models.SearchViewModel'.

我是否尝试混合使用苹果和梨 - 有没有在 From 和 To 搜索框 (ViewModel) 下显示房间列表?

谢谢,

标记

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-4


    【解决方案1】:

    您可以返回包含搜索结果的不同视图:

    IQueryable<Room> rooms = db.Rooms.Where(r => r.Clients.Any(c => c.Departure >= dteFrom && c.Departure < dteTo));
    return View("Result", rooms.ToList());
    

    Result.cshtml里面:

    @model IEnumerable<Room>
    ... show the rooms here
    

    如果您不想保留相同的视图,请修改您的视图模型,使其包含第三个属性,该属性将表示您将在 POST 控制器操作中填充的搜索结果(房间集合)并重新显示相同的视图:

    IQueryable<Room> rooms = db.Rooms.Where(r => r.Clients.Any(c => c.Departure >= dteFrom && c.Departure < dteTo));
    searchViewModel.Rooms = rooms;
    return View(searchViewModel);
    

    然后在视图中你可以有一个部分来显示结果:

    @if (Model.Rooms != null)
    {
        ... display the search results here
    }
    

    但在这两种情况下,我猜Room 对象是域模型。良好的做法要求您定义一个视图模型,其中只包含视图所需的信息:

    public class RoomViewModel
    {
        ... only properties that you need to work with on the view
    }
    

    然后使用 IEnumerable&lt;RoomViewModel&gt; Rooms { get; set; } 属性。您仍然可以从 DAL 层的控制器操作中获取您的 IQueryable&lt;Room&gt; 域模型,但在将其传递给视图之前,请确保执行到视图模型的转换。这是AutoMapper 可以派上用场的地方。

    【讨论】:

    • 要么你有一台都灵电脑为你发帖,要么你在帮助这里的人方面非常多产 - 要么/或者,我很感激 - 它帮助了我,更具体地说,帮助了我正在尝试的人在这个社区中心提供帮助,真是太棒了!我也转达他们的感谢。干杯!
    • 有什么办法可以将搜索表单保留在 results.cshtml 的顶部 - 或者是在 PartialViews 区域中?
    • 是的,你可以,这就是我答案的第二部分所涵盖的内容 => 向现有视图模型添加一个属性,该模型将包含房间集合,并在视图内部测试是否定义了此属性。
    【解决方案2】:

    您将不同的模型返回到同一个视图,因此首先只需更改您的控制器以返回传入的searchViewModel

    ViewBag.Rooms = rooms.ToList();
    return View(searchViewModel);
    

    您还可以将房间列表返回到同一个视图,就像您对 ViewBag 所做的那样,您只是在视图中没有任何地方为列表呈现任何标记:

    @model ttp.Models.SearchViewModel 
    @{     
        ViewBag.Title = "Search Availability"; 
    } 
    <h2>Search Availability</h2> 
    @using (Html.BeginForm())  
    {      
        <div class="row">
            <div class="span2">@Html.LabelFor(x => x.From)</div>
            <div class="span2">@Html.EditorFor(x => x.From)</div>
            <div class="span2">@Html.ValidationMessageFor(x => x.From)</div>
        </div>
        <div class="row">
            <div class="span2">@Html.LabelFor(x => x.To)</div>
            <div class="span2">@Html.EditorFor(x => x.To)</div>
            <div class="span2">@Html.ValidationMessageFor(x => x.To)</div>
        </div>
        <div class="row">
            <div class="span2 offset2"><button type="submit">Search</button></div>
        </div> 
    }
    @if (ViewBag.Rooms != null)
    {
        foreach (var room in ViewBag.Rooms as List<Room>)
        {
            // Build your room list markup here
        }
    }
    

    【讨论】:

      最近更新 更多