Сегодня я получил электронное письмо, и меня спросили, почему UpdatePanel может вызвать проблемы, если его объединить с UrlRewrite. Сначала я не отнесся к этому серьезно, потому что раньше я также использовал UpdatePanel в UrlRewrite, и проблем не было. Однако, получив упакованный код от другой стороны, я обнаружил, что проблема действительно повторилась. Если бы я обратился к целевой странице напрямую, проблем не было бы. Потому что я был в это время в компании и не изучил внимательно причину ошибки. По дороге домой я снова и снова моделировал в уме процесс реализации UpdatePanel, но ничего плохого не заметил. В конце концов я не смог сдержаться и, сидя в автобусе, открыл ноутбук и стал внимательно искать проблему. Автобус очень сильно трясло, но, к счастью, я наконец нашел проблему, прежде чем меня вырвало. Мои мысли сейчас все еще были ошибочными.
Воспроизведение проблемы:
Сейчас я воспроизведу проблему. В исходном коде использовался UrlRewriteModule NBear. Для простоты я использовал наиболее распространенный метод UrlRewrite, чтобы получить тот же эффект, стараясь избегать некоторых друзей (включая меня), которые не знакомы с NBear и мешают пониманию статьи. содержание.
Сначала создайте новый веб-сайт с поддержкой ASP.NET AJAX. Создайте файл ~/SubFolder/Target.aspx со следующим содержимым:
~/SubFolder/Target.aspx.
<html xmlns=" http://www.w3.org/1999/xhtml " >
<head runat="сервер">
<title>Целевая страница</title>
</голова>
<тело>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<СодержимоеШаблон>
<%= DateTime.Now.ToString() %>
<asp:Button ID="Button1" runat="server" Text="Refresh" />
</ContentTemplate>
</asp:UpdatePanel>
</форма>
</тело>
</html>
Затем создайте файл Global.asax, предоставьте метод Application_BeginRequest и реализуйте в нем перезапись URL-адресов следующим образом:
Метод Application_BeginRequest в Global.asax.
void Application_BeginRequest (отправитель объекта, EventArgs e)
{
HttpContext context = (отправитель как HttpApplication).Context;
если (context.Request.Path.Contains("Source.aspx"))
{
context.RewritePath("SubFolder/Target.aspx", false);
}
}
Таким образом, когда мы получим доступ к файлу ~/Source.aspx, он будет переписан в ~/SubFolder/Target.aspx, откроем страницу, и все будет нормально:
После нажатия кнопки «Обновить» время обновляется. Затем, когда мы снова нажали кнопку, возникла ошибка: «Sys.WebForms.PageRequestManagerServerErrorException: при обработке запроса на сервере произошла неизвестная ошибка. Код состояния, возвращенный с сервера: 12031».
Анализ проблемы:
Причина этой проблемы в том, что Url Rewrite обновляет адрес, отправленный формой, а UpdatePanel отражает изменение адреса на странице.
Когда мы открываем страницу в первый раз, мы видим, что действие элемента <form /> в исходном файле страницы больше не является исходным файлом Source.aspx, к которому мы получили доступ, а целевым файлом после перезаписи URL-адреса:
действие элемента формы является целевой страницей
...
<form name="form1" Method="post" action="SubFolder/Target.aspx" id="form1">
...
</форма>
...
К счастью, мы используем частичный рендеринг. Пока «цель» верна, UpdatePanel все равно может правильно отправлять и получать данные, а затем обновлять страницу. Поэтому после нажатия кнопки «Обновить» страница обновляется корректно. Однако действие нашего элемента формы также изменилось, что можно увидеть с помощью Web Development Helper и панели инструментов IE Dev:
Поскольку мы напрямую обращались к ~/SubFolder/Target.aspx при выполнении асинхронной обратной передачи, значением действия созданного объекта формы является Target.aspx. В результате UpdatePanel старательно модифицировала действие элемента клиентской формы. Это позволит нам получить доступ к несуществующей странице при повторной отправке, и ошибки неизбежны.
Решите проблему.
Теперь, когда вы обнаружили проблему, вы, естественно, сможете легко ее решить. Нам нужно только отреагировать на событие загрузки Sys.Application. Оно будет срабатывать при первой загрузке страницы и после каждого частичного рендеринга. В это время мы можем изменить атрибут действия элемента формы на странице. , а именно:
Соответствующее событие загрузки Sys.Application.
Sys.Application.add_load(функция()
{
вар форма = Sys.WebForms.PageRequestManager.getInstance()._form;
form._initialAction = form.action = window.location.href;
});
Что касается того, почему элемент формы на странице должен быть получен именно таким способом, что такое _initialAction и зачем его нужно устанавливать, то это предполагает реализацию UpdatePanel, поэтому я не буду объяснять это здесь. Пока на странице размещен такой небольшой фрагмент кода, эта проблема решена.
Углубленный вопрос:
причина этой проблемы на самом деле заключается в том, что после перезаписи URL-адреса действием элемента формы является не адрес, запрошенный клиентом, а целевой адрес перезаписи URL-адреса. Если мы не будем использовать частичный рендеринг, а воспользуемся самым традиционным PostBack, хотя функция страницы не будет повреждена, после PostBack пользователь обнаружит, что содержимое адресной строки изменилось и сразу становится целевым адресом. Это не тот результат, который мы хотим видеть. Теперь, когда он переписан, давайте перепишем его до конца. Конечно, мы все еще можем использовать упомянутый выше метод и использовать JavaScript для изменения действия элемента формы, но этот метод недостаточно «красив», и пользователь также может видеть целевой адрес нашей перезаписи URL-адреса из источника HTML. файл, а не?
Было бы здорово, если бы мы могли задать действие Формы на стороне сервера, но, к сожалению, класс System.Web.UI.HtmlControls.HtmlForm не позволяет нам это сделать. Но, к счастью, мы используем ASP.NET и используем модель объектно-ориентированного программирования. Итак, мы «наследуем» System.Web.UI.HtmlControls.HtmlForm и реализуем наш собственный элемент управления Form:
наследуем класс HtmlForm для реализации нашего собственного From
пространство имен ActionlessForm {
Форма открытого класса: System.Web.UI.HtmlControls.HtmlForm
{
защищенное переопределение void RenderAttributes (писатель HtmlTextWriter)
{
Writer.WriteAttribute("имя", this.Name);
base.Attributes.Remove("имя");
Writer.WriteAttribute("Метод", this.Method);
base.Attributes.Remove("Метод");
this.Attributes.Render(писатель);
base.Attributes.Remove("действие");
если (base.ID != ноль)
Writer.WriteAttribute("id", base.ClientID);
}
}
}
Затем мы можем использовать его на странице. Конечно, перед этим нам нужно прописать его на странице (или в Web.config):
используем собственную реализованную форму.
<%@ Регистрация TagPrefix="skm" Namespace="ActionlessForm"
Сборка="ActionlessForm" %>
...
<skm:Form id="Form1" Method="post" runat="server">
...
</skm:Форма>
...
На этом этапе нам больше не нужно писать «умный» JavaScript на странице. Проблема с действием элемента формы после Url Rewrite решена.
(«Подробные вопросы» относятся к части предыдущей статьи в MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/urlrewriting.asp )
http://www.cnblogs.com/JeffreyZhao/archive/2006/12/27/updatepanel_with_url_rewrite.html