Recebi um e-mail hoje e me perguntaram por que o UpdatePanel causaria problemas se fosse combinado com o UrlRewrite. Não levei isso a sério no início, porque também usei UpdatePanel em UrlRewrite antes e não houve problema. No entanto, depois de receber o código empacotado da outra parte, descobri que o problema realmente havia ocorrido. Se eu acessasse a página de destino diretamente, não haveria problema. Porque eu estava na empresa na época e não estudei cuidadosamente a causa do erro. No caminho para casa, simulei mentalmente o processo de implementação do UpdatePanel repetidamente, mas não notei nada de errado. No final, não pude evitar. Abri meu laptop enquanto estava sentado no ônibus e procurei cuidadosamente o problema. O ônibus estava tremendo muito, mas felizmente finalmente encontrei o problema antes de vomitar. Meu pensamento ainda estava errado.
Reproduzindo o problema:
Agora vou reproduzir o problema. O UrlRewriteModule do NBear foi usado no código original. Por uma questão de simplicidade, usei o método UrlRewrite mais comum para obter o mesmo efeito, tentando evitar alguns amigos (inclusive eu) que não estão familiarizados com o NBear e atrapalham a compreensão do artigo. contente.
Primeiro, crie um novo site ASP.NET habilitado para AJAX. Crie um arquivo ~/SubFolder/Target.aspx com o seguinte conteúdo:
~/SubFolder/Target.aspx
<html xmlns=" http://www.w3.org/1999/xhtml " >
<head runat="servidor">
<title>Página de destino</title>
</head>
<corpo>
<form id="form1" runat="servidor">
<asp:ScriptManager ID="ScriptManager1" runat="servidor">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="servidor">
<ContentTemplate>
<%= DateTime.Now.ToString() %>
<asp:Button ID="Button1" runat="servidor" Text="Atualizar" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
Em seguida, crie um Global.asax, forneça o método Application_BeginRequest e implemente Url Rewrite nele, como segue:
Método Application_BeginRequest em Global.asax
void Application_BeginRequest(objeto remetente, EventArgs e)
{
Contexto HttpContext = (remetente como HttpApplication).Context;
if (context.Request.Path.Contains("Fonte.aspx"))
{
context.RewritePath("SubFolder/Target.aspx", falso);
}
}
Desta forma, quando acessarmos o arquivo ~/Source.aspx, ele será reescrito em ~/SubFolder/Target.aspx, abrirá a página e tudo estará normal:
Após clicar no botão Atualizar, a hora é atualizada. Então, ao clicar novamente no botão, ocorreu o erro: "Sys.WebForms.PageRequestManagerServerErrorException: Ocorreu um erro desconhecido ao processar a solicitação no servidor. O código de status retornado do servidor foi: 12031".
Análise do problema:
A razão deste problema é que Url Rewrite atualiza o endereço enviado pelo Form, e UpdatePanel reflete a alteração no endereço da página.
Quando abrimos a página pela primeira vez, podemos ver que a ação do elemento <form /> no arquivo fonte da página não é mais o Source.aspx que acessamos, mas sim o arquivo alvo após Url Rewrite:
A ação do elemento do formulário é a página de destino
...
<form name="form1" method="post" action="SubFolder/Target.aspx" id="form1">
...
</form>
...
Felizmente, usamos a renderização parcial, desde que o "destino" esteja correto, o UpdatePanel ainda pode enviar e obter dados corretamente e, em seguida, atualizar a página. Portanto, após clicar no botão Atualizar, a página é atualizada corretamente. No entanto, a ação do nosso elemento de formulário também mudou, o que pode ser visto rapidamente usando o Web Development Helper e a IE Dev Toolbar:
Como acessamos diretamente ~/SubFolder/Target.aspx ao executar PostBack assíncrono, o valor da ação do objeto Form gerado é Target.aspx. Como resultado, o UpdatePanel modificou diligentemente a ação do elemento do formulário do cliente. Isso nos permitirá acessar uma página inexistente quando enviarmos novamente, e os erros serão inevitáveis.
Resolva o problema:
Agora que descobriu o problema, naturalmente será capaz de resolvê-lo facilmente. Precisamos apenas responder ao evento de carregamento de Sys.Application. Ele será acionado quando a página for carregada pela primeira vez e após cada renderização parcial. Neste momento, podemos modificar o atributo action do elemento de formulário na página. , como segue:
Evento de carregamento Sys.Application correspondente
Sys.Application.add_load(função()
{
var formulário = Sys.WebForms.PageRequestManager.getInstance()._form;
form._initialAction = form.action = window.location.href;
});
Quanto ao motivo pelo qual o elemento do formulário na página deve ser obtido desta forma, o que é _initialAction e por que deve ser definido, envolve a implementação do UpdatePanel, portanto não vou explicar aqui. Contanto que um pequeno pedaço de código seja colocado na página, esse problema está resolvido.
Pergunta aprofundada:
A razão para este problema é que, após a reescrita de URL, a ação do elemento do formulário não é o endereço solicitado pelo cliente, mas o endereço de destino da reescrita de URL. Se não usarmos Renderização Parcial, mas usarmos o PostBack mais tradicional, embora a função da página não seja danificada, após o PostBack o usuário descobrirá que o conteúdo da barra de endereço mudou e se torna diretamente o endereço de destino. Este não é o resultado que queremos ver. Agora que foi reescrito, vamos reescrevê-lo até ao fim. Claro, ainda podemos usar o método mencionado acima e usar JavaScript para modificar a ação do elemento do formulário, mas esse método não é "bonito" o suficiente, e o usuário também pode ver o endereço de destino de nossa reescrita de URL da fonte HTML arquivo, não?
Seria ótimo se pudéssemos definir a ação do Form no lado do servidor, mas infelizmente a classe System.Web.UI.HtmlControls.HtmlForm não nos permite fazer isso. Mas, felizmente, usamos ASP.NET e o modelo de programação orientado a objetos. Portanto, "herdamos" System.Web.UI.HtmlControls.HtmlForm e implementamos nosso próprio controle Form:
herdamos a classe HtmlForm para implementar nosso próprio From
namespace ActionlessForm {
Formulário de classe pública: System.Web.UI.HtmlControls.HtmlForm
{
substituição protegida void RenderAttributes (escritor HtmlTextWriter)
{
escritor.WriteAttribute("nome", this.Nome);
base.Attributes.Remove("nome");
escritor.WriteAttribute("método", this.Method);
base.Attributes.Remove("método");
this.Attributes.Render(escritor);
base.Attributes.Remove("ação");
if (base.ID! = nulo)
escritor.WriteAttribute("id", base.ClientID);
}
}
}
Então podemos usá-lo na página. Claro que antes disso precisamos cadastrá-lo na página (ou Web.config):
use nosso próprio Form implementado
<%@ Registrar TagPrefix="skm" Namespace="ActionlessForm"
Assembly="ActionlessForm" %>
...
<skm:Form id="Form1" method="post" runat="server">
...
</skm:Formulário>
...
Neste ponto, não precisamos mais escrever um JavaScript "inteligente" na página. O problema de ação do elemento do formulário após a reescrita do URL ser resolvido.
("Perguntas detalhadas" referem-se a parte do artigo anterior no 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