c# - .NET Microsoft.AspNetCore.Http.Extensions UriHelper.GetDisplayUrl 返回无效的 URI

标签 c# .net http .net-core

我是 .NET 框架的新手,我遇到了 Microsoft.AspNetCore.Http.HttpRequest 接口(interface)的问题。我正在尝试使用 GetDisplayUri扩展名,但它返回无效的 URI。后来我将 URI 传递给 System.Uri.CreateThis() 并抛出以下异常:

System.UriFormatException: Invalid URI: The format of the URI could not be determined.

GetDisplayUri 方法应该根据 HttpRequest 中的字段创建一个 URL,但我无法弄清楚 URL 的哪些部分在哪些字段中,而且我在网上找不到任何这方面的例子。我特别想知道我应该如何将 URL 分解为 PathPathBaseQueryString 变量。

例如,假设我想构建 URL "http://example.com/route/endpoint?foo=bar"。我很确定我的 QueryString 只是 "?foo=bar" 但我不知道如何将 URL 的其余部分分解为其他字段。另外让我知道除了我提到的三个字段之外是否还有与 GetDisplayUri 相关的其他字段。

如果有任何不清楚的地方,请告诉我。

最佳答案

我可能无法帮助您确定异常的来源,但我可以举例说明如何从请求和查询字符串构建/重建 URL。

我有一个显示记录列表的屏幕。由于它们很多,我需要支持过滤和分页。过滤器作为查询字符串放置,即 ?foo1=bar1&foo2=bar2。分页还在 url 上放置了额外的页面大小和当前页码,即 size=15&page=1

我没有使用 GetDisplayUri(),而是使用了一个 UrlHelperExtensions,它获取当前 Url,检查 url 查询字符串并添加额外的查询字符串(页面大小和当前页面) 根据需要添加到 url。

namespace DL.SO.Project.Framework.Mvc.Extensions
{
    public static class UrlHelperExtensions
    {
        public static string Current(this IUrlHelper url, object routeValues)
        {
            // Get current route data
            var currentRouteData = url.ActionContext.RouteData.Values;

            // Get current route query string and add them back to the new route
            // so that I can preserve them.
            // For example, if the user applies filters, the url should have
            // query strings '?foo1=bar1&foo2=bar2'. When you construct the
            // pagination links, you don't want to take away those query 
            // strings.

            var currentQuery = url.ActionContext.HttpContext.Request.Query;
            foreach (var param in currentQuery)
            {
                currentRouteData[param.Key] = param.Value;
            }

            // Convert new route values to a dictionary
            var newRouteData = new RouteValueDictionary(routeValues);

            // Merge new route data
            foreach (var item in newRouteData)
            {
                currentRouteData[item.Key] = item.Value;
            }

            return url.RouteUrl(currentRouteData);
        }
    }
}

为了进行分页,我需要跟踪当前页面大小、总项目数、当前页、总页数、起始页和结束页。我为此创建了一个类 Pager.cs

namespace DL.SO.Project.Framework.Mvc.Paginations
{
    public class Pager
    {   
        public int TotalItems { get; private set; }
        public int CurrentPage { get; private set; }
        public int CurrentPageSize { get; private set; }
        public int TotalPages { get; private set; }
        public int StartPage { get; private set; }
        public int EndPage { get; private set; }

        public Pager(int totalItems, int currentPage = 1, int currentPageSize = 15)
        {
            currentPageSize = currentPageSize < 15
                ? 15
                : currentPageSize;

            // Calculate total, start and end pages
            var totalPages = (int)Math.Ceiling(
                (decimal)totalItems / (decimal)currentPageSize
            );

            currentPage = currentPage < 1
                ? 1
                : currentPage;

            // Only display +- 2
            var startPage = currentPage - 2;
            var endPage = currentPage + 2;
            if (startPage <= 0)
            {
                endPage = endPage - startPage + 1;
                startPage = 1;
            }
            if (endPage > totalPages)
            {
                endPage = totalPages;
                if (endPage > 5)
                {
                    startPage = endPage - 4;
                }
            }

            this.TotalItems = totalItems;
            this.CurrentPage = currentPage;
            this.CurrentPageSize = currentPageSize;
            this.TotalPages = totalPages;
            this.StartPage = startPage;
            this.EndPage = endPage;
        }
    }
}

最后,我可以在局部 View 上使用 url 扩展和 Pager 类来构造寻呼机。

@model DL.SO.Project.Framework.Mvc.Paginations.Pager
@{
    var showingRangeFrom = (Model.CurrentPage - 1) * Model.CurrentPageSize + 1;
    var showingRangeTo = Model.CurrentPage * Model.CurrentPageSize;

    if (showingRangeFrom > Model.TotalItems)
    {
        showingRangeFrom = Model.TotalItems;
    }
    if (showingRangeTo > Model.TotalItems)
    {
        showingRangeTo = Model.TotalItems;
    }
}

@if (Model != null && Model.TotalItems > 0)
{
    <div class="list-pager">
        <div class="list-pager-info">
            <span>Showing <strong>@showingRangeFrom-@showingRangeTo</strong>
                of <strong>@Model.TotalItems</strong> entries
            </span>
        </div>
        <div class="list-pagination">
            <ul class="pagination">
                <li class="page-item @(Model.CurrentPage == 1? "disabled" : "")">
                    <!-- use Url extension here -->
                    <a href="@Url.Current(new { page = Model.CurrentPage - 1 })" 
                        class="page-link" tabindex="-1">
                        &lt; Prev
                    </a>                        
                </li>
                @for (int i = Model.StartPage; i <= Model.EndPage; i++)
                {
                    <li class="page-item @(i == Model.CurrentPage? "active" : "")">
                        <!-- use Url extension here -->
                        <a href="@Url.Current(new { page = i })" 
                            class="page-link">@i</a>
                    </li>
                }
                <li class="page-item @(Model.CurrentPage >= Model.EndPage? "disabled" : "")">
                     <!-- use Url extension here -->
                     <a href="@Url.Current(new { page = Model.CurrentPage + 1 })" 
                         class="page-link" tabindex="-1">Next ></a>
                </li>
            </ul>
        </div>
    </div>
}

这样,分页上的链接将反射(reflect)到带有查询字符串的当前 url,以及页面大小和当前页面。

关于c# - .NET Microsoft.AspNetCore.Http.Extensions UriHelper.GetDisplayUrl 返回无效的 URI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47599685/

相关文章:

c# - ASP.NET:是否应该在适配器填充数据集后立即关闭连接?

java - 如何在HTTP客户端库中返回JSON?

c# - 从字符串语句中删除最后一个逗号

c# - !=-运算符对结构失败

c# - C# 中的文件系统观察程序仅被触发一次

c# - FileNotFoundException 从 Windows 应用商店应用程序的 Assets 文件夹中读取 JSON 文件

c# - 这个 ConcurrentDictionary + Lazy<Task<T>> 代码是如何工作的?

c# - 保持应用程序始终运行

c# - 使用 Windows.Web.Http.HttpClient 类修补异步请求

http - 在 Erlang 中读取接收到的 HTTP 请求的主体