首页 > 解决方案 > 使用过滤器 (EnumDropDownListFor) 设置 MVC ASP.NET 从详细信息返回到索引页面

问题描述

我在尝试返回正确设置过滤器的索引(列表)页面时遇到问题。从详细信息页面返回时永远不会设置过滤器,并且始终默认为下拉列表中的第一个值。使用 Html 帮助程序 EnumDropDownListFor。

编辑:我应该指出,如果我将当前月份过滤器从它正确发布的索引页面更改为索引 ActionResult,并且过滤器在索引页面中正确设置。所以问题是从详细信息页面发布回索引页面时。

这是我的代码。

型号代码:

using System;
using System.Collections.Generic;

namespace ShiftPatternConfigurator.Models
{
    // shift view
    public class ShiftViewModel
    {
        public IEnumerable<Shift> Shifts { get; set; }
        public Month Month { get; set; }
    }

    // shift model
    public class Shift
    {
        public int ShiftNo;
        public string ShiftName;
        public DateTime StartTime;
        public DateTime FinishTime;
        public string Team;
        public int Week;
        public int CycleWeek = 0;
        public string StartDay;
        public DateTime StartDate;
    }

    // month enum
    public enum Month
    {
        January = 1,
        February = 2,
        March = 3,
        April = 4,
        May = 5,
        June = 6,
        July = 7,
        August = 8,
        September = 9,
        October = 10,
        November = 11,
        December = 12
    }
}

控制器代码:

using ShiftPatternConfigurator.DataAccess;
using ShiftPatternConfigurator.Models;
using System;
using System.Web.Mvc;

namespace ShiftPatternConfigurator.Controllers
{
    public class HomeController : Controller
    {
        // GET: Index
        public ActionResult Index()
        {
            ViewBag.Title = "Shift Pattern";
            ShiftViewModel monthShiftView = new ShiftViewModel
            {
                Month = new Month()
            };
            monthShiftView.Month = (Month)DateTime.Now.Month;
            monthShiftView.Shifts = DbContext.GetShiftsByMonth(monthShiftView.Month);       
            return View(monthShiftView);
        }

        // POST: Index
        [HttpPost]
        public ActionResult Index(Month month)
        {
            ViewBag.Title = "Shift Pattern";
            ShiftViewModel monthShiftView = new ShiftViewModel
            {
                Month = new Month()
            };
            monthShiftView.Month = month;
            monthShiftView.Shifts = DbContext.GetShiftsByMonth(monthShiftView.Month);
            return View(monthShiftView);
        }

        // GET: Details
        public ActionResult Details(int shiftNo, Month monthFilter)
        {
            ViewBag.Title = "Shift Details";
            ViewBag.MonthFilter = monthFilter;
            Shift shift = DbContext.GetShiftByShiftNo(shiftNo);
            return View(shift);
        }
    }
}

索引(列表)代码:

@model ShiftPatternConfigurator.Models.ShiftViewModel
<div class="jumbotron">

    <h1>@ViewBag.Title - @Model.Month</h1>

    @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        @Html.AntiForgeryToken()
        @Html.EnumDropDownListFor(x => x.Month)
        <input type="submit" value="Select Month" class="btn btn-primary btn-sm" />
    }

</div>

<table class="table">
    <tr>
        <th>Shift No</th>
        <th>Shift Name</th>
        <th>Start Time</th>
        <th>Finish Time</th>
        <th>Team</th>
        <th>Week</th>
        <th>Start Day</th>
        <th>Start Date</th>
        <th></th>
    </tr>

    @if (Model.Shifts.Count() > 0)
    {
        foreach (var item in Model.Shifts)
        {
            <tr>
                <td>@item.ShiftNo</td>
                <td>@item.ShiftName</td>
                <td>@item.StartTime</td>
                <td>@item.FinishTime</td>
                <td>@item.Team</td>
                <td>@item.Week</td>
                <td>@item.StartDay</td>
                <td>@item.StartDate.ToShortDateString()</td>
                <td>
                    <div class="btn-group btn-group-xs">
                        @Html.ActionLink("Edit", "Edit", new { shiftNo = item.ShiftNo, monthFilter = Model.Month }, new { @class = "btn btn-primary" })
                        @Html.ActionLink("Details", "Details", new { shiftNo = item.ShiftNo, monthFilter = Model.Month }, new { @class = "btn btn-primary" })
                    </div>
                </td>
            </tr>
        }
    }
    else
    {
        <tr>
            <td colspan="10" align="center"><h2>No Data</h2></td>
        </tr>
    }

</table>

详细代码:

@using ShiftPatternConfigurator.Models
@model Shift

<h2>@ViewBag.Title</h2>

<div>
    <h4>Shift - @Model.ShiftNo</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>Shift No:</dt>
        <dd>@Model.ShiftNo</dd>
        <dt>Shift Name</dt>
        <dd>@Model.ShiftName</dd>
        <dt>Start Time</dt>
        <dd>@Model.StartTime.ToShortDateString() @Model.StartTime.ToLongTimeString()</dd>
        <dt>Finish Time</dt>
        <dd>@Model.FinishTime.ToShortDateString() @Model.FinishTime.ToLongTimeString()</dd>
        <dt>Team:</dt>
        <dd>@Model.Team</dd>
        <dt>Week:</dt>
        <dd>@Model.Week</dd>
        <dt>Cycle Week:</dt>
        <dd>@Model.CycleWeek</dd>
        <dt>Start Day:</dt>
        <dd>@Model.StartDay</dd>
        <dt>Start Date:</dt>
        <dd>@Model.StartDate</dd>
    </dl>
</div>
<p>
    @Html.ActionLink("Edit", "Edit", new { /* id = Model.PrimaryKey */ }) |
    @Html.ActionLink("Back to List-ActionLink", "Index", "Home", new { month = ViewBag.MonthFilter })
    @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        @Html.AntiForgeryToken()
        @Html.Hidden("month", (Month)ViewBag.MonthFilter)
        <input type="submit" value="Back to List-Form" class="btn btn-primary btn-sm" />
    }
    @Ajax.ActionLink("Back to List-Ajax", "Index", "Home",
        new { month = (Month)ViewBag.MonthFilter },
        new AjaxOptions { HttpMethod = "POST" },
        new { @class = "btn btn-primary btn-sm" })


</p>

我尝试了以下方法来返回带有过滤器集的索引页面:

  1. @Html.ActionLink 方法

我发现这不起作用,因为 ActionLink 总是发送一个 GET 请求,所以我不能使用这种方法。

@Html.ActionLink("Back to List-ActionLink", "Index", "Home", new { month = ViewBag.MonthFilter })
  1. @Ajax.ActionLink 方法

使用 Ajax 方法,索引 POST 方法被命中,但页面停留在详细信息页面上。

@Ajax.ActionLink("Back to List-Ajax", "Index", "Home",
    new { month = (Month)ViewBag.MonthFilter },
    //new AjaxOptions { HttpMethod = "POST", OnSuccess = "window.location.href = '/'" },
    new AjaxOptions { HttpMethod = "POST" },
    new { @class = "btn btn-primary btn-sm" })
  1. @Html.BeginForm 方法

使用此方法,它可以正确地正确发布到 POST ActionResult,但是下拉列表默认为列表中的第一个。所以过滤器没有正确传递给 enumdropdownlistfor。

@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
    @Html.Hidden("month", (Month)ViewBag.MonthFilter)
    <input type="submit" value="Back to List-Form" class="btn btn-primary btn-sm" />
}

这是使用@Html.BeginForm 回发的方法3,在屏幕截图中显示了调试值:

  1. 页面启动并点击 GET 索引 ActionResult,Models Month 枚举设置为当前月份,班次列表从 BDcontext 返回并分配给 Model。

获取索引操作结果

  1. 索引视图然后呈现 Html 将 EnumDropDownListFor 正确设置为当前日期

正确设置枚举 DDL

从图像中可以看出,月份设置为当前月份。

正确设置月份过滤器

编辑:这是由 @Html.EnumDropDownListFor 帮助器正确生成的 HTML 输出

正确生成的选择列表

  1. 选择详细信息链接后,代码会点击获取详细信息 ActionResult 并正确呈现视图。

详细代码 详情查看

  1. 点击返回 List-Form 按钮后,POST Index Action Result 被正确设置所有参数。

索引代码 POST

  1. 但是视图是使用 Month 过滤器呈现的,默认为列表中的第一个,而不是我选择的月份。

编辑:这是由 @Html.EnumDropDownListFor 助手错误生成的 HTML 输出

错误生成的选择列表

发布后索引查看代码 索引视图后过滤器失败

请帮助我提出如何使这项工作的建议。

标签: asp.netmodel-view-controllerindexingenumdropdownlistfor

解决方案


所以我找到了解决我的问题的方法,尽管感觉它是一种与正确方法相反的黑客行为。也许有人可以评论为什么它没有按照我想要的方式工作?

我所做的是以下内容:

  1. 在我的详细信息页面中使用 ActionLink 传递参数。
  2. 处理我的 GET Index ActionResult 方法中的可选参数。

所以代码看起来像这样。

详细视图操作链接:

@Html.ActionLink("Back to List", "Index", "Home", new { monthFilter = ViewBag.MonthFilter }, new { @class = "btn btn-primary btn-sm" })

索引(列表)GET ActionResult:

// GET: Index
public ActionResult Index(string monthFilter)
{

    ViewBag.Title = "Shift Pattern";
    ShiftViewModel monthShiftView = new ShiftViewModel
    {
        Month = new Month()
    };

    // hack to fix issue with filter not being passed back to index page from Details view
    if(monthFilter == null)
        monthShiftView.Month = (Month)DateTime.Now.Month;
    else
        monthShiftView.Month = (Month)Enum.Parse(typeof(Month), monthFilter); ;

    monthShiftView.Shifts = DbContext.GetShiftsByMonth(monthShiftView.Month);       
    return View(monthShiftView);
}

如您所见,我处理月份值,如果传入的月份值为空,则使用当前月份,或者如果传入的值可用,则我使用传入的值。


推荐阅读