【问题标题】:How should I handle filtering search results within a date range for my asp.net core mvc app?我应该如何处理我的 asp.net core mvc 应用程序在日期范围内的过滤搜索结果?
【发布时间】:2021-01-21 21:56:22
【问题描述】:

下午好,我整天都在阅读论坛、博客等,试图找出解决我的问题的方法,但没有一个是一针见血的。

我的场景:我正在尝试按日期范围过滤搜索结果。我希望用户能够搜索特定记录并使用日期范围过滤该搜索。或者,我希望他们能够在不提供搜索条件的情况下查看某个日期范围内的所有记录。

视图模型

    public class VMSpecialCollectionSearch
{
    // results of search query
    public List<ArchivesFileManagement_MVCDB.SpecialCollections> SearchResults { get; internal set; }

    public SelectList TypeOptions { get; set; }

    // Selected search options
    [Required]
    public string SearchType { get; set; }
    [Required]
    public string SearchText { get; set; }
    public string CurrentFilter { get; set; }

    public DateTime? FromDate { get; set; }
    public DateTime? ToDate { get; set; }
}

表单 - 注意:第一个表单可以正常运行并相应地返回我的搜索结果。

    <form class="form-group" onsubmit="return validateSelection()">
    <div class="card-body">
        <div class="row justify-content-center">
            <div class="col-md-auto">
                <label>Type:</label>&nbsp;
                <select id="searchTypeSelection" asp-for="SearchType" asp-items=@Model.TypeOptions required></select>
            </div>
            <div class="col-md-auto">
                <label>Description:</label>&nbsp;
                <input id="searchText" type="text" asp-for="SearchText" required />
            </div>
            <div class="col-md-auto">
                <button type="submit" class="btn btn-primary btn-sm">Search</button>
            </div>
        </div>
    </div>
</form>
<form id="dateForm" onsubmit="ApplyDateFilter(event)" class="form-group">
    <div class="row justify-content-center">
        <div class="col-md-auto">
            <label>From:</label>&nbsp;
            <input id="fromDate" type="text" asp-for="FromDate" class="datePicker" required />
        </div>
        <div class="col-md-auto">
            <label>To:</label>&nbsp;
            <input id="toDate" type="text" asp-for="ToDate" class="datePicker" required />
        </div>
        <div class="col-md-auto">
            <button class="btn btn-primary btn-sm" type="submit">Apply</button>
        </div>
    </div>
</form>

处理日期过滤器提交 - 注意:我也尝试将其设置为 Post 方法,但这也不起作用。

    function ApplyDateFilter(e) {
        e.preventDefault();
        //var formData = new FormData($("#dateForm").get(0));
        var from = $("#fromDate").val();
        var to = $("#toDate").val();
        var type = $("#searchTypeSelection").val();
        var text = $("#searchText").val();
        debugger;
        $.ajax({
            type: "Get",
            url: '@Url.Action("IndexFilter", "SpecialCollections")',
            data: //formData,
            {
                FromDate: from,
                ToDate: to,
                SearchType: type,
                SearchText: text
            },
            contentType: "application/json",
        });
    }

控制器

    // GET: SpecialCollections/
    public IActionResult IndexFilter(string FromDate, string ToDate, string SearchType, string SearchText)
    {    ... CREATE AN UPDATED VIEW MODEL ...

        return View(nameof(Index), vm);
    }

我的问题:提交第二个表单(针对日期范围)后,当我返回视图时,我没有返回新的搜索查询结果。它给了我与以前相同的结果。有没有更好的方法来处理这种情况?

这是我尝试过的... 我尝试将搜索结果实现为部分视图,这样我就可以在不重新加载页面的情况下更新结果。这失败了,因为我在结果表中的所有按钮都坏了。 (我尝试使用委托来解决这个问题,但无济于事)。我目前正在尝试以不同的操作处理第二个表单提交,然后使用新的视图模型重新加载相同的视图(索引)。

除了搜索结果没有改变外,一切似乎都正常。我没有收到任何错误。

【问题讨论】:

  • 您是否在 IndexFilter 操作的第一行设置了断点,以验证您的 JSON 有效负载是否正确映射到这些操作参数?我很确定您可能需要使用 [FromBody] 标签将请求正文映射到您的操作参数。
  • @tnk479 我在测试时确实在控制器中放置了断点,以确保控制器按预期运行。它检查得很好。我对 [FromBody] 标签的理解是如何使用我的 ViewModel 作为参数。不过我对此并不完全确定。

标签: c# ajax asp.net-core-mvc


【解决方案1】:

我的问题:提交第二个表单(针对日期范围)时,我没有 当我返回视图时取回我的新搜索查询结果。它给 我和以前一样的结果。有没有更好的处理方式 这种情况?

由于您使用 JQuery Ajax 过滤数据(基于日期范围),因此在执行操作后,它会将更新后的视图返回给 Ajax 成功函数。但是从您的代码来看,您还没有根据Ajax成功函数中的响应更新页面内容,因此数据不会更新。

我建议您可以参考以下示例代码并使用部分视图来显示记录。

型号:

public class VMSpecialCollectionSearch
{ // results of search query
    public List<VMArchives> SearchResults { get; internal set; }

    public SelectList TypeOptions { get; set; }

    // Selected search options
    [Required]
    public string SearchType { get; set; }
    [Required]
    public string SearchText { get; set; }
    public string CurrentFilter { get; set; }

    public DateTime? FromDate { get; set; }
    public DateTime? ToDate { get; set; }
}
 
public class VMArchives
{
    public int Id { get; set; }
    public string Titile { get; set; }

    public DateTime DateTime { get; set; }
    public string Type { get; set; }
}

然后,创建一个 ArchivesController 控制器来管理档案:

public class ArchivesController : Controller
{
    private readonly IRepository repo; //create a Repository and add initial data.
    public ArchivesController(IRepository repository)
    {
        repo = repository;
    }
    //Main page
    public IActionResult Index(string FromDate, string ToDate, string SearchType, string SearchText)
    { 
        var result = FilterData(FromDate, ToDate, SearchType, SearchText); 

        return View(result);
    }

    //Based on the condition to filter data
    public VMSpecialCollectionSearch FilterData (string FromDate, string ToDate, string SearchType, string SearchText)
    {
        VMSpecialCollectionSearch result = new VMSpecialCollectionSearch();
        //get All type
        result.TypeOptions = new SelectList(
            repo.GetAllVMArchives()
            .GroupBy(c => c.Type)
            .Select(c =>
                new SelectListItem()
                {
                    Value = c.Key,
                    Text = c.Key
                }).ToList(), "Value", "Text");

        var allArchives = repo.GetAllVMArchives();

        //According the SearchType to filter data
        if (!string.IsNullOrEmpty(SearchType) && SearchType != "All")
            allArchives = allArchives.Where(c => c.Type == SearchType).ToList();
        //According the SearchText to filter data
        if (!string.IsNullOrEmpty(SearchText))
            allArchives = allArchives.Where(c => c.Titile.Contains(SearchText)).ToList();
        //According the date range to filter data.
        if (!string.IsNullOrEmpty(FromDate) && !string.IsNullOrEmpty(ToDate))
        {
            DateTime from;
            DateTime to;

            if (DateTime.TryParse(FromDate, out from) && DateTime.TryParse(ToDate, out to))
            {
                allArchives = allArchives.Where(c => c.DateTime > from && c.DateTime < to).ToList();
            }
        }
        result.SearchResults = allArchives;
        return result;
    }

    // GET: SpecialCollections/
    public IActionResult IndexFilter(string FromDate, string ToDate, string SearchType, string SearchText)
    {
        var result = FilterData(FromDate, ToDate, SearchType, SearchText);
        return PartialView("_IndexFilter", result.SearchResults);
    }

主页中的代码(Index.cshtml):

@model MVCDemo.Models.VMSpecialCollectionSearch

@{
    ViewData["Title"] = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>Index</h1>

<form class="form-group">
    <div class="card-body">
        <div class="row justify-content-center">
            <div class="col-md-auto">
                <label>Type:</label>&nbsp;
                <select id="searchTypeSelection" asp-for="SearchType" asp-items=@Model.TypeOptions required>
                    <option value="All">All</option>
                </select>
            </div>
            <div class="col-md-auto">
                <label>Description:</label>&nbsp;
                <input id="searchText" type="text" asp-for="SearchText" required />
            </div>
            <div class="col-md-auto">
                <button type="submit" class="btn btn-primary btn-sm">Search</button>
            </div>
        </div>
    </div>
</form>
<form id="dateForm" onsubmit="ApplyDateFilter(event)" class="form-group">
    <div class="row justify-content-center">
        <div class="col-md-auto">
            <label>From:</label>&nbsp;
            <input id="fromDate" type="text" asp-for="FromDate" class="datePicker" required />
        </div>
        <div class="col-md-auto">
            <label>To:</label>&nbsp;
            <input id="toDate" type="text" asp-for="ToDate" class="datePicker" required />
        </div>
        <div class="col-md-auto">
            <button class="btn btn-primary btn-sm" type="submit">Apply</button>
        </div>
    </div>
</form>

<div id="content">
    <partial name="_IndexFilter.cshtml" model="Model.SearchResults" />
</div>

@section Scripts{
    <script>
        function ApplyDateFilter(e) {
            e.preventDefault(); 
            var from = $("#fromDate").val();
            var to = $("#toDate").val();
            var type = $("#searchTypeSelection").val();
            var text = $("#searchText").val();
            debugger;
            $.ajax({
                type: "Get",
                url: '@Url.Action("IndexFilter", "Archives")',
                data: //formData,
                {
                    FromDate: from,
                    ToDate: to,
                    SearchType: type,
                    SearchText: text
                },
                contentType: "application/json",
                success: function (response) {
                    $("#content").html(""); //clear the records content
                    $("#content").html(response);  //add the updated content.
                }
            });
        } 
    </script>
}

[评论] 在Index.cshtml 页面中,我们使用partial 标记来显示VMArchives 列表。然后,在Ajax成功函数中,从控制器成功获取结果后,我们将清除记录容器并更新内容。

使用以下代码创建一个_IndexFilter.cshtml 部分视图以显示 VMArchives:

@model IEnumerable<MVCDemo.Models.VMArchives>

<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Id)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Titile)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.DateTime)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Type)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Id)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Titile)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.DateTime)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Type)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
            </td>
        </tr>
}
    </tbody>
</table>

这样的结果(如果点击“搜索”按钮,它将提交表单到索引操作,如果点击“应用”按钮,它将通过Ajax过滤数据):

【讨论】:

  • 您对我在 Ajax 调用中缺少的成功函数是正确的。我想我认为因为我使用更新的 ViewModel 返回相同的视图,所以它会重新加载页面。我错了。
猜你喜欢
  • 2010-09-26
  • 1970-01-01
  • 2021-05-17
  • 1970-01-01
  • 1970-01-01
  • 2010-12-05
  • 2020-05-30
  • 2011-07-24
  • 1970-01-01
相关资源
最近更新 更多