Olá pessoal,
No post anterior, escrevi como realizar a comunicação com o serviço WCF externo do Dynamics 365 no server side (utilizei um plugin).
Neste post, irei fazer a mesma chamada, porém utilizando o que acredito que seja o mais recomendado e eficiente. Usar Biding HTML e o Contrato do serviço.
É imprescindível que o serviço WCF do post anterior esteja implementado. Pois, ele será a base para este. Na verdade, a única coisa que este post apresenta de diferente é o meio/forma de comunicação com o serviço!
Primeiramente, precisamos gerar o contrato do WCF, para isso, basta navegar no browser pelo endereço do serviço que veremos um tela similar a esta:
Veja que podemos criar nosso contrato utilizando o svcutil.exe (quando instalamos o Visual Studio ele é automaticamente instalado). O svcutil irá ler a interface do WCF e gerar nosso contrato.
Eu inseri alguns parâmetros para facilitar o uso do contrato:
svcutil.exe http://tiagowin20163976.cloudapp.net/WcfService/Mat.svc?wsdl ^ /namespace:*,"Dynamics365" ^ /d:"C:\Users\tiago.cardoso\Downloads"
Para executar o svcutil, precisamos abrir o Developer Command Prompt for VS (cada versão do VS tem programa) e colar o script acima:
No meu caso o arquivo Mat.cs será adicionado na pasta Downloads. Copie e adicione no MESMO PROJETO ONDE O PLUGIN IRÁ FICAR!
A última parte não poderia ser diferente de criar o plugin propriamente! Vou seguir a mesma ideia do post anterior e criar para a entidade Conta (account). Foi colocar o código e depois irei comentar:
using Dynamics365;
using Microsoft.Xrm.Sdk;
using System;
using System.ServiceModel;
namespace Plugins
{
public class AccountCreate : IPlugin
{
#region Secure/Unsecure Configuration Setup
private string _secureConfig = null;
private string _unsecureConfig = null;
public AccountCreate(string unsecureConfig, string secureConfig)
{
_secureConfig = secureConfig;
_unsecureConfig = unsecureConfig;
}
#endregion
public void Execute(IServiceProvider serviceProvider)
{
// Extract the tracing service for use in debugging sandboxed plug - ins.
// If you are not registering the plug-in in the sandbox, then you do
// not have to add any tracing service related code.
ITracingService tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));
// The InputParameters collection contains all the data passed in the message request.
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
// Obtain the target entity from the input parameters.
Entity entity = (Entity)context.InputParameters["Target"];
// Verify that the target entity represents an entity type you are expecting.
// For example, an account. If not, the plug-in was not registered correctly.
if (entity.LogicalName != "account")
return;
// Obtain the organization service reference which you will need for
// web service calls.
IOrganizationServiceFactory serviceFactory =
(IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
try
{
// Plug-in business logic goes here.
var serviceURL = "http://tiagowin20163976.cloudapp.net/WcfService/Mat.svc";
tracingService.Trace("- CallServiceByWebClientSOAP");
tracingService.Trace("Somar('4','5')");
// Create Bind object
BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.None;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
myBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
// Create endpoint
EndpointAddress endPointAddress = new EndpointAddress(serviceURL);
// Create Channel to access Encrypt Service Interface
ChannelFactory<IMat> factory = new ChannelFactory<IMat>(myBinding, endPointAddress);
IMat channel = factory.CreateChannel();
// Call Encrypt Service
var response = channel.Somar("4", "5");
tracingService.Trace("Result: " + response);
// Close factory
factory.Close();
}
catch (FaultException<OrganizationServiceFault> ex)
{
throw new InvalidPluginExecutionException("An error occurred in MyPlug-in.", ex);
}
catch (Exception ex)
{
tracingService.Trace("MyPlugin: {0}", ex.ToString());
throw;
}
}
}
}
}
Vamos lá:
- A primeira linha faz uma referência (namespace) ao contrato que criamos com o svcutil;
- O que acontence dentro do “try“:
- serviceUrl – Informamos a URL do serviço que estamos requisitando
- BasicHttpBinding – Criamos o binding que propriamente faz a conexão com o serviço WCF. Note que não estou utilizando nenhum método de autenticação ou proxy neste exemplo;
- endPointAddress – Criamos um objeto com o endpoint do serviço;
- factory – Informamos o contrato e endpoint para a classe ChannelFactory. Veja a conversão (unboxing) para o tipo do nosso contrato IMat;
- channel – Cria o canal com o endpoint, ou seja, cria/abre a conexão com o serviço;
- channel.Somar – Por fim, chamamos o método do serviço. Veja que por usarmos o contrato do serviço o método e parâmetros são reconhecidos! (tipados)
A resposta da chamada, nada mais é do que o que método retorna. Neste exemplo será um número! O número 9 (5+4)!
Assim, ao criar uma conta no CRM, quando observamos o log de execução do plugin, vemos:
Bom, é isso! Acredito que esta forma seja bem mais robusta e utilize melhores práticas de programação bem como funcionalidades mais atuais!
[]’s,
Tiago




