我是.NET框架的新手,我遇到了Microsoft.AspNetCore.Http.HttpRequest
界面的问题。我正在尝试使用GetDisplayUri扩展名,但它返回的URI无效。稍后我将URI传递给System.Uri.CreateThis()
,并抛出以下异常:
System.UriFormatException: Invalid URI: The format of the URI could not be determined.
GetDisplayUri
方法应该根据HttpRequest
内的字段创建一个URL,但是我无法弄清楚URL的哪些部分在哪个字段中,我不能在网上找到这个例子。我特别想知道如何将网址分解为Path
,PathBase
和QueryString
变量。
例如,假设我想构建网址"http://example.com/route/endpoint?foo=bar"
。我很确定我的QueryString
只是"?foo=bar"
,但我不知道如何将其余的URL分解为其他字段。另请告诉我,除了我提到的与GetDisplayUri
相关的三个字段之外还有其他字段。
如果有什么不清楚,请告诉我。
答案 0 :(得分:2)
我可能无法帮助您确定异常的来源,但我可以举例说明如何根据请求和查询字符串构建/重建URL。
我有一个显示记录列表的屏幕。由于其中有很多,我需要支持过滤和分页。过滤器作为查询字符串放置,即?foo1=bar1&foo2=bar2
。分页也会在网址上添加其他页面大小和当前页码,即size=15&page=1
。
我没有使用GetDisplayUri()
,而是使用UrlHelperExtensions
获取当前的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;
}
}
}
最后,我可以使用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">
< 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>
}
这样,分页上的链接会反映到当前网址,其中包含查询字符串,以及页面大小和当前页面。
答案 1 :(得分:1)
好的,经过大约一个小时的反复试验,我发现哪些字段映射到了网址的哪个部分。一般表单为url = [Scheme]://[Host][PathBase][Path][QueryString]
,每个表单都有关于如何连接它们的特定规则(例如,Path和PathBase必须以/
开头)。
因此,在问题("http://example.com/route/endpoint?foo=bar"
)的示例中,您的HttpRequest对象需要以下字段。
var request = class_implementing_HttpRequest() {
Scheme = "http",
Host = new HostString("example.com"),
PathBase = new PathString("/route"),
Path = new PathString("/endpoint"),
QueryString = new QueryString("?foo=bar")
}
由于隐藏了GetDisplayUri
的实施,因此有点令人讨厌。希望如果其他人碰到这个,我已经为你节省了一个小时的猜测和检查。
编辑:正如大卫在他的回答评论中指出的那样,.NET Core是开源的,我本可以找到答案here。