Conectar a servicios externos mediante HTTPS desde Microsoft Dynamics AX 2012

Hace ya bastante tiempo publiqué el código necesario para consumir servicios web externos desde Microsoft Dynamics AX 2012 utilizando únicamente X++. Este código se puede encontrar fácilmente en muchos sitios ya que es básicamente el mismo para casi cualquier servicio WCF, pero a veces necesitamos ajustar algunas propiedades de la conexión, por ejemplo, para conectar a extremos HTTPS.

Según la documentación de MSDN (aquí), en C# el cambio sería muy sencillo, simplemente modificando un par de propiedades del binding durante la conexión:

BasicHttpBinding b = new BasicHttpBinding();
b.Security.Mode = BasicHttpSecurityMode.Transport ;
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

Sin embargo en X++, como suele pasar al utilizar tipos de .NET, la cosa no es tan simple, aunque no es demasiado complicado. Este es el código genérico que suelo usar:

protected CLRObject ServiceClient()
{
    CLRObject                                           serviceClient;
    System.String                                       serviceUrl;

    System.Type                                         clientType;
    System.ServiceModel.EndpointAddress                 endPointAddress;
    System.ServiceModel.Description.ServiceEndpoint     endPoint;
    System.Exception                                    ex;

    System.ServiceModel.BasicHttpBinding                binding;
    System.ServiceModel.BasicHttpSecurity               security;
    System.ServiceModel.HttpTransportSecurity           transport;
    boolean                                             isHttps;


    serviceUrl  = this.ServiceUrl();
    isHttps     = this.isHttps(serviceUrl);

    try
    {
        clientType = CLRInterop::getType(this.ServiceTypeName());
        serviceClient = AifUtil::createServiceClient(clientType);

        endPointAddress = new System.ServiceModel.EndpointAddress(serviceUrl);
        endPoint = serviceClient.get_Endpoint();
        endPoint.set_Address(endPointAddress);

        // Binding changes for HTTPS
        if (isHttps)
        {
            binding  = endPoint.get_Binding();

            security = binding.get_Security();
            security.set_Mode(System.ServiceModel.BasicHttpSecurityMode::Transport);

            transport = security.get_Transport();
            transport.set_ClientCredentialType(System.ServiceModel.HttpClientCredentialType::Windows);
            security.set_Transport(transport);

            binding.set_Security(security);

            endPoint.set_Binding(binding);
        }
    }
    catch(Exception::CLRError)
    {
        ex = CLRInterop::getLastException();
        throw error(ex.ToString());
    }

    return serviceClient;
}

La configuración específica dependerá del tipo de seguridad que utilice el servicio. Este código funciona en el caso de seguridad HTTPS con autenticación delegada en la seguridad de Windows, pero el código se puede modificar fácilmente para adaptarla a otros tipos de conexión.

Espero que sea útil 😉

Enlaces