статьи : <rewriter>
< переписать url = " ^/User/(d+)$ " to = " ~/User.aspx?id=$1 " обработка = " остановить " />
< переписать url = " ^/User/(w+)$ " to = " ~/User.aspx?name=$1 " обработка = " остановить " />
</ rewriter >
Когда пользователь запрашивает «/User/jeffz», на странице отображается код <form action="/User.aspx?name=jeffz" />. Это связано с тем, что при создании кода, страница Текущее значение Request.Url.PathAndQuery будет использоваться для получения действия элемента формы. Это приводит к тому, что «User.aspx?name=jeffz» появляется в адресной строке после PostBack, и этот адрес может не иметь возможности запросить правильный ресурс (поскольку он может быть перезаписан в другом месте или из-за отношений на уровне каталога). Нет такой ресурс). В предыдущей статье « UpdatePanel и UrlRewrite » я говорил, что эту проблему можно решить, добавив в конец страницы строку кода JavaScript:
< script Language ="javascript" type ="text/javascript">
document.getElementsByTagName( "форма" )[0].action = window.location;
</script> Цель этой
строки кода очень очевидна. Измените действие формы на window.location (то есть путь в адресной строке браузера), чтобы при выполнении PostBack на странице был указан целевой адрес. быть адресом перед перезаписью URL. Такой подход может заставить программу работать нормально, но меня это действительно не удовлетворяет. Почему?
Потому что это слишком некрасиво.
Потому что мы по-прежнему предоставляем клиенту адрес после перезаписи URL. Пока пользователь устанавливает HTTP-сниффер (например, знаменитый Fiddler) или напрямую выбирает просмотр исходного файла в IE, наш целевой адрес будет отображаться перед пользователем без какого-либо сокрытия. Как мы можем сообщить пользователям о наших правилах переписывания? Мы должны решить эту проблему. Решение очень простое и уже очень популярное: использовать адаптер управления для изменения поведения генерации формы. Но что мне кажется странным, так это то, что все поисковые запросы по этому адаптеру управления в Интернете относятся к версиям VB.NET, но язык C#, продвигаемый в основном Microsoft, найти не удается. Хотя переписать его несложно, если вы хоть немного понимаете синтаксис VB.NET, в конце концов, это все равно дополнительная работа. Поэтому я опубликую код версии C# этого адаптера, чтобы друзья могли использовать его напрямую:
пространство имен Sample.Web.UI.Adapters
{
общедоступный класс FormRewriterControlAdapter :
System.Web.UI.Adapters.ControlAdapter
{
защищенное переопределение void Render (писатель HtmlTextWriter )
{
base .Render( новый RewriteFormHtmlTextWriter (писатель));
}
}
общедоступный класс RewriteFormHtmlTextWriter : HtmlTextWriter
{
public RewriteFormHtmlTextWriter (писатель HtmlTextWriter )
: база (писатель)
{
это .InnerWriter = Writer.InnerWriter;
}
public RewriteFormHtmlTextWriter (писатель TextWriter )
: база (писатель)
{
это .InnerWriter = писатель;
}
общедоступное переопределение void WriteAttribute(имя строки , значение строки , bool fEncode)
{
если (имя == "действие" )
{
Контекст HttpContext = HttpContext .Current;
if (context.Items[ "ActionAlreadyWritten" ] == null )
{
значение = context.Request.RawUrl;
context.Items[ "ActionAlreadyWritten" ] = true ;
}
}
base .WriteAttribute(имя, значение, fEncode);
}
}
}
Проще говоря, этот адаптер управления фактически ждал момента вывода атрибута «action» и менял значение на атрибут RawUrl текущего объекта Request. Этот атрибут определяется, когда ASP.NET впервые получает запрос от IIS. Он не изменится при последующей операции перезаписи в BeginRequest. Поэтому нам нужно только вывести RawUrl для действия формы, чтобы решить проблему изменения адреса PostBack.
Однако, чтобы этот адаптер управления вступил в силу, необходимо также создать файл браузера в веб-проекте, например «App_BrowsersForm.browser», и написать в нем следующий код:
< браузеры >
< браузер refID = « По умолчанию » >
<controlAdapters>
< адаптер controlType = " System.Web.UI.HtmlControls.HtmlForm "
тип адаптера = " Sample.Web.UI.Adapters.FormRewriterControlAdapter " />
</ Адаптеры управления >
</ браузер >
</ браузеры >
На данный момент проблема изменения адреса PostBack, вызванная перезаписью URL-адреса на уровне ASP.NET, полностью решена — подождите, почему мы должны подчеркивать «уровень ASP.NET»? Это верно, потому что если вы выполняете перезапись URL-адресов на уровне IIS, эта проблема все равно существует. Например, если вы используете IIRF для перезаписи URL-адресов и включаете указанный выше адаптер управления, вы все равно обнаружите, что адрес PostBack на странице отличается от адреса, запрошенного клиентом. Неужели RawUrl тоже стал «нелояльным»? Это не связано с RawUrl, а определяется механизмом ASP.NET. Чтобы объяснить эту проблему, давайте еще раз взглянем на диаграмму из первой статьи « IIS и ASP.NET »:
Перезапись URL-адреса на уровне IIS происходит перед шагом 2 на рисунке выше. Поскольку он переписан, селектор ISAPI IIS передаст запрос ASPNET ISAPI для обработки. Другими словами, когда IIS передает запрос на обработку механизму ASP.NET, информация, которую ASP.NET получает от IIS, уже является адресом после перезаписи URL-адреса (например, /User.aspx?name=jeffz), поэтому не имеет значения. Независимо от того, где ASP.NET обрабатывает запрос, он не может знать URL-адрес, когда IIS получил запрос.
Другими словами, мы действительно ничего не можем с этим поделать.
Однако четыре слова «на самом деле нет никакого способа» являются условными. Если говорить полностью, то это должно быть так: «полагаться на сам ASP.NET» действительно означает «нет никакого способа». Но что, если IIS поможет нам при перезаписи URL-адресов? Будучи зрелым компонентом с открытым исходным кодом, 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]
Обратите внимание, что мы используем дополнительный модификатор. Добавление U в коллекцию модификаторов означает, что нам нужно, чтобы IIRF сохранил исходный адрес перед перезаписью URL-адреса в серверной переменной HTTP_X_REWRITE_URL. Теперь мы можем получить это значение в ASP.NET, поэтому модифицируем метод WriteAttribute в предыдущем коде адаптера управления следующим образом:
public override void WriteAttribute( string name, string value, bool fEncode)
{
если (имя == "действие" )
{
Контекст HttpContext = HttpContext .Current;
if (context.Items[ "ActionAlreadyWritten" ] == null )
{
значение = context.Request.ServerVariables[ "HTTP_X_REWRITE_URL" ]
?? контекст.Запрос.RawUrl;
context.Items[ "ActionAlreadyWritten" ] = true ;
}
}
base .WriteAttribute(имя, значение, fEncode);
}
Теперь значение действия не просто получается из атрибута RawUrl, а пытается получить значение переменной HTTP_X_REWRITE_URL из коллекции ServerVariables, потому что там хранится адрес исходного запроса, полученного IIS.
На этом этапе основные темы перезаписи URL-адресов были рассмотрены. В следующей статье, которая является последней в этой серии, мы сосредоточимся на различиях в некоторых деталях, вызванных использованием разных уровней перезаписи URL-адресов, а также на соответствующих моментах. примечание.