codememo

상대 경로(리팩터링 메서드)에서 절대 URL 가져오기

tipmemo 2023. 6. 17. 09:25
반응형

상대 경로(리팩터링 메서드)에서 절대 URL 가져오기

상대 URL에서 절대 URL을 얻을 수 있는 네이티브 .NET 방법이 없다는 것에 정말 놀랐습니다.이 문제가 여러 번 논의되었지만 이 문제를 잘 처리할 수 있는 만족스러운 방법을 발견한 적은 없습니다.아래의 방법을 미세 조정하는 것을 도와줄 수 있습니까?

하드 코딩(http/https) 대신 프로토콜을 자동으로 선택하면 될 것 같습니다.그 밖에 부족한 것이 있습니까(캐비닛, 공연 등)?

public static string GetAbsoluteUrl(string url)
    {
        //VALIDATE INPUT FOR ALREADY ABSOLUTE URL
        if (url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) 
           || url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
        { 
            return url;
        }

        //GET PAGE REFERENCE FOR CONTEXT PROCESSING
        Page page = HttpContext.Current.Handler as Page;

        //RESOLVE PATH FOR APPLICATION BEFORE PROCESSING
        if (url.StartsWith("~/"))
        {
            url = page.ResolveUrl(url);
        }

        //BUILD AND RETURN ABSOLUTE URL
        return "http://" + page.Request.ServerVariables["SERVER_NAME"] + "/" 
                         + url.TrimStart('/');
    }

이것은 항상 이 작은 골칫거리에 대한 저의 접근이었습니다.VirtualPathUtility를 사용합니다.ToAbsolute(relativeUrl)를 사용하면 메서드를 정적 클래스의 확장으로 선언할 수 있습니다.

/// <summary>
/// Converts the provided app-relative path into an absolute Url containing the 
/// full host name
/// </summary>
/// <param name="relativeUrl">App-Relative path</param>
/// <returns>Provided relativeUrl parameter as fully qualified Url</returns>
/// <example>~/path/to/foo to http://www.web.com/path/to/foo</example>
public static string ToAbsoluteUrl(this string relativeUrl) {
    if (string.IsNullOrEmpty(relativeUrl))
        return relativeUrl;

    if (HttpContext.Current == null)
        return relativeUrl;

    if (relativeUrl.StartsWith("/"))
        relativeUrl = relativeUrl.Insert(0, "~");
    if (!relativeUrl.StartsWith("~/"))
        relativeUrl = relativeUrl.Insert(0, "~/");

    var url = HttpContext.Current.Request.Url;
    var port = url.Port != 80 ? (":" + url.Port) : String.Empty;

    return String.Format("{0}://{1}{2}{3}",
        url.Scheme, url.Host, port, VirtualPathUtility.ToAbsolute(relativeUrl));
}
new System.Uri(Page.Request.Url, "/myRelativeUrl.aspx").AbsoluteUri

이건 나한테 효과가 있어요

new System.Uri(Page.Request.Url, ResolveClientUrl("~/mypage.aspx")).AbsoluteUri

ASP.NET에서는 "상대 URL"에 대한 참조점을 고려해야 합니다. 페이지 요청이나 사용자 컨트롤에 대한 참조점인지 아니면 단순히 "~/"를 사용하여 "상대 URL"에 대한 참조점인지 여부를 고려해야 합니다.

Uri클래스에는 상대 URL을 절대 URL로 변환하는 간단한 방법이 포함되어 있습니다(상대 URL의 참조점으로 절대 URL이 지정됨).

var uri = new Uri(absoluteUrl, relativeUrl);

한다면relativeUrl사실 절대 URL입니다. 그러면.absoluteUrl무시됩니다.

그러면 유일한 질문은 기준점이 무엇인지, 그리고 "~/" URL이 허용되는지 여부입니다.Uri생성자는 이를 변환하지 않습니다.).

다음은 사용자의 현재 위치 옵션에서 많은 유효성 검사 및 상대 경로 지정을 처리하는 나만의 버전입니다.여기서부터 자유롭게 리팩터링하세요 :)

/// <summary>
/// Converts the provided app-relative path into an absolute Url containing 
/// the full host name
/// </summary>
/// <param name="relativeUrl">App-Relative path</param>
/// <returns>Provided relativeUrl parameter as fully qualified Url</returns>
/// <example>~/path/to/foo to http://www.web.com/path/to/foo</example>
public static string GetAbsoluteUrl(string relativeUrl)
{
    //VALIDATE INPUT
    if (String.IsNullOrEmpty(relativeUrl))
        return String.Empty;
    //VALIDATE INPUT FOR ALREADY ABSOLUTE URL
    if (relativeUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase) 
    || relativeUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
        return relativeUrl;
    //VALIDATE CONTEXT
    if (HttpContext.Current == null)
        return relativeUrl;
    //GET CONTEXT OF CURRENT USER
    HttpContext context = HttpContext.Current;
    //FIX ROOT PATH TO APP ROOT PATH
    if (relativeUrl.StartsWith("/"))
        relativeUrl = relativeUrl.Insert(0, "~");
    //GET RELATIVE PATH
    Page page = context.Handler as Page;
    if (page != null)
    {
        //USE PAGE IN CASE RELATIVE TO USER'S CURRENT LOCATION IS NEEDED
        relativeUrl = page.ResolveUrl(relativeUrl);
    }
    else //OTHERWISE ASSUME WE WANT ROOT PATH
   {
        //PREPARE TO USE IN VIRTUAL PATH UTILITY
        if (!relativeUrl.StartsWith("~/"))
            relativeUrl = relativeUrl.Insert(0, "~/");
        relativeUrl = VirtualPathUtility.ToAbsolute(relativeUrl);
    }

    var url = context.Request.Url;
    var port = url.Port != 80 ? (":" + url.Port) : String.Empty;
    //BUILD AND RETURN ABSOLUTE URL
    return String.Format("{0}://{1}{2}{3}",
           url.Scheme, url.Host, port, relativeUrl);
}

MVC 컨트롤러 또는 보기의 컨텍스트에 있는 경우 다음을 통해 액세스할 수 있는 UrlHelper를 사용할 수 있습니다.Url

Url.Content("~/content/images/myimage.jpg")

다음으로 완전히 확장될 것입니다./virtual_directoryname/content/images/myimage.jpg

컨트롤러 또는 .cshtml 파일에서 사용할 수 있습니다.

네, 그것이 불리는 것은 조금 이상합니다.Content하지만 그것은 자원에 대한 절대적인 경로를 얻기 위해 사용되어야 하기 때문에 말이 됩니다.

여전히 토종 제품을 사용할 만큼 좋은 것은 없습니다.다음은 제가 하게 된 것입니다.

public static string GetAbsoluteUrl(string url)
{
    //VALIDATE INPUT
    if (String.IsNullOrEmpty(url))
    {
        return String.Empty;
    }

    //VALIDATE INPUT FOR ALREADY ABSOLUTE URL
    if (url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
    { 
        return url;
    }

    //GET CONTEXT OF CURRENT USER
    HttpContext context = HttpContext.Current;

    //RESOLVE PATH FOR APPLICATION BEFORE PROCESSING
    if (url.StartsWith("~/"))
    {
        url = (context.Handler as Page).ResolveUrl(url);
    }

    //BUILD AND RETURN ABSOLUTE URL
    string port = (context.Request.Url.Port != 80 && context.Request.Url.Port != 443) ? ":" + context.Request.Url.Port : String.Empty;
    return context.Request.Url.Scheme + Uri.SchemeDelimiter + context.Request.Url.Host + port + "/" + url.TrimStart('/');
}

Business Logic 계층에서 URL을 생성하려는 경우 ASP.NET 웹 양식의 페이지 클래스/Control의 ResolveUrl(...) 등을 유연하게 사용할 수 없습니다.또한 웹 양식의 ResolveUrl(...) 메서드를 놓쳤을 뿐만 아니라 Url을 가져올 수 없는 경우에도 ASP.NET MVC 컨트롤러에서 URL을 생성해야 할 수 있습니다.Url에도 불구하고 작업(...).작업에는 컨트롤러 이름과 작업 이름만 사용되며 상대 URL은 사용되지 않습니다.

사용해 보았습니다.

varuri = newUri(절대Url, relativeUrl)

접근합니다, 하지만 문제도 있습니다.디렉터리에서 , 은 다음과 웹 응 용 프 로 IIS 가 되 은 는 팅 URL 같http://localhost/MyWebApplication1/myPage URL은 "/myPage로 됩니다.http://localhost/MyPage그것은 또 다른 문제입니다.

그래서 이러한 문제점을 극복하기 위해 클래스 라이브러리에서 작업할 수 있는 UrlUtils 클래스를 작성하게 되었습니다.따라서 페이지 클래스에 종속되지 않고 ASP.NET MVC에 종속됩니다.그래서 당신의 클래스 라이브러리 프로젝트에 MVC dll에 대한 참조를 추가하는 것이 괜찮다면 우리 수업은 원활하게 진행될 것입니다.웹 애플리케이션 URL이 다음과 같은 IIS 가상 디렉터리 시나리오에서 테스트했습니다.http://localhost/MyWebApplication/MyPage때때로 Absolute url이 SSL url인지 아니면 비SSL url인지 확인해야 한다는 것을 깨달았습니다.그래서 저는 이 옵션을 지원하는 우리 반 도서관을 썼습니다.상대 URL이 절대 URL이거나 '~/'로 시작하는 상대 URL일 수 있도록 이 클래스 라이브러리를 제한했습니다.

이 라이브러리를 사용하여 전화할 수 있습니다.

string absoluteUrl = UrlUtils.MapUrl("~/Contact");

반환:http://localhost/Contact: URL인 경우:http://localhost/Home/About

반환:http://localhost/MyWebApplication/Contact: URL인 경우:http://localhost/MyWebApplication/Home/About

  string absoluteUrl = UrlUtils.MapUrl("~/Contact", UrlUtils.UrlMapOptions.AlwaysSSL);

반환:**https**://localhost/MyWebApplication/Contact: URL인 경우:http://localhost/MyWebApplication/Home/About

여기는 우리반 도서관입니다.

 public class UrlUtils
    {
        public enum UrlMapOptions
        {
            AlwaysNonSSL,
            AlwaysSSL,
            BasedOnCurrentScheme
        }

        public static string MapUrl(string relativeUrl, UrlMapOptions option = UrlMapOptions.BasedOnCurrentScheme)
        {
            if (relativeUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
                relativeUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
                return relativeUrl;

            if (!relativeUrl.StartsWith("~/"))
                throw new Exception("The relative url must start with ~/");

            UrlHelper theHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);

            string theAbsoluteUrl = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) +
                                           theHelper.Content(relativeUrl);

            switch (option)
            {
                case UrlMapOptions.AlwaysNonSSL:
                    {
                        return theAbsoluteUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase)
                            ? string.Format("http://{0}", theAbsoluteUrl.Remove(0, 8))
                            : theAbsoluteUrl;
                    }
                case UrlMapOptions.AlwaysSSL:
                    {
                        return theAbsoluteUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase)
                            ? theAbsoluteUrl
                            : string.Format("https://{0}", theAbsoluteUrl.Remove(0, 7));
                    }
            }

            return theAbsoluteUrl;
        }
    }   

현재 핸들러를 고려하여 이전의 모든 불만 사항(포트, 논리 URL, 상대 URL, 기존의 절대 URL 등)을 처리하는 최종 버전은 다음 페이지입니다.

public static string ConvertToAbsoluteUrl(string url)
{
    if (!IsAbsoluteUrl(url))
    {
        if (HttpContext.Current != null && HttpContext.Current.Request != null && HttpContext.Current.Handler is System.Web.UI.Page)
        {
            var originalUrl = HttpContext.Current.Request.Url;
            return string.Format("{0}://{1}{2}{3}", originalUrl.Scheme, originalUrl.Host, !originalUrl.IsDefaultPort ? (":" + originalUrl.Port) : string.Empty, ((System.Web.UI.Page)HttpContext.Current.Handler).ResolveUrl(url));
        }
        throw new Exception("Invalid context!");
    }
    else
        return url;
}

private static bool IsAbsoluteUrl(string url)
{
    Uri result;
    return Uri.TryCreate(url, UriKind.Absolute, out result);
}

절대 URL을 검색하려면 다음 코드를 확인하십시오.

Page.Request.Url.AbsoluteUri

저는 도움이 되기를 바랍니다.

이것도 잘 작동합니다.

HttpContext.Current.Server.MapPath(relativePath)

여기서 상대 경로는 "~/foo/file.jpg"와 같습니다.

언급URL : https://stackoverflow.com/questions/3681052/get-absolute-url-from-relative-path-refactored-method

반응형