Hoje aprenderemos como usar a propriedade EnablePageMethods do controle ScriptManager e trabalhar com a biblioteca Sys.Net.PageMethod oferecida pelo Microsoft ASP.NET Ajax 1.0 para utilização em conjunto com a linguagem Javascript.
Introdução:
Muitos têm a necessidade de interagir com as funções e classes server-side do ASP.NET utilizando o Ajax (antigo Atlas) com a linguagem Javascript. Por falta de um exemplo claro e material para estudo sobre esse assunto específico, muitas pessoas acabam recorrendo a outros componentes e bibliotecas Ajax encontradas no mercado. Eu mesmo já me deparei com aplicativos utilizando duas “dll's” (Ajax), onde o aplicativo inteiro utilizava ASP.NET Ajax e, por uma necessidade específica utilizou outra biblioteca Ajax em um Web Form para fazer essa comunicação com o servidor, através de um código Javascript usado no Form. Geralmente esse tipo de “ajeito técnico” é válido quando queremos transformar um problema em uma “solução rápida”, desde que o mesmo não comprometa o desempenho nem o funcionamento do código, mas nem sempre esse “ajeito” é considerado uma boa prática.
Codificando:
Para iniciar nosso artigo, abra o Visual Studio.NET SP1 e crie um Novo Projeto > C# > ASP.NET Web Application com o nome de PageMethod [figura 1]; depois abra o Web Form padrão (Default.aspx) e arraste um controle do tipo ScriptManager [figura 2] do Ajax, feito isso adicione dois botões da categoria HTML Controls Input (Submit) e crie um DIV no HTML com o id = ResultId ou um Label para o Form também com id = ResultId.
Veja abaixo na listagem 1 como ficou o HTML completo do Form que será usado no nosso exemplo:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Page Methods - ScriptManager(Microsoft Ajax)</title>
</head>
<body>
<h2>Usando PageMethods com Session</h2>
<h4>Utilizando javascript para acessar valores "server side" como Session, Configurações do Web.Config etc ou invocar funções do Code Behind!</h4>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1"
runat="server" EnablePageMethods="true">
<Scripts>
<asp:ScriptReference Path="PageMethod.js"/>
</Scripts>
</asp:ScriptManager>
</form>
<center>
<table>
<tr align="left">
<td >
Escrevendo a data e hora atual em uma Sessão:</td >
<td>
<input type="Button"
onclick="SetSessionValue(SessionValue, Date())"
value="Salvar" />
</td >
</tr >
<tr align ="left">
<td>
Recuperando a data e hora armazenados na Sessão:</td>
<td>
<input type="Button"
onclick="GetSessionValue(SessionValue)"
value="Recuperar" />
</td>
</tr>
</table>
</center>
<hr/>
<span id="ResultId"></span>
</body>
</html>
Com o HTML completo conforme Listagem 1, iremos fazer as devidas configurações necessárias. Aos botões Input (Submit) adicione o evento onclick e faça a chamada à função Javascript que se comunicará com a função do servidor e que será responsável pela criação e recuperação do valor da Sessão, veja como ficará cada controle na Listagem 2:
Input 1
Type=”Button”
Value=”Salvar”
Onclick=”SetSessionValue('SessionValue'),Date())”
Input 2
Type=”Button”
Value=”Recuperar”
Onclick=”GetSessionValue('Sessionvalue')”
Vamos para as configurações do ScriptManager, mas antes crie um novo arquivo do tipo Jscript File (Projeto > Add > New Item > Jscript File) [figura 5] com o nome de PageMethod.js [figura 6] e coloque o código Javascript da Listagem 3
// PageMethods.js
var displayElement;
// Criando variáveis globais, executando e criando a Sessão.
function pageLoad()
{
displayElement = $get("ResultId");
PageMethods.SetSessionValue("SessionValue", Date(),
OnSucceeded, OnFailed);
}
// Recuperar o valor da Sessão.
function GetSessionValue(key)
{
PageMethods.GetSessionValue(key,
OnSucceeded, OnFailed);
}
//Salvando a Data e hora atual na Sessão.
function SetSessionValue(key, value)
{
PageMethods.SetSessionValue(key, value,
OnSucceeded, OnFailed);
}
// Função de retorno caso seja invocado com sucesso
function OnSucceeded(result, userContext, methodName)
{
if (methodName == "GetSessionValue")
{
displayElement.innerHTML = "Valor atual da Sessão: " +
result;
}
}
// Função de retorno caso algo dê errado
function OnFailed(error, userContext, methodName)
{
if(error !== null)
{
displayElement.innerHTML = "Ocorreu um erro: " +
error.get_message();
}
}
if (typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
Agora sim, clique no controle ScriptManager e em propriedades, clique em Scripts e adicione uma nova referência ao arquivo Javascript recém criado conforme figura 7. Reparem a diferença de um código Javascript comum com o código mostrado da listagem 3 onde podemos perceber o uso de método da biblioteca do Ajax (Sys.Net), vemos trechos como: “displayElement = $get("ResultId")“ e itens específicos como: “error.get_message()” e “Sys.Application.notifyScriptLoaded()”.
Ao concluir, vá até o código (arquivo .cs) da página ASP.NET e vamos trabalhar com as funções que serão chamadas pelo Javascript para interação com a Sessão do aplicativo.
Veja como ficou o código do Web Form na listagem 4 abaixo:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Web.Services;
namespace PageMethod
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[WebMethod]
// Recuperando o valor da Sessão.
public static string GetSessionValue(string key)
{
return (string)HttpContext.Current.Session[key];
}
[WebMethod]
// Salvando o valor da Sessão.
public static string SetSessionValue(string key, string value)
{
HttpContext.Current.Session[key] = value;
return (string)HttpContext.Current.Session[key];
}
}
}
Percebam o uso da identificação [WebMethod] antes de cada função que será usada e da importação da classe “System.Web.Services”. Isso é necessário por que a biblioteca do Ajax (Sys.Net.PageMethod) utiliza a classe System.Web.Services e seus métodos para compartilhar os métodos server-side e torná-los acessíveis através do código client-side (Javascript).
Configurações do Web.Config (Microsoft ASP.NET Ajax 1.0)
Para finalizar, após tudo isso não podemos nos esquecer das configurações do Web.Config para que o ASP.NET Ajax 1.0 funcione corretamente. Caso crie um novo projeto usando um Template de Projeto com Ajax não precisará das configurações da listagem 5:
<?xml version="1.0"?><configuration>
<configSections>
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere"/>
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
</sectionGroup>
</sectionGroup>
</sectionGroup>
</configSections>
<appSettings/>
<connectionStrings/>
<system.web>
<compilation debug="true">
<assemblies>
<add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
<authentication mode="Windows"/>
<pages>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</controls>
<pages>
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
</httpHandlers>
<httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules>
<add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</modules>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated"/>
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</handlers>
</system.webServer>
</configuration>
Comentário
Ultimamente ando lendo em muitos fóruns alguns usuários afirmando que para o aplicativo que utiliza ASP.NET Ajax 1.0 funcione corretamente, o servidor de hospedagem terá que o ter o componente instalado, essa afirmação não é correta. O que acontece é que nas primeiras versões do Atlas, sua instalação não adicionava o Assembly ao GAC (Global Assembly Cache) e também quando se adicionava um objeto do Atlas no Web Form a referência a dll era adicionada e sua propriedade Copy Local era automaticamente marcada como True, o que não acontece nas últimas versões do Atlas agora chamado de ASP.NET Ajax, onde o mesmo é adicionado ao GAC na sua instalação e a propriedade em questão não é marcada como True.
Para resolvermos esse problema podemos simplesmente selecionar o Assembly System.Web.Extensions no Solution Explorer e em propriedades configurar a propriedade Copy Local = True, dessa forma ao compilar o projeto a dll é automaticamente copiada para a pasta Bin do projeto eliminando a necessidade de se ter o componente instalado no servidor [figura 8].
Conclusão
Com esse artigo aprendemos a utilizar o ASP.NET Ajax para chamar funções server-side através da linguagem Javascript. O uso desse exemplo pode ser muito útil, espero que gostem e aproveitem o artigo, qualquer dúvida entre em contato, até o próximo.