< rewriter >
< 다시 쓰기 url = " ^/사용자/(d+)$ " = " ~/User.aspx?id = $1 " 처리 = " 중지 " />
< 다시 쓰기 url = " ^/사용자/(w+)$ " = " ~/User.aspx?name=$1 " 처리 = " 중지 " />
</ rewriter >
사용자가 "/User/jeffz"를 요청하면 페이지에 나타나는 코드는 <form action="/User.aspx?name=jeffz" />가 됩니다. 페이지 Request.Url.PathAndQuery의 현재 값은 양식 요소의 작업을 가져오는 데 사용됩니다. 이로 인해 PostBack이 완료되면 주소 표시줄에 "User.aspx?name=jeffz"가 표시되고 이 주소는 올바른 리소스를 요청하지 못할 수 있습니다(다른 곳에 다시 작성될 수 있거나 디렉터리 수준 관계로 인해). 그러한 자원). 이전 기사 " UpdatePanel 및 UrlRewrite "에서 페이지 끝에 JavaScript 코드 한 줄을 추가하면 이 문제가 해결될 수 있다고 말했습니다:
< script Language ="javascript" type ="text/javascript">
document.getElementsByTagName( "form" )[0].action = window.location;
</script> 이 코드 줄의 목적 은
매우 분명합니다. 양식의 동작을 window.location(즉, 브라우저 주소 표시줄의 경로)으로 변경하면 페이지에서 PostBack을 수행할 때 대상 주소가 URL 재작성 전의 주소여야 합니다. 이 방법을 사용하면 프로그램이 정상적으로 실행될 수 있지만 실제로는 만족스럽지 않습니다. 왜?
너무 추악하기 때문입니다.
URL 재작성 후에도 클라이언트에 주소가 노출되기 때문입니다. 사용자가 HTTP 스니퍼(예: 유명한 Fiddler)를 설치하거나 IE에서 소스 파일을 보기 위해 직접 선택하는 한, 대상 주소는 숨김 없이 사용자 앞에 표시됩니다. 사용자에게 재작성 규칙을 어떻게 알릴 수 있나요? 우리는 이 문제를 해결해야 합니다. 솔루션은 매우 간단하고 이미 매우 널리 사용됩니다. 이는 제어 어댑터를 사용하여 양식 생성 동작을 변경하는 것입니다. 그런데 이상한 점은 이 컨트롤 어댑터에 대한 인터넷 검색은 모두 VB.NET 버전인데, 마이크로소프트에서 주로 홍보하는 C# 언어는 찾을 수 없다는 점입니다. VB.NET 구문을 조금만 이해하면 다시 작성하는 것이 어렵지는 않지만 결국에는 여전히 추가 작업입니다. 그래서 친구들이 직접 사용할 수 있도록 이제 이 어댑터의 C# 버전 코드를 게시하겠습니다.
네임스페이스 Sample.Web.UI.Adapters
{
공개 클래스 FormRewriterControlAdapter :
System.Web.UI.Adapters.ControlAdapter
{
보호된 재정의 무효 렌더링( HtmlTextWriter 작가)
{
base .Render( new RewriteFormHtmlTextWriter (작가));
}
}
공개 클래스 RewriteFormHtmlTextWriter : HtmlTextWriter
{
공개 RewriteFormHtmlTextWriter( HtmlTextWriter 작가)
: 베이스 (작가)
{
this .InnerWriter = 작가.InnerWriter;
}
공개 RewriteFormHtmlTextWriter( TextWriter 작가)
: 베이스 (작가)
{
이 .InnerWriter = 작가;
}
공개 재정의 void WriteAttribute( 문자열 이름, 문자열 값, bool fEncode)
{
if (이름 == "작업" )
{
HttpContext 컨텍스트 = HttpContext .Current;
if (context.Items[ "ActionAlreadyWritten" ] == null )
{
값 = context.Request.RawUrl;
context.Items[ "ActionAlreadyWritten" ] = true ;
}
}
기본 .WriteAttribute(이름, 값, fEncode);
}
}
}
간단히 말하면, 이 Control Adapter는 실제로 "action" 속성이 출력되는 순간을 기다리고 있으며, 현재 Request 객체의 RawUrl 속성으로 값을 변경하고 있는 것입니다. 이 속성은 ASP.NET이 처음으로 IIS로부터 요청을 받을 때 결정됩니다. BeginRequest의 후속 다시 쓰기 작업에서는 변경되지 않습니다. 따라서 PostBack 주소 변경 문제를 해결하려면 Form 작업에 대한 RawUrl만 출력하면 됩니다.
그러나 이 제어 어댑터를 적용하려면 웹 프로젝트에 "App_BrowsersForm.browser"와 같은 브라우저 파일을 생성하고 그 안에 다음 코드를 작성
해야 합니다 .
< 브라우저 refID = " 기본값 " >
<컨트롤어댑터>
< 어댑터 controlType = " System.Web.UI.HtmlControls.HtmlForm "
AdapterType = " Sample.Web.UI.Adapters.FormRewriterControlAdapter " />
</ 제어어댑터 >
</ 브라우저 >
</ browsers >
이제 ASP.NET 수준에서 URL 재작성으로 인한 PostBack 주소 변경 문제는 완벽하게 해결되었습니다. 잠깐, 왜 "ASP.NET 수준"을 강조해야 할까요? 그렇습니다. IIS 수준에서 URL 재작성을 수행하면 이 문제가 여전히 존재하기 때문입니다. 예를 들어 URL 재작성에 IIRF를 사용하고 위의 제어 어댑터를 활성화하는 경우에도 페이지의 포스트백 주소가 클라이언트가 요청한 주소와 다르다는 것을 알 수 있습니다. RawUrl도 "불충성"하게 되었나요? 이는 RawUrl 때문이 아니라 ASP.NET 메커니즘에 의해 결정됩니다. 이 문제를 설명하기 위해 첫 번째 기사 " IIS 및 ASP.NET "의 다이어그램을 다시 살펴보겠습니다.
위 그림의 2단계 이전에 IIS 수준 URL 재작성이 발생하므로 IIS의 ISAPI 선택기는 처리를 위해 요청을 ASPNET ISAPI로 전달합니다. 즉, IIS가 처리를 위해 ASP.NET 엔진에 요청을 전달할 때 ASP.NET이 IIS에서 얻은 정보는 이미 URL 재작성 후의 주소(예: /User.aspx?name=jeffz)이므로 상관없습니다. ASP.NET은 요청을 처리하는 위치에 관계없이 IIS가 요청을 받았을 때 URL을 알 수 없습니다.
즉, 이에 대해 우리가 할 수 있는 일은 실제로 아무것도 없습니다.
그러나 "정말 방법이 없습니다"라는 네 단어는 조건부입니다. 완전히 표현하자면 "ASP.NET 자체에 의존하는 것"은 실제로 "방법이 없습니다"입니다. 하지만 URL 재작성을 수행할 때 IIS가 도움이 된다면 어떨까요? 성숙한 오픈 소스 구성 요소인 IIRF는 ASP.NET 엔진과 심지어 모든 ISAPI 처리기에도 도움이 필요하다는 것을 자연스럽게 알고 있습니다. "변경할 때 변경하세요"라는 원칙을 자연스럽게 알고 있으므로 원래 주소를 저장하는 방법을 배웠습니다. 서버 변수 HTTP_X_REWRITE_URL의 기능입니다. 그러나 IIRF는 이 작업을 "의식적으로"(얼마나 피곤한지) 수행하지 않으므로 구성 파일에서 이를 상기시켜야 합니다:
RewriteRule ^/User/(d+)$ /User.aspx?id=$1 [I, L , U ]
RewriteRule ^/User/(w+)$ /User.aspx?name=$1 [I, L, U]
추가 수정자를 사용한다는 점에 유의하세요. Modifier 컬렉션에 U를 추가하면 서버 변수 HTTP_X_REWRITE_URL에 URL을 다시 쓰기 전에 원래 주소를 저장하기 위해 IIRF가 필요하다는 것을 나타냅니다. 이제 ASP.NET에서 이 값을 얻을 수 있으므로 이전 제어 어댑터 코드의 WriteAttribute 메서드를 다음과 같이 수정합니다.
public override void WriteAttribute( string name, string value, bool fEncode)
{
if (이름 == "작업" )
{
HttpContext 컨텍스트 = HttpContext .Current;
if (context.Items[ "ActionAlreadyWritten" ] == null )
{
값 = context.Request.ServerVariables[ "HTTP_X_REWRITE_URL" ]
??컨텍스트.요청.RawUrl;
context.Items[ "ActionAlreadyWritten" ] = true ;
}
}
기본 .WriteAttribute(이름, 값, fEncode);
}
이제 작업 값은 단순히 RawUrl 속성에서 가져오는 것이 아니라 IIS에서 받은 원래 요청의 주소가 ServerVariables 컬렉션에 저장되어 있기 때문에 ServerVariables 컬렉션에서 HTTP_X_REWRITE_URL 변수 값을 가져오려고 시도합니다.
지금까지 URL 재작성에 대한 주요 주제를 다루었습니다. 이 시리즈의 마지막 기사인 다음 기사에서는 다양한 수준의 URL 재작성을 사용하여 발생하는 일부 세부 사항의 차이점과 관련 사항에 중점을 둘 것입니다. 메모.