< rewriter >
<書き換える URL = " ^/ユーザー/(d+)$ " to = " ~/User.aspx?id=$1 " 処理= "停止" />
<書き換える URL = " ^/ユーザー/(w+)$ " to = " ~/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( "フォーム" )[0].action = window.location;
の目的は
非常に明白で、フォームのアクションを window.location (つまり、ブラウザのアドレス バーのパス) に変更して、ページが PostBack を実行するときにターゲット アドレスが変更されるようにします。 URL Rewrite 前のアドレスになります。このアプローチではプログラムを正常に実行できますが、実際には満足できません。なぜ?
あまりにも醜いからです。
URL 書き換え後もアドレスをクライアントに公開しているためです。ユーザーが HTTP スニファー (有名な Fiddler など) をインストールしているか、IE でソース ファイルを表示することを直接選択している限り、ターゲット アドレスは何の隠蔽もなくユーザーの目の前に表示されます。書き換えルールをユーザーに知らせるにはどうすればよいでしょうか?私たちはこの問題を解決しなければなりません。解決策は非常にシンプルで、すでに非常に普及しています。それは、コントロール アダプターを使用してフォーム生成の動作を変更することです。ただ、不思議に思うのは、このコントロールアダプターをインターネットで検索してもVB.NET版ばかりで、主にMicrosoftが推進しているC#言語が見つからないことです。 VB.NET の構文を少し理解していれば書き換えることは難しくありませんが、それでもやはり余分な作業になります。そこで、友人が直接使用できるように、このアダプターの C# バージョン コードを投稿します:
namespace Sample.Web.UI.Adapters
{
パブリッククラスFormRewriterControlAdapter :
System.Web.UI.Adapters.ControlAdapter
{
protectedオーバーライドvoid Render( HtmlTextWriterライター)
{
Base .Render( new RewriteFormHtmlTextWriter (ライター));
}
}
パブリッククラスRewriteFormHtmlTextWriter : HtmlTextWriter
{
public RewriteFormHtmlTextWriter( HtmlTextWriterライター)
:ベース(ライター)
{
この.InnerWriter = ライター.InnerWriter;
}
public RewriteFormHtmlTextWriter( TextWriterライター)
:ベース(ライター)
{
this .InnerWriter = ライター;
}
public override void WriteAttribute( string name, string value, bool fEncode)
{
if (名前 == "アクション" )
{
HttpContextコンテキスト = HttpContext .Current;
if (context.Items[ "ActionAlreadyWritten" ] == null )
{
値 = context.Request.RawUrl;
context.Items[ "ActionAlreadyWritten" ] = true ;
}
}
基本.WriteAttribute(名前, 値, fEncode);
}
}
、
このコントロールアダプターは実際には「action」属性が出力される瞬間を待っており、その値を現在のRequestオブジェクトのRawUrl属性に変更します。この属性は、ASP.NET が最初に IIS から要求を受信したときに決定され、その後の BeginRequest の Rewrite 操作では変更されません。したがって、PostBack アドレス変更の問題を解決するには、Form アクションの RawUrl を出力するだけで済みます。
ただし、このコントロール アダプターを有効にするには、Web プロジェクトに "App_BrowsersForm.browser" などのブラウザー ファイルを作成し、そのファイルに次のコードを記述する必要が
あります。
<ブラウザ refID = "デフォルト" >
<コントロールアダプター>
<アダプター controlType = " System.Web.UI.HtmlControls.HtmlForm "
adapterType = " Sample.Web.UI.Adapters.FormRewriterControlAdapter " />
</ controlAdapters >
</ブラウザ>
</ブラウザ>
この時点で、ASP.NET レベルでの URL 書き換えによって引き起こされるポストバック アドレスの変更の問題は完全に解決されました。待て、なぜ「ASP.NET レベル」を強調する必要があるのでしょうか。そうです。IIS レベルで URL 書き換えを行っても、この問題は依然として存在するからです。たとえば、URL 書き換えに IIRF を使用し、上記のコントロール アダプターを有効にしても、ページ上のポストバック アドレスがクライアントによって要求されたアドレスと異なることがわかります。 RawUrlも「不誠実」になってしまったのでしょうか?これは RawUrl によるものではなく、ASP.NET メカニズムによって決定されます。この問題を説明するために、最初の記事「 IIS と ASP.NET 」の図をもう一度見てみましょう。
IIS レベルの URL 書き換えは、上の図の手順 2 の前に発生します。書き換えられるため、IIS の ISAPI セレクターは、処理のために要求を ASPNET ISAPI に渡します。つまり、IIS が処理のために要求を ASP.NET エンジンに渡すとき、ASP.NET が IIS から取得する情報はすでに URL 書き換え後のアドレス (/User.aspx?name=jeffz) になっているため、問題は発生しません。 ASP.NET が要求をどこで処理するかに関係なく、IIS が要求を受信したときの URL を知ることはできません。
言い換えれば、それについて私たちにできることは本当に何もありません。
ただし、「本当に方法がない」という 4 つの言葉は条件付きであり、完全に言うと、「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 を追加すると、IIRF が URL 書き換えの前に元のアドレスをサーバー変数 HTTP_X_REWRITE_URL に保存する必要があることを示します。これで、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 書き換えを使用することによって生じるいくつかの詳細の違いと、その関連点に焦点を当てます。注記。