2015-08-22 1 views
1

У меня есть индексный список, содержащий список записей. У меня есть 2 поля datepicker (FromDate, ToDate), которые я использую, чтобы разрешить пользователям фильтровать данные в списке. Первые пользователи времени получить доступ к странице, нет никаких значений в FromDate и Todate перейти к действиюMVC Невозможно передать значение одному из двух параметров по URL

Index(DateTime? fd, DateTime? td) 

поэтому я использую значение по умолчанию

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

После загрузки Индексных с данными по умолчанию, пользователи теперь могут используйте поля даты, чтобы изменить диапазон дат. Каждый раз, когда пользователи нажимают на поиск, я передам значения из двух полей даты в действие индекса в моем контроллере, используя url. Однако первое значение (fd) не передается контроллеру. Второе значение (td) правильно передается на контроллер. Что я делаю неправильно? Или есть лучший подход/лучшая практика для этого?

Мой Индексный просмотр:

<a id="btnSearch" class="btn btn-info" href="/Slide/Index/[email protected]("dd-MM-yyyy")&[email protected]("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); 
} 
+0

У вас может быть только последний параметр, являющийся необязательным, поэтому удалите с маршрута 'fd = UrlParameter.Optional' и измените метод на« Index (DateTime fd, DateTime? Td) »(и если вы всегда проходите 2 даты, тогда ваш должен сделать то же самое для 'td' (то есть не является нулевым) –

+0

@ Stephen: см. Мое обновление. Спасибо –

ответ

0

Вы должны удалить / перед ? - он должен быть

<a id="btnSearch" class="btn btn-info" href="/Slide/[email protected]`, 

Однако жесткий кодирования URL на основе 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, чтобы опубликовать выбранные даты для метода контроллера, который возвращает только отфильтрованные результаты, чтобы избежать необходимости регенерировать представление каждый тайм е.

+0

шаг курица. Думаю, ты решишь мою проблему. –

0

Ваш жестко строка запроса [email protected]&[email protected] является:

  1. ошибка, особенно если вам необходимо кодировать URL для специальных символов
  2. трудно читать и обслуживать.

В качестве лучшей практики, рекомендуется использовать методы расширения Html.ActionLink() или Html.RouteLink(), поэтому он не будет нарушена, если шаблон URL маршрутизации изменяется (или) нуждается в кодировке URL.

@{ 
    // 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 
) 

Вам действительно нужен симпатичный URL-адрес, который вы написали ниже?

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

Если нет, держите его как родовое, насколько это возможно, как показано ниже.

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

И ваш URL Маршрут будет по-прежнему работать правильно до тех пор, как вы используете Html.ActionLink(), как я показал выше. Это сделает гиперссылку подобным образом.

<a id="btnSearch" class="btn btn-info" 
    href="/Slide/?fd=01/01/2015&to=01/02/2015">Search</a> 

Если вы переписываете свой код, как я показал выше, я уверен, что он исправит вашу проблему.

+0

Извините, мой компьютер не работает после того, как я разместил вопрос, чтобы не попробовать ваше предложение. Я обновил свой вопрос, чтобы уточнить мою проблему. Извиняюсь за любую путаницу. –