MVC无法将值传递给URL上的2个参数之一

时间:2015-08-22 02:08:16

标签: asp.net-mvc

我有一个列出记录列表的索引视图。我有2个datepicker字段(FromDate,ToDate),我用它来允许用户过滤列表中的数据。用户第一次访问该页面时,FromDate和ToDate中的值没有传递给操作

Index(DateTime? fd, DateTime? td) 

所以我使用默认值

fromDate = DateTime.Today.AddDays(-7); // and
toDate = DateTime.Today.AddDays(14);

使用默认数据加载索引视图后,用户现在可以使用日期字段更改日期范围。每次用户点击搜索时,我都会使用url将2个日期字段中的值传递给控制器​​中的Index操作。但是,第一个值(fd)不会传递给控制器​​。第二个值(td)正确传递给控制器​​。我做错了什么?或者有更好的方法/最佳实践来做到这一点?

我的索引视图:

<a id="btnSearch" class="btn btn-info" href="/Slide/Index/?fd=@ViewBag.FromDate.ToString("dd-MM-yyyy")&td=@ViewBag.ToDate.ToString("dd-MM-yyyy")"> Search </a>

<div class="input-group date">
      <span>From: </span>@Html.TextBox("FromDate", (DateTime)ViewBag.FromDate, new { @class = "col-md-6", @style="width:80px" })
</div>
<div class="input-group date">
      <span>From: </span>@Html.TextBox("ToDate", (DateTime)ViewBag.ToDate, new { @class = "col-md-6", @style="width:80px" })
</div>

<div class="row">
    <table class="table table-hover" style="width:auto" id="sTable">
       //this is where I list the result data here....
    </table>
</div><!--End of row-->

我的路线:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapRoute(
        name: "Slide",
        url: "Slide/Index/{fd}/{td}",
        defaults: new { controller = "Slide", action = "Index", fd = UrlParameter.Optional, td = UrlParameter.Optional }
    );
    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );

}

行动方法:

public ActionResult Index(DateTime? fd = null, DateTime? td = null)
{
    DateTime fromDate;
    DateTime toDate;

    if (!fd.HasValue)
        fromDate = DateTime.Today.AddDays(-7);
    else
        fromDate = fd.Value;

    if (!td.HasValue)
        toDate = DateTime.Today.AddDays(14);
    else
        toDate = td.Value;

    IEnumerable<EZone_SlideInfo> lSlide = _slideRepo.GetSlideByExpiration(fromDate, toDate);

    ViewBag.FromDate = DateTime.Parse(fromDate.ToShortDateString());
    ViewBag.ToDate = DateTime.Parse(toDate.ToShortDateString());

    return View(lSlide);
}

2 个答案:

答案 0 :(得分:0)

您的硬编码查询字符串@{ // This code block can be put at the VERY TOP of the .cshtml view. // That way, it doesn't clutter up your HTML source code potion with C# code. var searchRouteValues = new RouteValueDictionary { { "fd", ViewBag.FromDate.ToString("dd-MM-yyyy") }, { "td", ViewBag.ToDate.ToString("dd-MM-yyyy") } }; var btnSearchHtmlAttributes = new Dictionary<string, object> { { "class", "btn btn-info" }, { "id", "btnSearch" } }; } <!-- using ActionLink extension method --> @Html.ActionLink( linkText : "Search", actionName : "Index", controller : "Slide", routeValues : searchRouteValues, htmlAttributes : btnSearchHtmlAttributes ) <!-- using RouteLink extension method --> @Html.RouteLink( linkText : "Search", routeName : "Slide" /* NOTICE: this requires CUSTOM route registration */, routeValues : searchRouteValues, htmlAttributes : btnSearchHtmlAttributes ) 为:

  1. 特别是如果您需要为特殊字符编码URL
  2. ,则容易出错
  3. 难以阅读和维护。
  4. 作为最佳做法,请考虑使用Html.ActionLink()Html.RouteLink()扩展方法,以便在路由模式更改(或)需要URL编码时不会被破坏。

    // your code
    routes.MapRoute(
        name: "Slide",
        url: "Slide/Index/{fd}/{td}",
        defaults: new { controller = "Slide", action = "Index", fd = UrlParameter.Optional, td = UrlParameter.Optional }
    );
    

    你是否真的需要一个漂亮的URL,如下所示?

    // default/generic route registration code
    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
    

    如果没有,请尽可能保持通用,如下所示。

    Html.ActionLink()

    只要您使用上面显示的<a id="btnSearch" class="btn btn-info" href="/Slide/?fd=01/01/2015&to=01/02/2015">Search</a> ,您的网址路线仍可正常运作。它会像这样呈现超链接。

    charArray

    如果您按照上面的说明重写代码,我相信它会解决您的问题。

答案 1 :(得分:0)

您需要在/之前移除? - 它应该是

<a id="btnSearch" class="btn btn-info" href="/Slide/Index?fd=@ViewBag.....`, 

但是您根据ViewBag属性对网址进行了硬编码,因此您的文本框不会执行任何操作(它们的值永远不会发送到控制器方法),因此您的视图只会在今天之间显示记录 - 7天,今天+ 14天。还

ViewBag.FromDate = DateTime.Parse(fromDate.ToShortDateString());

没有意义 - 您将日期转换为字符串,然后将其转换回日期。此外,您的路由默认值应为defaults: new { controller = "Slide", action = "Index" },即没有可选参数。

如果您想根据2个日期的选择过滤记录,则需要发布表格

@using (Html.BeginForm("Index", "Slide", FormMethod.Get))
{
  // you textboxes/datepickers
  <input type="submit" .../>
}

以便将选定的值发布回方法。您应该使用具有日期和集合属性的视图模型

public class SearchVM
{
  public DateTime FromDate { get; set; }
  public DateTime ToDate { get; set; }
  public IEnumerable<EZone_SlideInfo> Records { get; set; }
}

然后在你的视图中

@model SearchVM
@using (Html.BeginForm("Index", "Slide", FormMethod.Get))
{
  @Html.TextBoxFor(m => m.FromDate)
  @Html.TextBoxFor(m => m.ToDate)
  <input type="submit" .../>
}
<table>
  @foreach(var item in Model.Records)
  {
    // display your filtered results

和控制器方法

public ActionResult Index(DateTime? fromDate, DateTime? toDate) // no need for '= null'
{
  fromDate = fromDate ?? DateTime.Today.AddDays(-7);
  toDate = toDate ?? DateTime.Today.AddDays(14);
  ModelState.Clear();
  SearchVM model = new SearchVM()
  {
    FromDate = fromDate,
    ToDate = toDate,
    Records = _slideRepo.GetSlideByExpiration(fromDate.Value, toDate.Value);
  };
  return View(model);
}

当然,您可以通过使用javascript / jquery和ajax将所选日期发布到控制器方法来提高性能,该控制器方法仅返回已过滤的结果,以避免每次都重新生成视图。