简体   繁体   中英

Download Microsoft Dynamics AX 2012 service wsdl metadata after validating credentials like AX server domain, user name and password in my wcf service

I am completely new to this Microsoft Dynamics AX 2012 tool and WCF service. I have a self hosted WCF service, where it takes AX 2012 service wsdl URL, AX server domain name, user name and password as inputs and will try to download metadata of this wsdl url without any user authentication mechanism in place.

MY AX 2012 service WSDl URL below: http://####:8##1/DynamicsAx/Services/TestService?wsdl ---> WSDLEndpoint

I am dynamically creating WSHttpBinding, MetadataExchangeClient and assigned all it's properties and passed my wsdl endpoint.

Below is my sample code :

var binding = new WSHttpBinding(SecurityMode.None) { MaxReceivedMessageSize = int.MaxValue, MaxBufferPoolSize = int.MaxValue };
var mexClient = new MetadataExchangeClient(binding)
{
    ResolveMetadataReferences = true,
    MaximumResolvedReferences = int.MaxValue,
    OperationTimeout = TimeSpan.FromSeconds(TimeOutInSeconds),
    HttpCredentials =
                            new NetworkCredential(Username, Password, Domain)
};
mexClient.GetMetadata(new Uri(WSDLEndpoint), MetadataExchangeClientMode.HttpGet);
Log.Info("Metadata successfully downloaded.");      

But above code won't bother about user credentials validation, it directly downloads metadata out of the WSDL URL, but I am looking to validate user credentials and after successful authentication, will download metadata.

Please help me with some authentication approach to introduce on top of wshttpbinding that supports cross platforms.

I don't fully understand your meaning. Are you trying to create a WCF service with custom username/password authentication? This requires that we configure a certificate on the server-side. I created an example, wishing it is instrumental for you.
Server-side.

class Program
    {
        static void Main(string[] args)
        {
            Uri uri = new Uri("http://localhost:21011");
            WSHttpBinding binding = new WSHttpBinding();
            binding.Security.Mode = SecurityMode.Message;
            binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

            using (ServiceHost sh = new ServiceHost(typeof(MyService), uri))
            {
                sh.AddServiceEndpoint(typeof(IService), binding, "");
                ServiceMetadataBehavior smb;
                smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
                if (smb == null)
                {
                    smb = new ServiceMetadataBehavior()
                    {
                        HttpGetEnabled = true

                    };
                    sh.Description.Behaviors.Add(smb);
                }
                sh.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "5ba5022f527e32ac02548fc5afc558de1d314cb6");

                Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
                sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");

                sh.Opened += delegate
                {
                    Console.WriteLine("Service is ready");
                };
                sh.Closed += delegate
                {
                    Console.WriteLine("Service is clsoed");
                };
                sh.Open();
                Console.ReadLine();
                //pause
                sh.Close();
                Console.ReadLine();
            }
        }
    }
    [ServiceContract]

    public interface IService
    {
        [OperationContract]
        string Test();

    }
    public class MyService : IService
    {
        public string Test()
        {

            return DateTime.Now.ToString();
        }

}

On the Client-side, we create a client proxy by adding service reference.

ServiceReference1.ServiceClient client = new ServiceClient();
            client.ClientCredentials.UserName.UserName = "administrator";
            client.ClientCredentials.UserName.Password = "abcd1234!";
            var result = client.Test();
            Console.WriteLine(result);

The configuration automatically generated on the client-side.

  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_IService">
          <security>
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://10.157.13.69:21011/" binding="wsHttpBinding"
        bindingConfiguration="WSHttpBinding_IService" contract="ServiceReference1.IService"
        name="WSHttpBinding_IService">
        <identity>
          <certificate encodedValue="blabla… " />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>

In the above example, the client should provide username/password to be authenticated by the server so that call the remote service.
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/message-security-with-a-user-name-client
Feel free to let me know if there is anything I can help with.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM