04.02.2009

Context.RewritePath и атрибут action тега form

Как известно для того чтобы использовать friendly-urls нужно в обработчике события BeginRequest производить вызов Context.RewritePath и соответственно переписывать url.
Например /help/default.aspx можно заменить на default.aspx?action=help
Но при этом возникает неприятность. При рендеринге формы в атрибут action будет записан уже новый url ( default.aspx?action=help в нашем случае ) Таким образом, при нажатии на любую кнопку пользователю будет возвращена страница уже без дружественного url

Существует множество способов изменить такое поведение.
Наиболее простой способ - перекрывать метод Render и в нем сначала переписывать значение action а потом вызывать метод базового класса.


protected override void Render(HtmlTextWriter writer)
{
Page.Form.Action = Request.RawUrl;
base.Render(writer);
}



Однако этот метод не очень гибкий, поскольку нужно либо перекрывать метод Render на каждой странице либо создавать наследника класса Page и использовать его.
Еще один подводный камень - свойство Action класса HtmlForm доступно только в .NET Framework 2.0 SP1. Без сервиспака оно недоступно.

Поэтому лучше использовать технологию Adapters.
Для этого нужно создать папку App_Browsers и в ней файл name.browser со следующим содержимым

<browsers>
<browser refid="Default">
<controladapters>
<adapter controltype="System.Web.UI.HtmlControls.HtmlForm" adaptertype="HtmlFormAdapter">
</adapter>
</controladapters>
</browser>
</browsers>

Остается написать класс HtmlFormAdapter


public class HtmlFormAdapter : ControlAdapter
{
protected override void Render(HtmlTextWriter writer)
{
base.Render(new HtmlFormWriter(writer));
}
private class HtmlFormWriter : HtmlTextWriter
{
public HtmlFormWriter(HtmlTextWriter writer)
: base(writer)
{
InnerWriter = writer.InnerWriter;
}
public HtmlFormWriter(TextWriter writer)
: base(writer)
{
InnerWriter = writer;
}
public override void WriteAttribute(string key, string value, bool fEncode)
{
if ( string.Equals(key, "action", StringComparison.CurrentCultureIgnoreCase) )
{
value = HttpContext.Current.Request.RawUrl;
}
base.WriteAttribute(key, value, fEncode);
}
}
}


Перекрываем метод WriteAttribute и подменяем аттрибут action

P.S. существуют и другие методы, о них возможно напишу позже

Комментариев нет:

Отправить комментарий