Использование параметров DateTime на страницах Razor

#c# #datetime #razor-pages #asp.net-core-3.1

#c# #datetime #страницы razor #asp.net-core-3.1

Вопрос:

По сути, я пытаюсь создать фильтр выбора даты для моей страницы списка. Я начал с использования некоторой логики, найденной в функции поиска, подробно описанной здесь: https://learn.microsoft.com/en-us/aspnet/core/data/ef-rp/sort-filter-page?view=aspnetcore-3.1#add-paging

Мой метод Get структурирован следующим образом:

 public async Task OnGetAsync(string sortOrder, string currentFilter, string searchString, int? pageIndex, string startDate, string endDate)
        {
            if (endDate==null)
            {
                endDate = TimeUtils.DateToString(DateTime.Now);
            }
            if (startDate==null)
            {
                startDate = TimeUtils.DateToString(DateTime.Now.AddDays(-60));
            }
            EndDate = TimeUtils.StringToDate(endDate);
            StartDate = TimeUtils.StringToDate(startDate);
            CurrentSort = sortOrder;
            NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "Name";
            DateSort = sortOrder == "Date" ? "" : "Date";
            if (searchString != null)
            {
                pageIndex = 1;
            }
            else
            {
                searchString = currentFilter;
            }
            CurrentFilter = searchString;
            IQueryable<Issue> issuesIQ = _context.Issue.Include(o => o.Agent);
            if (!String.IsNullOrEmpty(searchString))
            {
                issuesIQ = issuesIQ.Where(o => o.Agent.ADAccount.Contains(searchString));
            }
            switch (sortOrder)
            {
                case "name_desc":
                    issuesIQ = issuesIQ.OrderByDescending(o => o.Agent.ADAccount);
                    break;
                case "Date":
                    issuesIQ = issuesIQ.OrderBy(o => o.ContactDate);
                    break;
                case "Name":
                    issuesIQ = issuesIQ.OrderBy(o => o.Agent.ADAccount);
                    break;
                default:
                    issuesIQ = issuesIQ.OrderByDescending(o => o.ContactDate);
                    break;
            }
            int pageSize = 50;
            Issues = await PaginatedList<Issue>.CreateAsync(issuesIQ.AsNoTracking(), pageIndex ?? 1, pageSize);
            
            
        }
  

Это устанавливает диапазон дат до последних 60 дней, когда я изначально загружаю страницу (когда параметры не указаны), и преобразует их в строки (подробнее об этом чуть позже), затем преобразует все, что хранится в этих строках, в объекты DateTime, используемые средством выбора (показано ниже)

 <form asp-page="./Index" method="get">
    <div class="form-actions no-color">
        <p>
            <div class="form-group">
                <label asp-for="StartDate" class="control-label"></label>
                <input asp-for="StartDate" class="form-control"/>
                <span asp-validation-for="StartDate" class="text-danger"></span>
                <label asp-for="EndDate" class="control-label"></label>
                <input asp-for="EndDate" class="form-control"/>
                <span asp-validation-for="EndDate" class="text-danger"></span>
            </div>Find by Agent NT:
            <input type="text" name="SearchString" value="@Model.CurrentFilter" />
            <input type="submit" value="Search" class="btn btn-primary" /> |
            <a asp-page="./Index">Back to full List</a>
        </p>
    </div>
</form>
  

Оттуда я изменяю кнопки next и previous, чтобы передавать значение средства выбора (после преобразования его обратно в строку) методу get при переходе со страницы на страницу.

 <a asp-page="./Index"
   asp-route-sortOrder="@Model.CurrentSort"
   asp-route-pageIndex="@(Model.Issues.PageIndex - 1)"
   asp-route-currentFilter="@Model.CurrentFilter"
   asp-route-endDate="@TimeUtils.DateToString(Model.EndDate)"
   asp-route-startDate="@TimeUtils.DateToString(Model.StartDate)"
   class="btn btn-primary @prevDisabled">
    Previous
</a>
<a asp-page="./Index"
   asp-route-sortOrder="@Model.CurrentSort"
   asp-route-pageIndex="@(Model.Issues.PageIndex   1)"
   asp-route-currentFilter="@Model.CurrentFilter"
   asp-route-endDate="@TimeUtils.DateToString(Model.EndDate)"
   asp-route-startDate="@TimeUtils.DateToString(Model.StartDate)"
   class="btn btn-primary @nextDisabled">
    Next
</a>
  

Теперь, чтобы объяснить, почему я использую строки для параметров и где я застрял. Я заметил, что когда я изначально использовал DateTimes в качестве параметров, я бы установил для них значение по умолчанию DateTime.MinValue , что было не так уж сложно преодолеть, но когда я перейду на следующую страницу, мой URL-адрес будет содержать кучу тарабарщины, а мои значения выбора будут просто читать мм / дд / гггг. Я немного почитал и обнаружил, что IIS не очень хорошо работает с некоторыми разделителями в DateTime, даже с аннотациями [DataType (DataType.Date)], которые у меня были в игре. На данный момент я прочитал некоторую документацию по DateTime.Синтаксический анализ и DateTime.toString и создал эти вспомогательные функции в TimeUtils

 public static DateTime StringToDate(string datetime)
        {
            DateTime dt = DateTime.Parse(datetime);
            return dt;
        }
        public static string DateToString(DateTime dt)
        {
            return dt.ToString("d");
        }
  

Это должно просто преобразовать DateTime в строку типа 9/15/2020, но когда я пытаюсь перейти со страницы на страницу, я получаю следующее в конце моего URL:

/ Проблемы?pageIndex=3amp;EndDate = 9/14/2020amp; StartDate = 7/16/2020

Чтобы свести все это к минимуму, я на правильном пути здесь, и мне просто нужно выполнить дополнительную настройку функций Parse и toString, чтобы исключить эти «/» из строк? Я рассматриваю возможность использования de culture в качестве аргумента в вызове toString для преобразования его в «.», но не уверен, что столкнусь с подобными проблемами.

Ответ №1:

Понял это, продолжив путь, по которому я шел, но с несколькими оговорками я все еще ломаю голову. Обновлены вспомогательные функции TimeUtils следующим образом:

 public static DateTime StringToDate(string datetime)
        {
            DateTime dt = DateTime.ParseExact(datetime,"yyyy-MM-dd",null);
            return dt;
        }
        public static string DateToString(DateTime dt)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(dt.Year);
            sb.Append("-");
            if (dt.Month < 10)
                sb.Append("0");
            sb.Append(dt.Month);
            sb.Append("-");
            if (dt.Day < 10)
                sb.Append("0");
            sb.Append(dt.Day);
            return sb.ToString();
        }
  

Изначально я выбрал формат «ГГГГМДД», но когда я попытался выполнить начальный фильтр (нажав поиск), у меня возникла ошибка, указывающая, что ParseExact не смог преобразовать «2020-09-16» в действительную дату. Я нигде не мог найти в OnGet, где происходило это преобразование, и подумал, что с Append происходит что-то неладное, поэтому я обновил ParseExact до нового формата. Это работало нормально, пока я не перешел на следующую страницу, которая фактически следовала за моей DateToString в исходном кодировании (без знаков «-«) и завершилась неудачей. Я обновил DateToString, включив в него символы «-«, и теперь все работает так, как задумано. Я предполагаю, что какое-то неявное преобразование в «гггг-ММ-дд» происходило на asp-для выбора в фильтре? Независимо от того, работает ли это.

Какая поездка.