Custom Workflow Activities - Resolução de incidentes

by Pedro Azevedo 9. September 2013 06:06

Boas pessoal,

EDIT: Eu já cá tinha um exemplo de uma criação de um Custom WorkFlow Activity, o post continua igual (alterei apenas o objectivo) mas mudei o exemplo, o exemplo que tinha era muito simples e estou a trocar por um exemplo que acontece-nos penso que a todos. O objectivo é extrair propriedades da Resolução de Incidente.

Hoje vou fazer um pouco de código C# Smile estava a ver que não… vamos falar em concreto sobre Custom Workflow Activities que permitem estender o comportamento por defeito dos Workflows.

O objectivo será que quando um incidente seja encerrado enviar em email com a descrição de resolução. A primeira opção que ocorria era criar um workflow, o problema é que dentro de um Workflow não conseguimos aceder a entidade Resolução de Incidente.

Uma solução seria criar um campo no incidente com esta informação. Mas existe uma solução mais eficaz que é recorrer a actividades customizadas de Workflow. Dentro desta actividade vamos pesquisar por esta entidade e retornar a descrição.

A primeira coisa a fazer é criar um projecto do template Workflow, do tipo Activity Designer Library:

 

Depois do projecto criado podem apagar o ficheiro que é criado por defeito:

 

E adicionem uma classe normal:

 

Antes de começarmos a colocar código vamos referenciar três DLLs fundamentais para programarmos para o CRM:

 

Estas DLLs estão na pasta onde vocês instalaram o SDK (se não tiverem podem sacar aqui). A seguir podemos colocar o seguinte código:

public class GetIncidentRes : CodeActivity
{
    protected override void Execute(CodeActivityContext activityContext)
    {
        IWorkflowContext contexto = activityContext.GetExtension<IWorkflowContext>();
        IOrganizationServiceFactory serviceFact = activityContext.GetExtension<IOrganizationServiceFactory>();
        IOrganizationService service = serviceFact.CreateOrganizationService(contexto.UserId);

        QueryByAttribute queryIncRes = new QueryByAttribute();
        queryIncRes.Attributes.AddRange(new string[] { "incidentid" });
        queryIncRes.ColumnSet = new ColumnSet(new string[] { "description" });
        queryIncRes.EntityName = IncidentResolution.EntityLogicalName;
        queryIncRes.Values.AddRange(new object[] { contexto.PrimaryEntityId });

        EntityCollection incidentResEntity = service.RetrieveMultiple(queryIncRes);
        IncidentResolution incidentResolution = (IncidentResolution)incidentResEntity.Entities.FirstOrDefault();
        DescrResol.Set(activityContext, incidentResolution.Description);
    }


    [OutputAttribute("DescrResol")]
    public OutArgument<string> DescrResol { get; set; }
}

Temos que referenciar três namespaces:

using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Workflow;

Em relação ao código é bastante simples, temos que derivar de CodeActivity, declarar o nosso output através do atributo OutputAttribute o texto que colocamos é o nome que vai aparecer depois no editor do Workflow. Mais de resto é o que fazemos habitualmente no CRM.

O Visual Studio vai-se queixar que não conhece a class IncidentResolution, isto porque ele não conhece as entidades que temos no CRM. Como estamos a trabalhar apenas com as entidades standard temos um ficheiro com todas as entidades standard na pasta do SDK (\samplecode\cs\helpercode). Poderíamos ter optado por usar o método late bound, mas neste caso quero trabalhar com early bound para isso teremos que gerar as classes das entidades e assim receber as entidades customizadas. Teremos que utilizar a ferramenta crmsvcutil.exe (\bin), a sua definição é a seguinte:

CrmSvcUtil.exe /url:http://<serverName>/<organizationName>/XRMServices/2011/Organization.svc /out:<outputFilename>.cs 
/username:<username> /password:<password> /domain:<domainName>

Podemos adicionar o ficheiro resultante ao nosso projecto:

 

Ao tentarmos compilar vai aparecer mais alguns erros um deles relacionado com a versão do .Net que ele coloca por defeito “.NET Framework 4 Client Profile”, mudamos para a “normal”:

Adicionamos ainda outra referência – System.Runtime.Serialization. Uma última coisa que é adicionar um strong name a nossa DLL:

Depois disto tudo vamos registar a nossa DLL, através da ferramenta: Plugin Registration Tool:

 

 

Depois de escolhermos a nossa DLL, basta dizer qual o workflow que queremos registar e temos o nosso workflow registrado.

Agora já podemos ir ao CRM e fazer o nosso Workflow que quando um incidente for finalizado envie um email com os detalhes da resolução, portanto criamos um novo processo do tipo Fluxo de Trabalho:

Depois de dizermos que o workflow só vai correr aquando da mudança de estado e depois de adicionarmos a condição que é apenas no estado Resolvido, podemos executar a nossa actividade customizada:

Depois deste passo podemos criar o email com base na informação retornada do nossa actividade customizada:

 

E temos a nossa actividade customizada, podem ver a sua funcionalidade e utilidade deste mecanismo.

 

Até a próxima.

Tags: , , , ,

Tudo sobre WebResources III

by Pedro Azevedo 30. August 2013 16:21

Boas pessoal,

Estou de volta com o último post sobre o assunto dos WebResources agora vendo casos práticos de onde posso usar esta funcionalidade:

Dashboard

Para adicionar é semelhante ao que fizemos quando adicionamos um WebResource ao formulário. Vejam o resultado:

Em relação ao exemplo anterior retirei o acesso ao formulário pois aqui não tínhamos essa situação. Mais de resto o código é igual.

 

Navegação no Formulário

Vamos analisar como podemos adicionar no Sitemap:

 

 Vejam o resultado:

Até aqui nada de especial, conseguimos referenciar os WebResources sem uma única linha de código, vamos ver casos mais complicados.

SiteMap – Sub Area

Para adicionarmos este tipo de link é necessário trabalharmos sobre o sitemap, por isso vamos criar um WebResource com o sitemap e vamos utilizar uma ferramenta SiteMapEditor:

Vejam a forma de referenciar o WebResource através da directiva $webresource. Se não utilizarmos esta ferramenta, teríamos que ter adicionar o SiteMap a uma solução, exportar essa solução e mexer directamente no XML e afectar as propriedades que afectamos em cima e depois importar novamente esta solução.

Vejam o resultado:

 Falta-nos falar de um último sítio onde poderemos usar os WebResources, que é na ribbon. Ora na ribbon o interessante é executarmos código Javascript por exemplo para escondermos ou desabilitarmos um botão ou para abrir um WebResource. Já tenho planeado um post para falar como desabilitar um botão na ribbon, por isso aqui vamos abrir um WebResource.

Apenas como exemplo e sem grande ciência adicionei um botão (utilizei a ferramenta RibbonWorkbench) e adicionei uma acção para abrir um URL, neste caso coloquei como endereço $webresource:ret_testewr como podem verificar na imagem.

E podem ver a sua execução:

Para complementar a situação anterior, existe outra forma de abrirmos um WebResource, utilizando a função openWebResource que apareceu com o UR8. Para a utilizarmos em vez de colocarmos um acção do tipo URL vamos criar uma acção para chamar uma função Javascript:

Antes de mostrar o código da função openwr, reparem como ele referenciou o WebResource onde está a função, através da directiva $webresource. A função openwr é muito simples:

function openwr() {
  Xrm.Utility.openWebResource("ret_testewr");
}

E assim finalizamos esta temática.

 

Até a próxima.

Tags: , , ,

Tudo sobre WebResources II

by Pedro Azevedo 25. June 2013 22:07

 Boas pessoal,

Vamos continuar o exemplo anterior e vamos tentar complicar um pouco para percebermos como tirar o maior partido desta funcionalidade.

Vamos então perceber como podemos referenciar um WebResource directamente. Agora quero colocar “OLA Nome do Cliente Potencial”. Para isso vou usar jQuery então adicionei a biblioteca do jQuery a solução através de um WebResource e adicionei o seguinte código:

$(document).ready(function() {
  var nomeCompleto = window.parent.Xrm.Page.getAttribute("fullname").getValue();
  $('#sayHello').append(nomeCompleto);
});

Se voltar abrir um Cliente Potencial vai dar o erro seguinte:

Isto porque mesmo tendo na solução um WebResource com a biblioteca jQuery, o CRM não vai carregar, por essa razão vamos ter que adicionar uma referência ao WebResource que tem a biblioteca jQuery, desta maneira:

<SCRIPT type=text/javascript src="ret_jquery"></SCRIPT>

Gravando, publicando e abrindo novamente o registo temos este resultado:

 

Este tipo de referenciação funciona se tivermos numa estrutura flat. Se tivermos os WebResources em pastas teremos que nos posicionar. Imaginemos que o WebResource ret_testewr estava em html/ret_testewr e que a biblioteca jQuery estava em scripts/ret_jquery, então teríamos que referenciar da seguinte maneira:

<SCRIPT type=text/javascript src="../scripts/ret_jquery"></SCRIPT>

Aqui estamos a usar um URL relativo e é assim que devemos usar, outra maneira era referenciarmos o WebResource da seguinte maneira:

<SCRIPT type=text/javascript src="http://<server>/<organization>/webresources/ret_jquery"></SCRIPT>

Colocar todo o caminho vai funcionar e muitas das vezes é o URL que eu coloco no browser para testar. Mas isto é muito mau, basta dizer que você não vai conseguir passar esse código para outro ambiente de desenvolvimento, sem ir alterar o código, o que é mau, por isso devemos sempre usar o URL relativo. Já para não falar se tivermos os dois tipos de deploy (online e on-premise) que o URL muda completamente.

Uma pergunta válida é o porquê de querermos estruturar os WebResources na forma de pastas. Não é uma obrigação mas sim uma boa prática, principalmente se um utilizador pertencer a mais que uma organização num servidor. Isto porque quando colocamos /WebResources/<nome web resource> ele vai aceder a organização por defeito do utilizador. Isto poderá gerar um erro do tipo “File Not Found” caso ele esteja aceder a uma organização que não a de por defeito e que esse WebResource não exista na organização por defeito. Então como boa prática deveria-se ter a a seguinte estrutura:

“_<prefixo da organização>”/<nome da pasta>/<nome do Recurso Web>

Já vimos que conseguimos aceder ao formulário então e como conseguimos aceder a coisas do CRM fora do formulário, por exemplo saber o nome da organização, para isso usamos a seguinte função:

Xrm.Page.context.getOrgUniqueName()

Se executarmos este código obtemos o seguinte erro:

 

Mas em cima colocamos o prefixo window.parent mesmo pondo este prefixo não funciona porque ele serve para aceder ao formulário. Para que isto funcione necessitamos de referenciar uma outra biblioteca (não esquecer que estou numa estrutura flat de WebResources, se este WebResource tivesse dentro de uma pasta teria que reposicionar):

 

<SCRIPT src="ClientGlobalContext.js.aspx"></SCRIPT>

 

Esta biblioteca permite acedermos a outros parâmetros, vejam aqui a lista:

  •     getAuthenticationHeader

Cabeçalho de autenticação SOAP para os WebServices do Dynamics CRM 4.0.

  •     getOrgLcid

Retorna o valor LCID da linguagem de base da organização.

  •     getOrgUniqueName

Retorna o nome da organização.

  •    getQueryStringParameters

Retorna um array de chave valor representando os argumentos em query string passados a página.

  •   getServerUrl

Retorna o URL base do servidor. Quando se está no modo offline ele retorna localhost.

  •   getUserId

Retorna o Guid do utilizador actual.

  •    getUserLcid

Retorna o valor LCID da linguagem seleccionada pelo utilizador.

  •   getUserRoles

Retorna um array de Guid que representam as roles associadas ao utilizador.

 Existe outra forma de referenciar WebResources através da directiva “$webresource:<Nome do WebResource>”, devemos usar sempre este tipo de referenciação, pois ele resolve as dependências de solução. Mas apenas podemos usar quando estamos a usar o SiteMap ou Ribbon. A questão das dependências é muito importante porque ele vai conseguir gerar o URL e com isso vai possibilitar haver cache do WebResource, vejam o URL para referenciar o WebResource:

/<organização>/%7B635318792490000000%7D/WebResources/ret_testewr

Se colocarmos um URL absoluto para além dos problemas anteriores ainda vamos perder a capacidade de fazer cache. Existe um artigo muito bom e que explica também como podemos gerar este URL.

Em relação a como aplicamos a directiva na prática vamos ver mais detalhes no próximo post.

 

Até a próxima

 

Fontes:

http://msdn.microsoft.com/en-us/library/gg328541.aspx

Tags: , , ,

Tudo sobre WebResources I

by Pedro Azevedo 11. June 2013 00:43

Boas pessoal,

Vou criar uma série de posts sobre o conceito de Recurso Web (WebResource) que apareceu com o CRM 2011. Esta nova funcionalidade permite adicionar e referenciar componentes externos ao CRM, os WebResources ficam gravados na BD do CRM.

Os WebResources permite aumentar a usabilidade do Dynamics CRM. Cada WebResource tem um tipo que pode ser uma imagem, ficheiros javascript, html ou até silverlight. A seguir uma lista dos vários tipos:

Tipo de Ficheiro

Extensões

Descrição

Webpage (HTML)

.htm, .html

Páginas Web que apenas pode conter código do lado do cliente

Style Sheet (CSS)

.css

Mudar a aparência do CRM

StyleSheet (XSL)

.xsl, .xslt

Script (JScript)

.js

Utilizado em eventos do formulário e campos mas também numa WebPage ou comandos da Ribbon

Data (XML)

.xml

Podermos referenciar ficheiros XML

Image (PNG)

.png

Pode ser usado na ribbon, sitemap ou para ter imagens na própria entidade.

Image (JPG)

.jpg

Image (GIF)

.gif

Image (ICO)

.ico

Silverlight (XAP)

.xap

Possibilita enriquecer os formulários através do Silverlight

 

Como o WebResource é um dos componentes de uma solução permite facilmente passa-los de um ambiente para o outro. Para que isto aconteça com eficiência teremos que saber como referenciá-los, mas este assunto vamos retomar mais adiante.

Uma pergunta que tive e que faz todo o sentido: “Vamos deixar de usar o iFrame?”, pois ainda não, apesar de diminuir muito a sua utilização, ainda não podemos dizer que vamos deixar totalmente a sua utilização. Penso que a sua utilização vai limitar-se para podermos mostrar páginas aspx. Vejam aqui um bom artigo sobre este tema.

Para criarmos um WebResource temos que escolher uma solução. Depois disso escolhemos um nome, o tipo de documento. Se o tipo de documento for de edição de texto podemos editar directamente ou carregar um documento externo. O output depois de gravarmos é o URL para esse WebResource, se colocarmos esse URL no browser podemos ver o conteúdo. Este URL pode ser utilizado para o referenciar por exemplo em outro WebResource.

Eu ou editar directamente o WebResource por isso vou escolher a opção “Editor de texto” e colocar o seguinte código HTML:

 

Para finalizar basta gravarmos e publicarmos.

Para visualizarmos o resultado teremos que gravar e publicar o WebResource e depois adiciona-lo a um formulário:

 

Reparem que eu tenho uma secção seleccionada então ele vai colocar no final dessa secção. Podemos adicionar uma nova secção e colocar lá o nosso WebResource. Para finalizar gravamos e publicamos e vamos ver o seguinte resultado:

 

Para finalizar relatar uma limitação relativamente ao tamanho do ficheiro do WebResource que é definido com o tamanho máximo de upload de ficheiros nos emails. Esta configuração está em Definições->Sistema->Administração->Definições de Sistema->Correio Electrónico no campo “Definir limite de tamanho do ficheiro para anexos”.

Neste primeiro post falamos de um modo genérico sobre WebResources, nos próximos vamos aprofundar um pouco mais.

 

Até a próxima

Tags: , , ,

Criar uma conta CRM Online

by Pedro Azevedo 23. May 2013 22:35

Boas pessoal,

Hoje vou fazer um guia de como criar uma conta online. Isto também no âmbito do workshop que vou realizar na comunidade Portugal a Programar.

A primeira coisa a fazer é aceder ao seguinte URL: http://crm.dynamics.com/pt-pt/on-demand nesta página como podemos visualizar na imagem a seguir tem várias informações e um botão (Guia de Introdução) que permite testar o CRM Online gratuitamente durante 30 dias:

A seguir carregue em “Experimentar Agora!”:

 

Para aceder ao CRM temos que criar uma conta Office 365:

Aqui é um registo simples mas aqui queria ressaltar o facto de esta versão gratuita de 30 dias inclui 25 licenças e um armazenamento até 5 GB. Muito bom.

 

Mais algumas informações pessoais e depois um campo importante que vai definir o nome de utilizador pelo qual nos autenticamos e a respectiva password. Depois deste preenchimento é carregar no botão “Criar a minha conta”.

Depois a Microsoft prepara a nossa organização, por isso temos que esperar um pouco:

Quando o processo é terminado recebemos um email com as informações de como autenticar na organização. Se acedermos ao portal do Office 365 já podemos ver o botão para aceder ao CRM.

Aqui também podemos ver quantos dias temos até ao final da subscrição:

Ao acedermos pela primeira vez a instância do CRM temos informações sobre a nossa organização e depois um ecrã para configurar a organização:

 

Depois disto tudo podemos finalmente entrar na nossa organização do CRM Online, já agora vejam o vídeo de introdução:

E temos o CRM ONLINE:

Até a próxima.

 

Tags: , , , , ,

About

Muito bem casado, Pai babado e um gosto muito grande pela tecnologia.

Tenho um lema "Sharing is Learning"

Mais aqui -> http://www.psazevedo.com

Month List