Создание ActionLink с DateTime в строке запроса в ASP.NET MVC - PullRequest
5 голосов
/ 07 января 2010

У меня есть форма поиска с критерием поиска DateTime плюс некоторые другие критерии:

<form method="get" action="/app/search">
    <input type="text" value="13/01/2010" name="BeginDate"/>
    <input type="text" value="blah" name="SomeOtherCriterion"/>
<form>

Итак, у меня есть контроллер поиска с действием по умолчанию (назовем его Index) и с параметром SearchCriteria.

public class SearchController
{
    public ActionResult Index(SearchCriteria searchCriteria) {//blah }
}    

public class SearchCriteria
{
    public DateTime BeginDate {get; set;}
    public string SomeOtherCriterion {get; set;}
}

Теперь, если я хочу создать ActionLink, передав значение SearchCriteria, таким образом:

Html.ActionLink("Search", "Index", searchCriteria)

Я получаю параметр строки запроса BeginDate в формате США. Глядя на Google и копаясь в System.Web.Routing с помощью Reflector, похоже, потому что он использует InvariantCulture, поэтому я ничего не могу с этим поделать.

Кажется, никто не задавал этот вопрос раньше, поэтому я думаю, что делаю что-то очень глупое ... Пожалуйста, помогите!

РЕДАКТИРОВАТЬ: передать SearchCriteria в ActionLink, а не анонимный объект, чтобы показать, почему я не могу просто сделать пользовательский ToString () самостоятельно.

Ответы [ 7 ]

4 голосов
/ 12 января 2010

Учитывая, что среда, по-видимому, жестко запрограммирована для обработки этого фрагмента данных с использованием InvariantCulture, я не думаю, что вы можете многое сделать, чтобы заставить ее работать прозрачно.

Есть один уродливый вариант - скачать исходный код MVC и извлечь код для всех нарушающих классов от Route до ParsedRoute, чтобы создать собственную реализацию RouteBase, которая делает то, что вам нужно.

Если бы у меня абсолютно было для сохранения объявления DateTime в классе SearchCriteria, то я бы выбрал этот маршрут (извините за каламбур).

Однако гораздо более простым решением было бы изменить класс SearchCriteria, чтобы использовать немного другое объявление для поля DateTime, основанное на типе, подобном этому:

public class MyDateTime
{
  public DateTime Value { get; set; }
  //for passing MyDateTime in place of a DateTime without casting
  public static implicit operator DateTime(MyDateTime instance) { return instance.Value; }
  //so you can assign a MyDateTime from a DateTime without a cast
  //- e.g. MyDateTime dt = DateTime.Now
  public static implicit operator MyDateTime(DateTime instance) { return new MyDateTime() { Value = instance }; }
  //override ToString so that CultureInfo.CurrentCulture is used correctly.
  public override string ToString()
  {
    return Value.ToString(CultureInfo.CurrentUICulture);
  }
}

Теоретически вы сможете развернуть это изменение без особых хлопот.

Большая работа могла бы быть, если у вас много кода, который использует элементы (например, .Days и т. Д.) Экземпляра DateTime в SearchCriteria: вы должны либо воспроизвести эти элементы в MyDateTime, оборачивая вокруг внутреннего DateTime Value или измените весь код на .Value.Member.

2 голосов
/ 14 января 2010

Во избежание проблем, связанных с региональными настройками и «культурой», Я рассматриваю дату и время как отдельные несвязанные поля, а затем собрать их в DateTime в моем контроллере.

Пример:

Year [ ] Month [ ] Day [ ]

Я всегда представляю отдельные текстовые поля для года, месяца и дня в таком порядке, чтобы не было путаницы между форматом США (месяц / день / год) и более или менее остальным форматом мира (день / месяц) /year).

1 голос
/ 15 января 2010

Получите книгу ASP.NET MVC 1.0, написанную Скоттом Хансельманом, Скоттом Гатри, Филом Хааком и Робом Конери. Они фактически делают этот точный сценарий в книге. Они используют определенный маршрут. Я смотрю на это прямо сейчас на странице 216.

Они делают это, разбивая день, месяц и год. Тогда вы несете ответственность за использование этих ценностей, когда они возвращаются.

1 голос
/ 08 января 2010
poking around in System.Web.Routing using Reflector it

кажется, потому что он использует InvariantCulture

Вы действительно уверены в этом? Части Modelbinding и UrlBuilding, которые я проверял, использовали CurrentCulture. Можете ли вы проверить, что произойдет, если вы установили CurrentCulture перед отображением ссылки?

1 голос
/ 07 января 2010

Возможно, вы могли бы использовать Model Binder для форматирования и анализа даты? Просто перечитал статью и заметил, что она не форматирует дату ... Наверное, не получится. Я оставлю ответ, хотя на случай, если он послужит источником непреднамеренного вдохновения:)

1 голос
/ 07 января 2010

Для этого мы используем ISO ("s" в строке формата - ГГГГ-ММ-ДДТЧ: ММ: СС). Он работает правильно, и JavaScript может справиться с этим.

1 голос
/ 07 января 2010

Можете ли вы предоставить отформатированную дату в своем ActionLink? Попробуйте это:

Html.ActionLink("Search", 
                "Index", 
                new {BeginDate = 
                      DateTime.Now.ToString("d", new CultureInfo("pt-BR");})

Конечно, это меняет BeginDate на строку вместо DateTime ... но, возможно, это будет работать для вас?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...