CRM 2013 - Formulários Criação Rápida (Quick Create Forms)

by Pedro Azevedo 26. December 2013 00:42

Boas pessoal,

Ora aí está uma outra nova funcionalidade que veio tornar ainda melhor este fantástico produto (olha que lindo deveria receber uma comissão da MSF). Esta nova funcionalidade permite criar um registo de uma entidade sem termos que sair de onde estamos.

Na barra de navegação do lado direito está um sinal de somar com a label “Criar” (este botão está presente em todas as áreas), ao seleccionar temos a possibilidade de criar para várias entidades, por defeito está disponível para as entidades: concorrente, conta, contacto, incidente, oportunidade e oportunidade potencial. Mas não estamos limitados a estas entidades, qualquer entidade pode ser passível de ter um formulário de criação rápida.

Apesar das actividades aparecerem neste menu quando seleccionamos e ao contrário do que acontece com as outras actividades ele abre um formulário completo, ou seja, saímos do registo onde estávamos.

Quando escolhemos uma destas entidades aparece um menu flyout apenas com alguns campos para preencher, bem como os campos obrigatórios, vejam a seguir um exemplo:

Como podemos ver na imagem anterior o formulário rápido aparece por cima de onde estávamos e quando acabarmos a criação podemos continuar a fazer o que estávamos a fazer. Como podemos visualizar as regras de obrigatoriedade são aplicadas, bem toda a lógica efectuada em javascript e com as regras de negócio.

Depois de gravarmos ele dá um feedback que foi criado com êxito e dá-nos a possibilidade de ver o registo criado e podermos actualizar os restantes dados ou criar novamente outro registo.

O formulário rápido é possível customizar, vamos detalhar em outro post.

Outra maneira de lançar a criação rápida é nas sub-grids carregar no botão com o sinal ‘+’. Atenção que existem sub-grids que apenas permitem adicionar existentes.

Noutro post vamos ver como podemos gerir esta funcionalidade.

 

Até a próxima.

Tags: , ,

CRM 2013 - UR1

by Pedro Azevedo 18. December 2013 23:48

 

Boas pessoal,

Está disponível o primeiro rollup para o CRM 2013. Este pode ser descarregado aqui e podemos ver detalhes sobre o mesmo aqui. De referir que o UR1 já foi aplicado no CRM Online, não sei se em todas as instâncias, para saberem se já foi aplicado podem ver a versão do CRM 2013, o UR1 tem a versão 6.0.1.0061 (a versão sem rollups era 6.0.0.0809).

Tenho a realçar a implementação das alterações realizadas no UR15 para o CRM 2011 no que diz respeito ao cliente para o Outlook. Foram realizadas melhorias ao nível do consumo de memória. Além destas novidades foram também corrigidos diversos erros.

Apenas um parêntesis o esquema de cores também foi modificado desaparecendo o fundo negro da barra de navegação. Pode parecer um detalhe mas faz muita diferença.

 

Até a próxima.

Tags: , , ,

CRM 2011 - XrmServiceToolkit - Exemplo RetrieveAttributeMetadata

by Pedro Azevedo 17. December 2013 15:44

Boas pessoal,

Aproveitando o último post onde utilizei uma chamada SOAP “inteira”, ou seja, tive que colocar todo o request e comparar como poderíamos ter feito a mesma coisa com o uso de a biblioteca XrmServiceToolkit que já apresentei antes aqui no blog.

Para além de menos código, esta biblioteca já resolve um dos problemas que encontraram com o último post, não funciona com o IE10 (nem em browsers como Firefox e Chrome já que não é standard da W3C), isto porque o IE10 já não suporta XPath e por consequência não consegue executar o seguinte código:

selectSingleNode("c:OptionSet//c:Options");

Para resolver este problema usei JQuery para resolver este problema, mas se tivéssemos a usar a biblioteca XrmServiceToolkit este problema já estava resolvido, já que esta biblioteca está sempre a ser atualizada.

Substituindo o código que usava o método anterior por jQuery fica assim:

 

function getOptionSet (entityLogicalName, attributeLogicalName, retrieveAsIfPublished) {				
	var context = GetGlobalContext();
	var serverUrl = context.getServerUrl();
	var SoapPath = serverUrl + "/XRMServices/2011/Organization.svc/web";
	var MetadataId = "00000000-0000-0000-0000-000000000000";
	
	var request = " <soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Body>"
	request += "<Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
	request += "<request i:type=\"a:RetrieveAttributeRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
	request += "<a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
	request += "<a:KeyValuePairOfstringanyType>";
	request += "<b:key>EntityLogicalName</b:key>";
	request += "<b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + entityLogicalName + "</b:value>";
	request += "</a:KeyValuePairOfstringanyType>";
	request += "<a:KeyValuePairOfstringanyType>";
	request += "<b:key>MetadataId</b:key>";
	request += "<b:value i:type=\"ser:guid\"  xmlns:ser=\"http://schemas.microsoft.com/2003/10/Serialization/\">" + MetadataId + "</b:value>";
	request += "</a:KeyValuePairOfstringanyType>";
	request += "<a:KeyValuePairOfstringanyType>";
	request += "<b:key>RetrieveAsIfPublished</b:key>";
	request += "<b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + retrieveAsIfPublished + "</b:value>";
	request += "</a:KeyValuePairOfstringanyType>";
	request += "<a:KeyValuePairOfstringanyType>";
	request += "<b:key>LogicalName</b:key>";
	request += "<b:value i:type=\"c:string\"   xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + attributeLogicalName + "</b:value>";
	request += "</a:KeyValuePairOfstringanyType>";
	request += "</a:Parameters>";
	request += "<a:RequestId i:nil=\"true\" /><a:RequestName>RetrieveAttribute</a:RequestName></request>";
	request += "</Execute>";
	request += "</soapenv:Body></soapenv:Envelope>";
	
	var req = new XMLHttpRequest();
	req.open("POST", SoapPath, false);
	req.setRequestHeader("Accept", "application/xml, text/xml, */*");
	req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
	req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
	req.send(request);

	if (req.responseXML != null) {
		return req.responseXML;
	}
}

 

Ficando a chamada e o parsing do resultado assim:

var optionXML = getOptionSet(entityName, fieldName, true);
var a =  $(optionXML.xml).find('OptionMetadata');
a.each(function(){
		  var text = $(this).find('Label').find('UserLocalizedLabel').find('Label').text();
		  $(myList).append('<option>' + text + '</option>');
});

E agora vejam como fica tirando partido da biblioteca XrmServiceToolkit:

var OptionSetControl = XrmServiceToolkit.Soap.RetrieveAttributeMetadata(entityname, fieldname, true);
for(var i = 0; i < OptionSetControl[0].OptionSet.Options.length; ++i)
{
	$(myList).append('<option>' + OptionSetControl[0].OptionSet.Options[i].Label.UserLocalizedLabel.Label + '</option>')
}

Uma diferença ENORME e sim funciona :P.

Mais uma vez fica a solução com os dois Recursos Web, um com a chamada SOAP e outra com o recurso a XrmServiceToolkit. Bem como todas as dependências.

 

Até a próxima.

ListadeEstados_1_0_0_1.zip (66,54 kb)

Tags: ,

CRM 2011 - Listar todas as opções num WebResource (Recurso Web)

by Pedro Azevedo 12. December 2013 01:39

Boas pessoal,

Foi colocada uma questão nos fóruns da Microsoft. Basicamente a questão era como obter todos os estados de uma entidade e listar em um Recurso Web. Como o código e os passos eram bastantes decidi colocar aqui no blog e ajudar futuramente outros programadores.

No final deste desenvolvimento como resultado teremos um Recurso Web a listar num OptionSet todas as opções de um OptionSet criado no CRM. Para isso teremos que aceder aos Metadados do CRM. Neste caso vou usar directamente uma mensagem SOAP para obter estes dados, usando a mensagem RetrieveAttributeRequest. Mas chamando através do Javasript.

O primeiro passo foi criar o Recurso Web no tipo HTML, neste Recurso Web coloquei o seguinte código:

<HTML xmlns:b xmlns:a xmlns:soapenv>
	<HEAD>
         </HEAD>
	<BODY>
		<SELECT id=myList/>
	</BODY>
</HTML>

Até agora nada de especial, vamos colocar algum código Javascript, como vamos estar em um Recurso Web vamos ter que obter informação do contexto para isso teremos que referenciar este aspx ClientGlobalContext.js.aspx (já está no CRM não é necessário referenciar por exemplo noutro Recurso Web).

Com esta referência poderemos então obter o contexto desta maneira:

var context = GetGlobalContext();
var serverUrl = context.getServerUrl();

NOTA: O método getServerUrl encontra-se deprecated com a vinda do UR12, para rollups superiores deve-se usar o método getClientUrl.

Agora "basta" construirmos o pedido SOAP para obter a informação que pretendemos:

var SoapPath = serverUrl + "/XRMServices/2011/Organization.svc/web";
var MetadataId = "00000000-0000-0000-0000-000000000000";
				
var request = " <soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Body>"
request += "<Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
request += "<request i:type=\"a:RetrieveAttributeRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
request += "<a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
request += "<a:KeyValuePairOfstringanyType>";
request += "<b:key>EntityLogicalName</b:key>";
request += "<b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + entityLogicalName + "</b:value>";
request += "</a:KeyValuePairOfstringanyType>";
request += "<a:KeyValuePairOfstringanyType>";
request += "<b:key>MetadataId</b:key>";
request += "<b:value i:type=\"ser:guid\"  xmlns:ser=\"http://schemas.microsoft.com/2003/10/Serialization/\">" + MetadataId + "</b:value>";
request += "</a:KeyValuePairOfstringanyType>";
request += "<a:KeyValuePairOfstringanyType>";
request += "<b:key>RetrieveAsIfPublished</b:key>";
request += "<b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + retrieveAsIfPublished + "</b:value>";
request += "</a:KeyValuePairOfstringanyType>";
request += "<a:KeyValuePairOfstringanyType>";
request += "<b:key>LogicalName</b:key>";
request += "<b:value i:type=\"c:string\"   xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + attributeLogicalName + "</b:value>";
request += "</a:KeyValuePairOfstringanyType>";
request += "</a:Parameters>";
request += "<a:RequestId i:nil=\"true\" /><a:RequestName>RetrieveAttribute</a:RequestName></request>";
request += "</Execute>";
request += "</soapenv:Body></soapenv:Envelope>";
				
var req = new XMLHttpRequest();
req.open("POST", SoapPath, false);
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
req.send(request);

Com este pedido podemos aceder a todas as opções do OptionSet escolhido. A seguir vou colocar todo o código, inclusivé o que permite fazer parsing dos resultados e que coloca noutra OptionSet.

<HTML xmlns:b xmlns:a xmlns:soapenv><HEAD>
<SCRIPT src="ClientGlobalContext.js.aspx"></SCRIPT>

<SCRIPT type=text/javascript>
			function getOptionSet (entityLogicalName, attributeLogicalName, retrieveAsIfPublished) {				
				var context = GetGlobalContext();
                var serverUrl = context.getServerUrl();
	            var SoapPath = serverUrl + "/XRMServices/2011/Organization.svc/web";
				var MetadataId = "00000000-0000-0000-0000-000000000000";
				
                var request = " <soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Body>"
				request += "<Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
				request += "<request i:type=\"a:RetrieveAttributeRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
				request += "<a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
				request += "<a:KeyValuePairOfstringanyType>";
				request += "<b:key>EntityLogicalName</b:key>";
				request += "<b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + entityLogicalName + "</b:value>";
				request += "</a:KeyValuePairOfstringanyType>";
				request += "<a:KeyValuePairOfstringanyType>";
				request += "<b:key>MetadataId</b:key>";
				request += "<b:value i:type=\"ser:guid\"  xmlns:ser=\"http://schemas.microsoft.com/2003/10/Serialization/\">" + MetadataId + "</b:value>";
				request += "</a:KeyValuePairOfstringanyType>";
				request += "<a:KeyValuePairOfstringanyType>";
				request += "<b:key>RetrieveAsIfPublished</b:key>";
				request += "<b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + retrieveAsIfPublished + "</b:value>";
				request += "</a:KeyValuePairOfstringanyType>";
				request += "<a:KeyValuePairOfstringanyType>";
				request += "<b:key>LogicalName</b:key>";
				request += "<b:value i:type=\"c:string\"   xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + attributeLogicalName + "</b:value>";
				request += "</a:KeyValuePairOfstringanyType>";
				request += "</a:Parameters>";
				request += "<a:RequestId i:nil=\"true\" /><a:RequestName>RetrieveAttribute</a:RequestName></request>";
				request += "</Execute>";
				request += "</soapenv:Body></soapenv:Envelope>";
				
				var req = new XMLHttpRequest();
				req.open("POST", SoapPath, false);
				req.setRequestHeader("Accept", "application/xml, text/xml, */*");
				req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
				req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
				req.send(request);

				if (req.responseXML != null) {
					var attributeData = req.responseXML.selectSingleNode("//b:value");
					if (attributeData != null) {
						var attributeType = attributeData.selectSingleNode("c:AttributeType").text;
						switch (attributeType) {
							case "Picklist":
								return attributeData;
								break;
							default:
								break;
						}
					}
				}
			}
		</SCRIPT>

<META charset=utf-8></HEAD>
<BODY contentEditable=true><SELECT id=myList></SELECT>
<SCRIPT>
	var optionSet = getOptionSet("ret_accao", "ret_estadocadastro", true);
	var options = optionSet.selectSingleNode("c:OptionSet//c:Options");
    var myPickList = document.getElementById("myList");
	for (var i = 0; i < options.childNodes.length; i++) {
		var textPick = options.childNodes[i].selectSingleNode("c:Label").selectSingleNode("a:UserLocalizedLabel").selectSingleNode("a:Label").text;
        var option = document.createElement("option");
        option.text = textPick;
        myPickList.add(option, myPickList.options[null]);
	}
</SCRIPT>
</BODY></HTML>

Se não quiserem andarem a fazer copy paste do código tenho aqui a solution que contém este código. É fazer download e importá-lo na vossa organização e lançar num botão por exemplo.

NOTA: Atenção ao cache dos web resources, façam iisreset e caso não resulte forcem o reload (CTRL+F5) na própria páguina que contiver este web resource

ListadeEstados_1_0_0_0.zip (3,29 kb)

Tags: , , , ,

Ferramenta - Ribbon Workbench

by Pedro Azevedo 6. December 2013 08:05

 Boas pessoal,

Inicio agora formalmente uma nova série de posts, que tem como objetivo mostrar as várias ferramentas\utilitários\bibliotecas disponíveis para o CRM e que tem como objetivo auxiliar-nos no dia-a-dia. A primeira “vítima” foi a biblioteca XrmServiceToolkit.

Hoje vou apresentar uma ferramenta muito útil e que não se pode viver sem ela. Estou a falar da ferramenta Ribbon Workbench. Como o próprio nome denúncia serve para customizar a Ribbon. Existem outras alternativas, tais como, Ribbon Editor, Pragma Toolkit e Visual Ribbon Editor mas a que mais utilizo é realmente a Ribbon Workbench. Esta já suporta CRM 2013 as outras ferramentas não tenho a certeza.

Para instalar basta ir a página http://www.develop1.net/public/page/Ribbon-Workbench-for-Dynamics-CRM-2011.aspx aqui temos várias informações e podemos escolher sobre qual versão do CRM queremos trabalhar.

Em ambos os casos vai fazer download da solução que devemos instalar na nossa organização. Depois de instalarmos a solução devemos ter a seguinte visualização:

Para aceder é selecionar o botão “Personalizado” no CRM 2011 tem o seguinte aspecto:

Depois de entrarmos no Ribbon Workbench temos que escolher a solução quer queremos customizar, por isso, já temos que ter criado uma solução e que esta inclua a entidade sobre a qual queremos customizar a ribbon, neste caso concreto adicionei a entidade Proposta (quote).

 

Depois de carregar a solução temos o seguinte aspecto:

Vamos então analisar cada uma destas secções individualmente:

 

Aqui vemos quais os botões que são possíveis de ver nas várias visualizações:

·         Home – é o menu que é mostrado nos ecrãs principais.

·         Sub-Grid – menu que é mostrado quando selecionamos uma subgrid, ou seja, no CRM 2011 sempre que selecionavamos uma subgrid a ribbon mudava para o contexto da entidade da subgird. No CRM 2013 não existe esta funcionalidade. Quer dizer existir existe por exemplo quando estamos num cliente e se virmos a lista de contactos:

 

Quando carregamos na lista aparece a lista em baixo:

 

Onde aqui aparece este menu.

·         Form – menu que aparece quando abrimos um registo de uma entidade.

De referir que temos a opção de ver a ribbon que aparece no cliente para o Outlook e que por ter a mesma estrutura que a barra de comandos e como vamos ver em futuros posts nós conseguimos recorrendo a ribbon acrescentar botões que não existem na barra de comandos.

Na próxima secção mostra os vários controlos que poderemos inserir na barra de comandos:

 

O tab permite agrupar botões, a tab scale define como os botões mudam quando existem retrições de tamanho. O grupo permite dar contexto a um conjunto de botões dentro de um determinado tab. E depois os vários tipos de botões, ou seja, Button, Split Button e Flyout. O Menu Section é o chamado Jewel Menu, que basicamente é o menu File que aparece no CRM 2011.

No CRM 2013 temos mais algumas definições. Na imagem estamos a ver a barra de comandos que pode mostrar até 5 comandos, os três pontos permite expandir as opções e é designado por overflow. Dentro da barra de comandos podemos ver os botões “normais”, os botões flyout podem estar dentro da barra de comandos e dentro do overflow:

 

Na secção final que vamos analisar temos as acções que poderemos realizar sobre os botões:

 

Na lista de entidades vemos as entidades que estavam na solução que escolhemos quando lançamos a ferramenta. Na lista ao lado temos os elementos da solução, incluindo os comandos que são executados, bem como as regras de mostrar ou não os botões. Este assunto dava para um livro por isso eu demonstrando nos vários posts que pretendo criar.

A última lista estão as propriedades dos elementos gráficos ou dos comandos ou regras.

A última acção e a mais importante é publicarmos as mudanças que realizamos, para isso basta carregar no botão "Publish".

Espero que tenham ficado com uma ideia desta magnifica ferramenta, um bem haja ao Scott Durow. Em futuros posts eu vou demonstrar como podemos acrescentar, esconder botões.

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