답변:
EscapeDataString
항상 사용 (이유에 대한 자세한 내용은 아래 Livven의 답변 참조)
편집 : 인코딩에서 두 가지가 다른 데드 링크 제거
URLEncode
도 마찬가지입니다).
기존 답변이 만족스럽지 않아이 문제를 해결하기 위해 조금 더 깊이 파기로 결정했습니다. 놀랍게도 그 대답은 매우 간단합니다.
사용할 거의 이유가 없습니다 (거의 *) Uri.EscapeUriString
. 문자열을 퍼센트 인코딩해야하는 경우 항상을 사용하십시오 Uri.EscapeDataString
.
* 유효한 사용 사례는 마지막 단락을 참조하십시오.
왜 이런거야? 설명서 에 따르면 :
EscapeUriString 메소드를 사용하여 이스케이프 처리되지 않은 URI 문자열을 Uri 생성자에 대한 매개 변수로 준비하십시오.
이것은 실제로 이해가되지 않습니다. RFC 2396 에 따르면 :
완성 된 URI를 이스케이프하거나 이스케이프 처리하면 의미가 변경 될 수 있으므로 URI는 항상 "이스케이프 된"형식입니다.
인용 된 RFC는 RFC 3986에 의해 폐기되었지만 , 요점은 여전히 유효합니다. 구체적인 예를 살펴보면이를 확인하겠습니다.
다음과 같은 간단한 URI가 있습니다.
http://example.org/
Uri.EscapeUriString
변경하지 않습니다.
이스케이프를 고려하지 않고 쿼리 문자열을 수동으로 편집하기로 결정했습니다.
http://example.org/?key=two words
Uri.EscapeUriString
당신을 위해 공간을 (올바르게) 벗어날 것입니다 :
http://example.org/?key=two%20words
쿼리 문자열을 수동으로 더 편집하기로 결정합니다.
http://example.org/?parameter=father&son
그러나이 문자열은 Uri.EscapeUriString
앰퍼샌드가 다른 키-값 쌍의 시작을 의미한다고 가정하기 때문에에 의해 변경되지 않습니다 . 이것은 당신이 의도 한 것일 수도 아닐 수도 있습니다.
실제로 key
매개 변수를 원하는 것으로 결정 father&son
하면 앰퍼샌드를 이스케이프 처리하여 이전 URL을 수동으로 수정하십시오.
http://example.org/?parameter=father%26son
그러나 Uri.EscapeUriString
퍼센트 문자도 이스케이프되어 이중 인코딩으로 이어집니다.
http://example.org/?parameter=father%2526son
보다시피 Uri.EscapeUriString
의도 된 용도로 사용 &
하면 여러 키-값 쌍 사이의 구분 기호 대신 쿼리 문자열에서 키 또는 값의 일부로 사용할 수 없습니다 .
이는 전체 URI를 이스케이프 처리하기 위해 예약 된 문자를 무시하고 예약되거나 예약되지 않은 문자 만 이스케이프하기 때문에 BTW는 문서와 반대이기 때문 입니다. 이렇게하면와 같은 것으로 http%3A%2F%2Fexample.org%2F
끝나지 않지만 위에서 설명한 문제로 끝납니다.
결국 URI가 유효하면 매개 변수로 Uri construtor에 전달하기 위해 이스케이프 할 필요가 없으며 유효하지 않은 경우 호출 Uri.EscapeUriString
도 마법 솔루션이 아닙니다. 실제로 대부분의 경우는 아니지만 대부분의 경우 작동하지만 결코 신뢰할 수는 없습니다.
키-값 쌍과 퍼센트 인코딩을 수집 한 다음 필요한 구분 기호로 연결하여 항상 URL과 쿼리 문자열을 구성해야합니다. 위에서 언급 한 것처럼 예약 된 문자를 이스케이프하지 않으므로이 Uri.EscapeDataString
용도로 는 사용할 수 있지만 사용할 수 Uri.EscapeUriString
는 없습니다.
예를 들어 사용자 제공 URI를 처리 할 때이를 수행 할 수없는 경우에만 Uri.EscapeUriString
최후의 수단 으로 사용 하는 것이 좋습니다. 그러나 앞에서 언급 한 경고가 적용됩니다. 사용자 제공 URI가 모호한 경우 결과가 바람직하지 않을 수 있습니다.
encodeURI
/ Uri.EscapeUriString
로 필요하지 않습니다 자주 encodeURIComponent
/ Uri.EscapeDataString
(당신이 URI 맥락에서 사용되어야 블라인드의 URL을 deaing 때부터),하지만 그 뜻은 아닙니다 그것의 장소를 가지고 있지 않습니다.
더하기 (+) 문자는 이러한 방법의 차이점에 대해 많은 것을 알 수 있습니다. 간단한 URI에서 더하기 문자는 "공백"을 의미합니다. "행복한 고양이"에 대해 Google에 문의 해보십시오.
유효한 URI (시도)이며 EscapeUriString
수정하지 않습니다.
이제 "happy c ++"에 대해 Google에 문의 해보십시오.
그것은 유효한 URI (시도)이지만 두 개의 플러스는 공백으로 해석되기 때문에 "happy c"를 검색합니다. 이 문제를 해결하기 위해 "happy c ++"를 EscapeDataString
voila *로 전달할 수 있습니다 .
*) 인코딩 된 데이터 문자열은 실제로 "happy % 20c % 2B % 2B"입니다. 공백 문자는 % 20이 16 진수이고 더하기 문자는 % 2B가 16 진수입니다.
원하는 UriBuilder
대로 사용 하는 경우 EscapeDataString
전체 URI의 일부 구성 요소 만 올바르게 이스케이프하면됩니다. 이 질문에 대한 @Livven의 답변은 실제로 사용할 이유가 없다는 것을 증명합니다 EscapeUriString
.
"https://www.google.com/?q=happy c++"
. "?"에서 수동으로 분할해야합니까, 아니면 더 좋은 방법이 있습니까?
EscapeDataString
. 제공 한 URL이 실제 URL 인 경우으로 분할하려고합니다 ?
.
소스의 주석은 차이점을 명확하게 해결합니다. 이 정보가 XML 문서 주석을 통해 전달되지 않는 이유는 미스터리입니다.
EscapeUriString :
이 방법은 퍼센트 부호를 포함하여 예약되거나 예약되지 않은 문자를 피합니다. EscapeUriString은 '#'부호도 이스케이프하지 않습니다.
EscapeDataString :
이 방법은 퍼센트 부호를 포함하여 예약되지 않은 문자가 아닌 모든 문자를 이스케이프합니다.
차이점은 예약 문자 를 처리하는 방법에 있습니다 . EscapeDataString
그들을 탈출; EscapeUriString
하지 않습니다.
RFC 에 따르면 예약 문자는 다음과 같습니다.:/?#[]@!$&'()*+,;=
완전성을 위해 예약되지 않은 문자는 영숫자 및 -._~
두 방법 모두 예약되거나 예약되지 않은 문자를 이스케이프합니다.
나는 일반에 동의 개념EscapeUriString
악이다. 공백과 같은 잘못된 문자 만 이스케이프 하고 예약 문자가 아닌 방법 이 유용하다고 생각합니다. 그러나 %
캐릭터를 다루는 방법에는 문제가 있습니다. 인코딩 된 문자 ( %
2 진수 16 진수)는 URI에서 유효 합니다. EscapeUriString
이 패턴을 감지 %
하고 2 진수로 즉시 진행되면 인코딩을 피하면 훨씬 더 유용 할 것이라고 생각 합니다 .
간단한 예
var data = "example.com/abc?DEF=あいう\x20えお";
Console.WriteLine(Uri.EscapeUriString(data));
Console.WriteLine(Uri.EscapeDataString(data));
Console.WriteLine(System.Net.WebUtility.UrlEncode(data));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(data));
/*
=>
example.com/abc?DEF=%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86+%E3%81%88%E3%81%8A
example.com%2fabc%3fDEF%3d%e3%81%82%e3%81%84%e3%81%86+%e3%81%88%e3%81%8a
*/
Uri.EscapeDataString()
. 다른 접근 방식을 사용하면 시스템에는 가능한 모든 입력에 대해 의도 한 결과를 생성하기에 충분한 정보가 없습니다.