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: , , , ,

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