Utilizando Server.Transfer e ASP.NET AJAX 1.0
Salve desenvolvedores,
depois de incluirmos o ASP.NET AJAX 1.0 no projeto, verificamos um sério problema com o Server.Transfer(novamente). Transferindo dados da Pagina1.aspx que está no diretório /Pasta1/, utilizando Server.Transfer para a Pagina2.aspx que está no diretório /Pasta2/. Ao executarmos uma ação na Pagina2 utilizando o UpdatePanel, após o primeiro post assíncrono, recebiamos o seguinte erro:
Sys.WebForms.PageRequestManagerServerErrorException: An unknown error occurred while processing the request on the server. The status code returned from the server was: 404
Erro 404? Página não encontrada? oras… como o primeiro post funciona e o restante não? Procurei, procurei, procurei e nada. Algumas pessoas com o mesmo erro, desde o Beta 2 e nada.
Então, debugando o Javascript (viva o IE6 hehe), consegui achar o problema.
Quando entramos na Pagina2.aspx pelo Server.Transfer, o action do formulário está correto, nesse caso: “../Pasta2/Pagina2.aspx”, pois o Server.Transfer não muda a URL e ainda estamos rodando no Contexto da Pagina1 (/Pasta1/), então temos que voltar uma pasta, entrar na pasta correta e chamar o arquivo correto.
Adicionando um evento no EndRequest (Sys.WebForms.PageRequestManager.getInstance().add_endRequest…), após o primeiro post, o action do formulário era apenas “Pagina2.aspx”, e nesse caso, como o contexto está ainda na Pasta1, vem a excessão 404.
Isso ocorre, porque dentro do ASP.NET AJAX, arquivo Resource (que é gerado dinamicamente pelo ScriptManager), é chamado o método Sys.Net.WebRequest._resolveUrl.
Sys.Net.WebRequest._resolveUrl = function Sys$Net$WebRequest$_resolveUrl(url, baseUrl) {
if (url && url.indexOf(’://’) !== -1) {
return url;
}
if (!baseUrl || baseUrl.length === 0) {
var baseElement = document.getElementsByTagName(’base’)[0];
if (baseElement && baseElement.href && baseElement.href.length > 0) {
baseUrl = baseElement.href;
}
else {
baseUrl = document.URL;
}
}
var qsStart = baseUrl.indexOf(’?');
if (qsStart !== -1) {
baseUrl = baseUrl.substr(0, qsStart);
}
baseUrl = baseUrl.substr(0, baseUrl.lastIndexOf(’/') + 1);
if (!url || url.length === 0) {
return baseUrl;
}
if (url.charAt(0) === ‘/’) {
var slashslash = baseUrl.indexOf(’://’);
if (slashslash === -1) {
throw Error.argument(”baseUrl”, Sys.Res.badBaseUrl1);
}
var nextSlash = baseUrl.indexOf(’/', slashslash + 3);
if (nextSlash === -1) {
throw Error.argument(”baseUrl”, Sys.Res.badBaseUrl2);
}
return baseUrl.substr(0, nextSlash) + url;
}
else {
var lastSlash = baseUrl.lastIndexOf(’/');
if (lastSlash === -1) {
throw Error.argument(”baseUrl”, Sys.Res.badBaseUrl3);
}
return baseUrl.substr(0, lastSlash+1) + url;
}
}
e nesse caso, ele recupera a URL, “baseUrl = document.URL;”, que ainda está na Pasta1, chamando o action atual, “Pagina2.aspx”, e gerando a excessão pra frente.
Mesmo mudando o action na mão, no evento BeginRequest (Sys.WebForms.PageRequestManager.getInstance().add_beginRequest), não funciona como o esperado.
Para resolver esse problema, basta adicionarmos o seguinte script no codebehind. Nesse caso, eu sei exatamente a estrutura das duas páginas, e passei o parametro na mão. Se alguém quiser, pode fazer essa comparação de diretórios utilizando AppRelativeVirtualPath e Context.Request.FilePath, seria bem-vindo o código.
// Adiciona JS para correção do AJAX
StringBuilder sbJS = new StringBuilder();
string actionUrl = string.Format(”‘{0}’”, “../Pasta2/Pagina2.aspx”);
sbJS.Append(”Sys.Application.add_load(function(){”);
sbJS.Append(” var form = Sys.WebForms.PageRequestManager.getInstance()._form;”);
sbJS.Append(” form._initialAction = ” + actionUrl + “;”);
sbJS.Append(” form.action = ” + actionUrl + “;”);
sbJS.Append(”});”);
ClientScript.RegisterStartupScript(this.GetType(), “CorrecaoAjax”, sbJS.ToString(), true);
Esse foi o único modo que consegui resolver esse outro problema com Server.Transer. Lembrando que eu sei exatamente a estrutura de pastas e sei para onde ele tinha que postar corretamente. E também, porque de uma página para outra, são pastas (estruturas) diferentes.
Esperamos que nessa CTP de janeiro já resolvam esse problema.
:)
Permalink Enviar por e-mail. Hits para esta publicação: 3698.
Penihel disse,
8 de Fevereiro de 2007 @ 07:45
Acho que o Server.Transfer é um dos pontos fracos do ASP.NET AJAX.
Então eu uso o Response.Redirect mesmo.
Abraço
BrunoKenj disse,
8 de Fevereiro de 2007 @ 10:58
Com certeza, Penihel.
Não só utilizando o ASP.NET AJAX… sempre é preciso fazer um gato pra funcionar algum outro controle com Server.Transfer. Aliás, acho que já dá até pra abrir uma categoria Server.Transfer dentro de ASP.NET, kwkw.
E eu nem sei se é tão mais rápido assim, afinal, todo o contexto da outra página (propriedades públicas e controles) é levado também.
No caso, pra guardar valor usando o Redirect, qual a sua idéia? Sessão?
abraços,
Lucas Campos disse,
8 de Fevereiro de 2007 @ 14:42
Eu estou utilizando o Server.Transfer…
Mas em minha outra página não tem o updatePanel…
Está rodando beleza!
Abraços!
Penihel disse,
12 de Fevereiro de 2007 @ 09:17
Bruno.
Sessao, ou quando as informaçoes sao grandes, Tipo uma tabela do banco. Eu guardo ela no Cache,e passo algum ID pela QueryString.
Mj. Logan disse,
5 de Abril de 2007 @ 23:57
Muito obrigado pela sua análise, BrunoKenj!
Inicialmente, procurando pela raiz do meu problema, achei que não tivesse relação com seu post, mas olhando o log do IIS, descobri que era exatamente isso! :^P
Vou modificar seu código para ser aplicável a qualquer URL, e faço outro comment com um novo código. Me poupou (mais) algumas horas de dor de cabeça!
Abraço!
Mj. Logan disse,
6 de Abril de 2007 @ 00:03
Em tempo: o código de erro que aparecia para mim era 12030 (The connection with the server has been reset), mas o problema era o mesmo.
Mj. Logan disse,
9 de Abril de 2007 @ 15:14
Aí está o método que implementei na minha aplicação, que funciona para qualquer diretório virtual. Implementei a partir da solução do BrunoKenj:
///
/// Adds to the page a JavaScript that corrects the misbehavior of AJAX when a page is target of a Server.Transfer call.
///
protected void AjaxUrlBugCorrection()
{
// Adiciona JS para correção do AJAX
string actualFile = Server.MapPath(AppRelativeVirtualPath)
, redirectFile = Server.MapPath(Context.Request.FilePath);
string baseSiteVirtualPath = HttpRuntime.AppDomainAppVirtualPath;
if (actualFile != redirectFile)
{
System.Text.StringBuilder sbJS = new System.Text.StringBuilder();
string actionUrl = string.Format(”‘{0}’”, baseSiteVirtualPath + AppRelativeVirtualPath.Replace(”~”, String.Empty));
sbJS.Append(”Sys.Application.add_load(function(){”);
sbJS.Append(” var form = Sys.WebForms.PageRequestManager.getInstance()._form;”);
sbJS.Append(” form._initialAction = ” + actionUrl + “;”);
sbJS.Append(” form.action = ” + actionUrl + “;”);
sbJS.Append(”});”);
ClientScript.RegisterStartupScript(this.GetType(), “CorrecaoAjax”, sbJS.ToString(), true);
}
}
BrunoKenj disse,
9 de Abril de 2007 @ 15:26
Mj. Logan, bacana! valeu!
Luis Carmelo disse,
21 de Julho de 2007 @ 23:45
Probe el codigo pero solo me funciona la primera vez que se ejecuta la segunda vez me sigue amrcando el mismo error alguien me podria ayudar
gracias
BrunoKenj disse,
29 de Agosto de 2007 @ 02:01
Luis Carmelo, intenta poner el codigo de Sr. Logan.
///
/// Adds to the page a JavaScript that corrects the misbehavior of AJAX when a page is target of a Server.Transfer call.
///
protected void AjaxUrlBugCorrection()
{
// Adiciona JS para correção do AJAX
string actualFile = Server.MapPath(AppRelativeVirtualPath)
, redirectFile = Server.MapPath(Context.Request.FilePath);
string baseSiteVirtualPath = HttpRuntime.AppDomainAppVirtualPath;
if (actualFile != redirectFile)
{
System.Text.StringBuilder sbJS = new System.Text.StringBuilder();
string actionUrl = string.Format(”‘{0}’”, baseSiteVirtualPath + AppRelativeVirtualPath.Replace(”~”, String.Empty));
sbJS.Append(”Sys.Application.add_load(function(){”);
sbJS.Append(” var form = Sys.WebForms.PageRequestManager.getInstance()._form;”);
sbJS.Append(” form._initialAction = ” + actionUrl + “;”);
sbJS.Append(” form.action = ” + actionUrl + “;”);
sbJS.Append(”});”);
ClientScript.RegisterStartupScript(this.GetType(), “CorrecaoAjax”, sbJS.ToString(), true);
}
}
Daniel Lopes disse,
14 de Novembro de 2007 @ 14:33
Também tenho problemas ao utilizar Server.Transfer juntamente com Ajax.
Infelizmente não entendi o funcionamento da função.
No meu caso, tenho várias páginas no sistema que utilizam Ajax e caso ocorram erros estas serão redirecionadas para a página de erro. No “Application_Error” do arquivo global.asax eu utilizo Server.Transfer.
Bem… como devo proceder neste caso?
Att.Daniel
Wanderson Santos disse,
14 de Maio de 2008 @ 21:54
Muito obrigado pela análise!
Alguém poderia confirmar se hoje já existe uma correção oficial deste problema para a versão 1.0 (para uso no framework 2.0)? A versão 3.5 possui este ajuste?
Desde já agradeço,
Wanderson Santos