2017-12-01 1 views
2

저는 .NET Framework를 처음 사용하고 있으며 Microsoft.AspNetCore.Http.HttpRequest 인터페이스에 문제가 있습니다. GetDisplayUri 확장 프로그램을 사용하려고하는데 잘못된 URI가 반환됩니다. 나중에 나는 System.Uri.CreateThis()에 URI를 전달하고 다음과 같은 예외가 발생지고 :.NET Microsoft.AspNetCore.Http.Extensions UriHelper.GetDisplayUrl이 잘못된 URI를 반환합니다.

GetDisplayUri 방법은 HttpRequest 내부의 필드를 기반으로 URL을 생성하도록되어 있지만, 나는 어떤 부분을 알아낼 수 없습니다
System.UriFormatException: Invalid URI: The format of the URI could not be determined. 

URL은 어떤 필드에 들어가므로이 온라인 예제를 찾을 수 없습니다. 나는 구체적으로 Path, PathBaseQueryString 개의 변수로 URL을 분류해야하는지 궁금합니다.

예를 들어 URL "http://example.com/route/endpoint?foo=bar"을 만들고 싶다고 가정 해 보겠습니다. 나는 내 QueryString이 단지 "?foo=bar" 일 뿐이라고 확신하지만 나머지 URL을 다른 필드로 나누는 방법을 모르겠습니다. GetDisplayUri과 관련이 있다고 언급 한 세 가지 이외의 다른 필드가 있는지 알려주세요.

불명확 한 점이 있으면 알려주십시오.

답변

2

약 1 시간의 시행 착오 끝에 URL의 어느 부분에 어떤 필드가 매핑되는지 알았습니다. 일반 양식은 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 코어는 오픈 소스이며 대답은 here입니다.

2

예외가 발생한 위치를 파악하는 데 도움이되지 않을 수도 있지만 요청 및 쿼리 문자열에서 URL을 작성/재구성하는 방법에 대한 예제를 제공 할 수 있습니다.

레코드 목록을 표시하는 화면이 있습니다. 그것들이 많이 있기 때문에 나는 필터링과 페이지 매김을 지원할 필요가있다. 필터는 검색어 문자열로 배치됩니다 (예 : ?foo1=bar1&foo2=bar2). 페이지 매김은 추가 페이지 크기와 현재 페이지 번호를 URL에도 넣습니다 (즉, size=15&page=1). 대신 GetDisplayUri()를 사용

, 내가 현재 URL을 소요 UrlHelperExtensions가 해당 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; 
     } 
    } 
} 

마지막으로 나는 호출기를 구성하는 부분보기에 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>@[email protected]</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> 
} 

매김에있는 링크가 함께 쿼리 문자열로 현재 URL뿐만 아니라 페이지 크기 및 현재 페이지에 반영이 방법.

+0

이것은 훌륭한 정보이며 도움을 주셔서 감사합니다. GetDislpayUri()를 호출하는 메서드에 대한 단위 테스트를 작성 중이며 실제로 구현을 변경할 수있는 권한이 없으므로 여기서이 메서드를 실제로 사용할 수는 없습니다. – Tom

+1

아, 알겠습니다. .NET Core는 오픈 소스이기 때문에 구현을 들여다 볼 수 있습니까? https://github.com/aspnet/HttpAbstractions/blob/dev/src/Microsoft.AspNetCore.Http.Extensions/UriHelper.cs –

+1

아, 확장 방법이 오픈 소스라는 단서가 없었습니다. 몇 시간 전에 좋았을 텐데. 어쨌든 고마워! – Tom

관련 문제