Criando métodos no lado Cliente/Servidor (DirectMethod)

Sumário

DirectMethod

Para um melhor entendimento deste Artigo veja o Índice (Rich Internet Applications com Ext.Net)

Criando métodos no lado Cliente/Servidor (DirectMethod)

Como vimos, os DirectEvents são extremamente poderosos, são inseridos no controle, lançados no lado cliente e executados no lado servidor.

Com todo este poder de trabalhar do lado cliente integrando ao lado servidor, temos os “DirectMethods“.

note-taking Logo, podemos definir que “DirectMethods” são métodos em .NET definidos no servidor que podemos chama-los no lado cliente pelo javascript.

Vejamos dois exemplos:

Chamando pelo Handler

ASPX Code

<ext:Button ID="Button1" runat="server" Text="Que horas são?" Icon="Clock">
	<Listeners>
		<Click Handler="App.direct.ShowServerTime();">
		</Click>
	</Listeners>
</ext:Button>

Code Behind

[DirectMethod]
public void ShowServerTime()
{
	X.MessageBox.Show(new MessageBoxConfig
	{
		Buttons = MessageBox.Button.OK,
		Title = "Server Time",
		Message = "No servidor são exatamente " + DateTime.Now.ToLongTimeString(),
		Icon = MessageBox.Icon.INFO
	});
}

Chamando pelo ponteiro (Fn)

ASPX Code

<script type="text/javascript" src="../Scripts/DirectMethods.js"></script>
<ext:Button ID="Button2" runat="server" Text="Que horas são?" Icon="Clock">
	<Listeners>
		<Click Fn="MyApp.showTime">
		</Click>
	</Listeners>
</ext:Button>

Crie um arquivo javascript e cole seguinte código no seu arquivo:

/**
<pre> Arquivo de definição dos objetos em javascript
 */

// definir o namespace de base para a aplicação
var MyApp = {};

MyApp.showTime = function() {
    App.direct.ShowServerTime();
};

Vamos analisar agora os pontos importantes do código que foi montado.
Primeiro vamos pegar a definição do método “public void ShowServerTime()” nele temos a definição do atributo  “[DirectMethod]“.

O atributo “DirectMethod” diz ao Ext.NET para criar um proxy entre o cliente e o servidor, automaticamente será criado um código javascript e o nosso método será exposto como um método  javascript.

note-taking Os métodos do tipo “DirectMethod“, diferentes dos tipos ASPX, não precisam ser estáticos, podem ser definidos como não-estáticos e no escopo do objeto.
Se definidos de forma estática, a vantagem é que o ciclo de vida da página ASP não ocorre, mas, em contrapartida, você não pode acessar os controles.

O namespace padrão criado para separar os “DirectMethods” no Ext.NET é o “App.direct“, neste namespace estão todos os “DirectMethods” criados para a requisição. Como pode ser visto na linha em destaque no código javascript.

Perceba que nos dois exemplos, temos a chamada pelo manipulador, “handler” e pela função “Fn“. Ambos já foram explicados no tópico “Utilizando Listeners (Eventos no lado cliente) e DirectEvents (Lado Servidor)“.

Retornando valores

Muitas vezes precisamos ir ao servidor e retornar algum resultado para o lado cliente, isso é possível, pois podemos ter retornos em nossos “DirectMethods“. Vamos aos exemplos:

Com um resultado simples

ASPX Code

<script type="text/javascript" src="../Scripts/DirectMethods.js"></script>
<ext:Button ID="Button3" runat="server" Text="Que horas são?" Icon="Clock">
	<Listeners>
		<Click Fn="MyApp.showTimeResult">
		</Click>
	</Listeners>
</ext:Button>

Code Behind

[DirectMethod]
public string ShowTimeResult()
{
	return "No servidor são exatamente " + DateTime.Now.ToLongTimeString();
}

javascript

MyApp.showTimeResult = function() {
    App.direct.ShowTimeResult({
        success : function(result) {
            Ext.Msg.show({
                title : 'Server Time',
                msg : result,
                buttons : Ext.Msg.OK,
                icon : Ext.Msg.WARNING
            });
        }
    });
};

O retorno não se restringe à apenas os tipos primários, podemos ter o nosso próprio tipo para retornar. Veja o exemplo:

Com um tipo definido

Definindo o nosso tipo

public struct MyInfo
{
	public string Nome { get; set; }
	public string Email { get; set; }
}

ASPX Code

<script type="text/javascript" src="../Scripts/DirectMethods.js"></script>
<ext:Button ID="Button4" runat="server" Text="Quem é você?" Icon="Information">
	<Listeners>
		<Click Fn="MyApp.getInfo">
		</Click>
	</Listeners>
</ext:Button>

Code Behind

[DirectMethod]
public MyInfo GetInfo()
{
	return new MyInfo {
		Nome = "http://desenvolvedores.net",
		Email="aha@evitandospam.com :)"
	};
}

javascript

MyApp.getInfo = function() {
    App.direct.GetInfo({
        success : function(result) {
            var msg = 'Eu sou o site ' + result.Nome + ' e meu e-mail é ' + result.Email;

            Ext.Msg.show({
                title : 'Info',
                msg : msg,
                buttons : Ext.Msg.OK,
                icon : Ext.Msg.INFO
            });
        }
    });
};

DirectMethods com parâmetros

Tipos primitivos

Podemos passar parâmetros para os nossos “DirectMethods“. No exemplo abaixo, eu vou utilizar um parâmetro do tipo data, calcular a idade e retornar a idade que deverá ser exibida ao utilizador da aplicação.

ASPX Code

<ext:DateField ID="DateField1" runat="server" FieldLabel="Data de Nascimento">
</ext:DateField>
<script type="text/javascript" src="../Scripts/DirectMethods.js"></script>
<ext:Button ID="Button5" runat="server" Text="Qual a sua idade?" Icon="Information">
	<Listeners>
		<Click Handler="MyApp.getAge(#{DateField1}.value);">
		</Click>
	</Listeners>
</ext:Button>
note-taking Atenção à linha em destaque, como utilizamos a passagem de parâmetro direto pelo evento, temos que definir a chamada como um “handler” , pois caso contrário o nosso método será chamado durante o carregamento da página. E não queremos isso. 🙂

Code Behind

[DirectMethod]
public int GetAge(DateTime dob)
{
	int age = DateTime.Now.Year - dob.Year;
	if(DateTime.Now.Month < dob.Month ||
		(DateTime.Now.Month == dob.Month &&
		DateTime.Now.Day < dob.Day))
		age--;

	return age;
}

javascript

MyApp.getAge = function(dob) {
    App.direct.GetAge(dob, {
        success : function(result) {
            var msg = 'Olá! Você tem ' + result + ' anos.';

            Ext.Msg.show({
                title : 'Age',
                msg : msg,
                buttons : Ext.Msg.OK,
                icon : Ext.Msg.INFO
            });
        }
    });
};

Parâmetros com tipos definidos

Se existir a necessidade de se passar um tipo definido como parâmetro, isso também é possível. Veja o exemplo:

ASPX Code

<ext:TextField ID="TextField1" runat="server" FieldLabel="Informe seu nome">
</ext:TextField>
<ext:TextField ID="TextField2" runat="server" FieldLabel="Informe seu email">
</ext:TextField>
<ext:Button ID="Button6" runat="server" Icon="Accept" Text="Enviar">
	<Listeners>
		<Click Handler="MyApp.showInfo(#{TextField1}.value, #{TextField2}.value);">
		</Click>
	</Listeners>
</ext:Button>

Code Behind

[DirectMethod]
public string ShowInfo(MyInfo info)
{
	return String.Format("Olá {0}! Seu e-mail é {1}.", info.Nome, info.Email);
}

javascript

MyApp.showInfo = function(nome, email) {
    /*
     * Devemos criar aqui o nosso objeto que será passado como parâmetro.
     * Temos que respoeitar exatamente a definição de nome que demos à nossas
     * propriedades.
     * Os nomes das propriedades do objeto criado não são sensíveis ao caso.
     */
    var myinfo = {
        nome : nome,
        email : email
    };

    App.direct.ShowInfo(myinfo, {
        success : function(result) {
            Ext.Msg.show({
                title : 'Info',
                msg : result,
                buttons : Ext.Msg.OK,
                icon : Ext.Msg.INFO
            });
        }
    });
};

Tratando exceções

Como nossos sitema não é a prova de falhas, temos que tratar as exceções que podem ocorrer no processamento de uma requisição ao servidor.
Nos exemplos abaixo, iremos ver as exceções tratadas e as não tratadas.

Uma exceção tratada

ASPX Code

<ext:Button ID="Button7" runat="server" Icon="Error" Text="Erro :(">
	<Listeners>
		<Click Fn="MyApp.catchException">
		</Click>
	</Listeners>
</ext:Button>

Code Behind

[DirectMethod]
public void CatchException()
{
	try
	{
		throw new Exception("Ops! Um erro foi lançado.");
	}
	catch(Exception ex)
	{
		Ext.Net.ResourceManager.AjaxSuccess = false;
		Ext.Net.ResourceManager.AjaxErrorMessage = ex.Message;
	}
}
note-taking As duas linhas em destaque indicam que o retorno deverá acontecer como uma falha, logo devemos dizer ao Ext.NET que houve um erro na requisição. Para isso passamos a propriedade “Ext.Net.ResourceManager.AjaxSuccess” para false e a propriedade “Ext.Net.ResourceManager.AjaxErrorMessage” irá receber a mensagem de erro que será exibida ao utilizador da aplicação.

javascript

MyApp.catchException = function() {
    App.direct.CatchException({
        failure : function(result) {
            Ext.Msg.alert('Erro!', result);
        }
    });
};
note-taking Neste ponto, temos que tratar um método diferente,no caso o método “failure‘ que será chamado sempre que ocorrer um erro no lado servidor, ou sempre que a propriedade “Ext.Net.ResourceManager.AjaxSuccess” retornar “false“.

Uma exceção não tratada

ASPX Code

<ext:Button ID="Button8" runat="server" Icon="Error" Text="Erro não tratado :(">
	<Listeners>
		<Click Fn="MyApp.unhandledException">
		</Click>
	</Listeners>
</ext:Button>

Code Behind

[DirectMethod]
public void UnhandledException()
{
	throw new Exception("Ops! Um erro não tratado foi lançado.");
}

javascript

MyApp.unhandledException = function() {
App.direct.UnhandledException({
	failure : function(result) {
		Ext.Msg.alert('Erro!', result);
	}
});
}; 

Uma exceção não tratada e sem “failure”

<ext:Button ID="Button9" runat="server" Icon="Error" Text="Erro não tratado e sem failure :(">
	<Listeners>
		<Click Handler="App.direct.UnhandledException();">
		</Click>
	</Listeners>
</ext:Button>

Como podemos perceber, é sempre bom termos o hábito de tratar a falha em uma requisição “DirectMethod“, nunca sabemos se ela irá acontecer ou não devido aos diversos fatores quando desenvolvemos para web.

Se o método “failure” não for especificado, uma caixa de mensagem semelhante à esta será exibida.

request_failure

Mais sobre “DirectMethods”

Como vimos, o namespace padrão definido pelo Ext.NET é o “App.direct”, mas, podemos decidir que queremos utilizar o nosso próprio namespace, para isso temos que modificar a definição do nosso atributo “[DirectMethod]“, vejamos algumas propriedades do mesmo.

Definindo um namespace (CompanyX)

ASPX Code

<ext:Button ID="Button10" runat="server" Icon="ApplicationGo" Text="Namespace Defin">
	<Listeners>
		<Click Fn="MyApp.definedNamespace">
		</Click>
	</Listeners>
</ext:Button>

Code Behind

[DirectMethod(Namespace = "CompanyX")]
public void DefinedNamespace()
{
	X.MessageBox.Show(new MessageBoxConfig
	{
		Buttons = MessageBox.Button.OK,
		Title = "Olá!",
		Message = "Eu fui chamado de um namespace definido por você. :)",
		Icon = MessageBox.Icon.INFO
	});
}
note-taking Perceba que na linha em destaque, nós adicionamos o namespace que queremos para a nossa aplicação, neste caso “CompanyX

javascript

MyApp.definedNamespace = function() {
    CompanyX.DefinedNamespace();
};
question Isto é útil quando temos uma aplicação muito grande, e queremos definir o nosso próprio namespace.
Mas, eu tenho que ficar a todo momento definindo o namespace para um “DirectMethod“?

R: Não.
Você não precisa a todo momento ficar escrevendo o namespace padrão.
Dentro do web.config, nas configurações do ext.net você pode adicionar a seguinte propriedade

<extnet directMethodNamespace="CompanyX"/>

e voilà todos os seus “DirectMethods” estarão utilizando o namespace padrão “CompanyX“.

 

note-taking Mas tome o cuidado de corrigir todos os pontos que você usou o namespace antigo “App.direct“, pois eles deixarão de funcionar.

Para saber mais sobre “DirectMethods” veja os exemplo em http://examples.ext.net/#/Events/DirectMethods/Overview/


É isso ai pessoal 🙂
Até o próximo
♦ Marcelo

Marcelo

Nascido em Juruaia/MG em uma fazenda de criação de búfalos, e residindo na região Sul do Brasil.
Trabalha com desenvolvimento de aplicações desde os 17 anos. Atualmente é Arquiteto Organizacional na Unimake Software.
Para saber mais ... http://desenvolvedores.net/marcelo
[]'s

Você vai gostar de...

Postagens populares.

Deixe um comentário

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.