在 ASP .Net Core MVC 中对日期时间进行排序

发布于 2025-01-12 15:36:26 字数 10913 浏览 3 评论 0原文

我正在 ASP.NET Core MVC 中开发一个 Web 应用程序,其中用户输入一个股票代码,然后获取有关给定股票代码的股票信息。我已经设法添加排序功能。它在数字上工作得很好,但是当它是日期时间(2022 年 3 月 7 日等)时如何对该表进行排序?有人可以帮我解决这个问题吗?这是我的代码:

查看模型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace PoC.Web.ViewModels
{
    public class StockViewModel
    {
        public DateTime Timestamp { get; set; }
        public decimal Open { get; set; }
        public decimal High { get; set; }
        public decimal Low { get; set; }
        public decimal Close { get; set; }
        public decimal Volume { get; set; }
    }

    public class SearchModel
    {
        public string Ticker { get; set; } = "";
        public int PageNr { get; set; } = 1;
        public int PageSize { get; set; } = 10;
        public int TotalRecords { get; set; } = 0;
        public int TotalPages { get; set; } = 0;
        public List<StockViewModel> Results { get; set; } = new List<StockViewModel>();
        public string ErrorMessage { get; set; } = "";
    }

    public class Error
    {
        public string Information { get; set; }
    }
}

StockController

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using PoC.Web.ViewModels;
using ServiceStack;
using PoC.Core.Media.Interfaces;

namespace PoC.Web.Controllers 
{
    public class StockController : Controller
    {
        public IActionResult Index(string ticker = "", int pageNr = 1, int pageSize = 10, string sortOrder="")
        {
            ViewData["TimestampSortParm"] = String.IsNullOrEmpty(sortOrder) ? "timestamp_desc" : "";
            ViewData["VolumeSortParm"] = sortOrder == "Volume" ? "volume_desc" : "Volume";
            ViewData["LowSortParm"] = sortOrder == "Low" ? "low_desc" : "Low";
            ViewData["HighSortParm"] = sortOrder == "High" ? "high_desc" : "High";
            ViewData["OpenSortParm"] = sortOrder == "Open" ? "open_desc" : "Open";
            ViewData["CloseSortParm"] = sortOrder == "Close" ? "close_desc" : "Close";

            var response = new SearchModel { Ticker = ticker };

            if (!String.IsNullOrEmpty(ticker))
            {
                var apiKey = "";
                var apiResponse = $"https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol={ticker}&apikey={apiKey}&datatype=csv".GetStringFromUrl();
                try
                {
                    var allPrices = apiResponse.FromCsv<List<StockViewModel>>().ToList();

                    int totalRecords = allPrices.Count;
                    int totalPages = (totalRecords + pageSize - 1) / pageSize;

                    response.TotalPages = totalPages;
                    response.TotalRecords = totalRecords;

                    switch (sortOrder)
                    {
                        case "Timestamp":
                            response.Results = allPrices.OrderBy(ar => ar.Timestamp).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "volume_desc":
                            response.Results = allPrices.OrderByDescending(ar => ar.Volume).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "Volume":
                            response.Results = allPrices.OrderBy(ar => ar.Volume).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "low_desc":
                            response.Results = allPrices.OrderByDescending(ar => ar.Low).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "Low":
                            response.Results = allPrices.OrderBy(ar => ar.Low).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "high_desc":
                            response.Results = allPrices.OrderByDescending(ar => ar.High).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "High":
                            response.Results = allPrices.OrderBy(ar => ar.High).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "open_desc":
                            response.Results = allPrices.OrderByDescending(ar => ar.Open).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "Open":
                            response.Results = allPrices.OrderBy(ar => ar.Open).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "close_desc":
                            response.Results = allPrices.OrderByDescending(ar => ar.Close).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "Close":
                            response.Results = allPrices.OrderBy(ar => ar.Close).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        default:
                            response.Results = allPrices.OrderByDescending(ar => ar.Timestamp).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                    }
                }
                catch (Exception exc)
                {
                    response.ErrorMessage = apiResponse.FromJson<Error>().Information;
                }
            }
            response.PageNr = pageNr;
            response.PageSize = pageSize;
            return View(response);
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

Index

@model PoC.Web.ViewModels.SearchModel

@{ ViewData["Title"] = "Stocks"; }

<form method="get">
    <div class="text-center">
        <h1 class="display-4">Welcome to the Stocks page.</h1>

        <div class="table-responsive">
            <table class="table small">
                <tr>
                    <td>
                        <label>Enter Ticker</label> <input type="text" asp-for="Ticker" class="form-control" />
                    </td>
                    <td style="vertical-align: bottom; horiz-align: center">  <button asp-controller="Stock" asp-action="Index" class="btn btn-dark">Fetch Data from AlphaVantage</button></td>
                </tr>
            </table>
        </div>

        <div>
            <table class="table">
                <thead class="thead-light">
                    <tr>
                        <th>
                            <a asp-controller="Stock" asp-action="Index" asp-route-ticker="@Model.Ticker" asp-route-sortOrder="@ViewData["TimestampSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">Timestamp</a>
                        </th>
                        <th>
                            <a asp-controller="Stock" asp-action="Index" asp-route-ticker="@Model.Ticker" asp-route-sortOrder="@ViewData["VolumeSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">Volume</a>
                        </th>
                        <th>
                            <a asp-controller="Stock" asp-action="Index" asp-route-ticker="@Model.Ticker" asp-route-sortOrder="@ViewData["LowSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">Low</a>
                        </th>
                        <th>
                            <a asp-controller="Stock" asp-action="Index" asp-route-ticker="@Model.Ticker" asp-route-sortOrder="@ViewData["HighSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">High</a>
                        </th>
                        <th>
                            <a asp-controller="Stock" asp-action="Index" asp-route-ticker="@Model.Ticker" asp-route-sortOrder="@ViewData["OpenSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">Open</a>
                        </th>
                        <th>
                            <a asp-controller="Stock" asp-action="Index" asp-route-ticker="@Model.Ticker" asp-route-sortOrder="@ViewData["CloseSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">Close</a>
                        </th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var m in @Model.Results)
                    {
                        <tr>
                            <td>
                                @m.Timestamp.ToString("dd MMM yyyy")
                            </td>
                            <td>
                                @m.Volume.ToString("N0")
                            </td>
                            <td>
                                @m.Low.ToString("N2")

                            </td>
                            <td>
                                @m.High.ToString("N2")

                            </td>
                            <td>
                                @m.Open.ToString("N2")
                            </td>
                            <td>
                                @m.Close.ToString("N2")
                            </td>
                        </tr>
                    }
                </tbody>
            </table>
        </div>

        <div class="text-center">
            <nav class="navbar-dark align-content-center">
                <ul class="pagination">
                    @for (var i = 1; i <= Model.TotalPages; i++)
                    {
                        <li class="page-item @(i == Model.PageNr ? "active" : "")">
                            <a asp-controller="Stock" asp-action="Index" asp-route-pageNr="@i" asp-route-ticker="@Model.Ticker" asp-route-currentFilter="@ViewData["CurrentFilter"]" class="page-link">@i</a>
                        </li>
                    }
                </ul>
            </nav>
        </div>
    </div>
</form>

I'm working on a web application in ASP.NET Core MVC, in which the user inputs a ticker and then gets stock information about the given ticker. I've managed to add a sorting feature. It works fine on numbers, but how do I sort this table when it's DateTime (07 Mar 2022 etc)? Can someone please help me fix this? This is my code:

View model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace PoC.Web.ViewModels
{
    public class StockViewModel
    {
        public DateTime Timestamp { get; set; }
        public decimal Open { get; set; }
        public decimal High { get; set; }
        public decimal Low { get; set; }
        public decimal Close { get; set; }
        public decimal Volume { get; set; }
    }

    public class SearchModel
    {
        public string Ticker { get; set; } = "";
        public int PageNr { get; set; } = 1;
        public int PageSize { get; set; } = 10;
        public int TotalRecords { get; set; } = 0;
        public int TotalPages { get; set; } = 0;
        public List<StockViewModel> Results { get; set; } = new List<StockViewModel>();
        public string ErrorMessage { get; set; } = "";
    }

    public class Error
    {
        public string Information { get; set; }
    }
}

StockController

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using PoC.Web.ViewModels;
using ServiceStack;
using PoC.Core.Media.Interfaces;

namespace PoC.Web.Controllers 
{
    public class StockController : Controller
    {
        public IActionResult Index(string ticker = "", int pageNr = 1, int pageSize = 10, string sortOrder="")
        {
            ViewData["TimestampSortParm"] = String.IsNullOrEmpty(sortOrder) ? "timestamp_desc" : "";
            ViewData["VolumeSortParm"] = sortOrder == "Volume" ? "volume_desc" : "Volume";
            ViewData["LowSortParm"] = sortOrder == "Low" ? "low_desc" : "Low";
            ViewData["HighSortParm"] = sortOrder == "High" ? "high_desc" : "High";
            ViewData["OpenSortParm"] = sortOrder == "Open" ? "open_desc" : "Open";
            ViewData["CloseSortParm"] = sortOrder == "Close" ? "close_desc" : "Close";

            var response = new SearchModel { Ticker = ticker };

            if (!String.IsNullOrEmpty(ticker))
            {
                var apiKey = "";
                var apiResponse = 
quot;https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol={ticker}&apikey={apiKey}&datatype=csv".GetStringFromUrl();
                try
                {
                    var allPrices = apiResponse.FromCsv<List<StockViewModel>>().ToList();

                    int totalRecords = allPrices.Count;
                    int totalPages = (totalRecords + pageSize - 1) / pageSize;

                    response.TotalPages = totalPages;
                    response.TotalRecords = totalRecords;

                    switch (sortOrder)
                    {
                        case "Timestamp":
                            response.Results = allPrices.OrderBy(ar => ar.Timestamp).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "volume_desc":
                            response.Results = allPrices.OrderByDescending(ar => ar.Volume).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "Volume":
                            response.Results = allPrices.OrderBy(ar => ar.Volume).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "low_desc":
                            response.Results = allPrices.OrderByDescending(ar => ar.Low).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "Low":
                            response.Results = allPrices.OrderBy(ar => ar.Low).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "high_desc":
                            response.Results = allPrices.OrderByDescending(ar => ar.High).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "High":
                            response.Results = allPrices.OrderBy(ar => ar.High).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "open_desc":
                            response.Results = allPrices.OrderByDescending(ar => ar.Open).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "Open":
                            response.Results = allPrices.OrderBy(ar => ar.Open).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "close_desc":
                            response.Results = allPrices.OrderByDescending(ar => ar.Close).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        case "Close":
                            response.Results = allPrices.OrderBy(ar => ar.Close).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                        default:
                            response.Results = allPrices.OrderByDescending(ar => ar.Timestamp).Skip((pageNr - 1) * pageSize).Take(pageSize).ToList();
                            break;
                    }
                }
                catch (Exception exc)
                {
                    response.ErrorMessage = apiResponse.FromJson<Error>().Information;
                }
            }
            response.PageNr = pageNr;
            response.PageSize = pageSize;
            return View(response);
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

Index

@model PoC.Web.ViewModels.SearchModel

@{ ViewData["Title"] = "Stocks"; }

<form method="get">
    <div class="text-center">
        <h1 class="display-4">Welcome to the Stocks page.</h1>

        <div class="table-responsive">
            <table class="table small">
                <tr>
                    <td>
                        <label>Enter Ticker</label> <input type="text" asp-for="Ticker" class="form-control" />
                    </td>
                    <td style="vertical-align: bottom; horiz-align: center">  <button asp-controller="Stock" asp-action="Index" class="btn btn-dark">Fetch Data from AlphaVantage</button></td>
                </tr>
            </table>
        </div>

        <div>
            <table class="table">
                <thead class="thead-light">
                    <tr>
                        <th>
                            <a asp-controller="Stock" asp-action="Index" asp-route-ticker="@Model.Ticker" asp-route-sortOrder="@ViewData["TimestampSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">Timestamp</a>
                        </th>
                        <th>
                            <a asp-controller="Stock" asp-action="Index" asp-route-ticker="@Model.Ticker" asp-route-sortOrder="@ViewData["VolumeSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">Volume</a>
                        </th>
                        <th>
                            <a asp-controller="Stock" asp-action="Index" asp-route-ticker="@Model.Ticker" asp-route-sortOrder="@ViewData["LowSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">Low</a>
                        </th>
                        <th>
                            <a asp-controller="Stock" asp-action="Index" asp-route-ticker="@Model.Ticker" asp-route-sortOrder="@ViewData["HighSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">High</a>
                        </th>
                        <th>
                            <a asp-controller="Stock" asp-action="Index" asp-route-ticker="@Model.Ticker" asp-route-sortOrder="@ViewData["OpenSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">Open</a>
                        </th>
                        <th>
                            <a asp-controller="Stock" asp-action="Index" asp-route-ticker="@Model.Ticker" asp-route-sortOrder="@ViewData["CloseSortParm"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">Close</a>
                        </th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var m in @Model.Results)
                    {
                        <tr>
                            <td>
                                @m.Timestamp.ToString("dd MMM yyyy")
                            </td>
                            <td>
                                @m.Volume.ToString("N0")
                            </td>
                            <td>
                                @m.Low.ToString("N2")

                            </td>
                            <td>
                                @m.High.ToString("N2")

                            </td>
                            <td>
                                @m.Open.ToString("N2")
                            </td>
                            <td>
                                @m.Close.ToString("N2")
                            </td>
                        </tr>
                    }
                </tbody>
            </table>
        </div>

        <div class="text-center">
            <nav class="navbar-dark align-content-center">
                <ul class="pagination">
                    @for (var i = 1; i <= Model.TotalPages; i++)
                    {
                        <li class="page-item @(i == Model.PageNr ? "active" : "")">
                            <a asp-controller="Stock" asp-action="Index" asp-route-pageNr="@i" asp-route-ticker="@Model.Ticker" asp-route-currentFilter="@ViewData["CurrentFilter"]" class="page-link">@i</a>
                        </li>
                    }
                </ul>
            </nav>
        </div>
    </div>
</form>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

岁月染过的梦 2025-01-19 15:36:26

我知道错误是什么。在第 18 行中,我将第一个案例从“timestamp_desc”更改为“Timestamp”,并且成功了。但无论如何,感谢@Crowcoder 提供的有用信息。

I know what the error was. In the line nr 18 i've changed the first case from "timestamp_desc" to "Timestamp" and it worked. But anyway, thanks @Crowcoder for the useful information.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文