static async Task Main(string[] args) { Console.WriteLine("\nStarting up...\n"); // Load environment variables from .env DotNetEnv.Env.Load("../../.env"); // Change to true to enable output of request/response headers and XML var DEBUG = System.Environment.GetEnvironmentVariable("DEBUG"); // Create a custom binding so we can allow the client to use cookies with AXL BasicHttpsBinding binding = new BasicHttpsBinding(); binding.AllowCookies = true; // Specify the CUCM AXL API location for the SOAP client EndpointAddress address = new EndpointAddress($"https://{ System.Environment.GetEnvironmentVariable( "CUCM_ADDRESS" ) }:8443/axl/"); //Class generated from AXL WSDL AXLPortClient client = new AXLPortClient(binding, address); if (DEBUG == "True") { client.Endpoint.EndpointBehaviors.Add(new DebugEndpointBehaviour()); } // To disable HTTPS certificate checking, uncomment the below lines // NOT for production use! See README.md for AXL certificate install steps // client.ChannelFactory.Credentials.ServiceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication // { // CertificateValidationMode = X509CertificateValidationMode.None, // RevocationMode = X509RevocationMode.NoCheck // }; // client.ChannelFactory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None; // client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None; // Incantation to force alternate serializer reflection behaviour due to complexities in the AXL schema // See https://github.com/dotnet/wcf/issues/2219 MethodInfo method = typeof(XmlSerializer).GetMethod("set_Mode", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); method.Invoke(null, new object[] { 1 }); // Base64 encode AXL username/password for Basic Auth var encodedUserPass = Convert.ToBase64String(Encoding.ASCII.GetBytes( System.Environment.GetEnvironmentVariable("CUCM_USERNAME") + ":" + System.Environment.GetEnvironmentVariable("CUCM_PASSWORD") )); // Incantation to create and populate a Basic Auth HTTP header // This must be done to force SoapCore to include the Authorization header on the first attempt HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty(); requestProperty.Headers["Authorization"] = "Basic " + encodedUserPass; // Creating context block apparently allows attaching custom HTTP headers to the request var scope = new OperationContextScope(client.InnerChannel); OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestProperty; // Create the request object GetPhoneReq request = new GetPhoneReq(); // Specify we want to use the <name> choice to retrieve by device name (vs. uuid) request.ItemElementName = ItemChoiceType142.name; request.Item = System.Environment.GetEnvironmentVariable("GETPHONE_DEVICE"); string model = ""; //Try the getPhone request try { getPhoneResponse response = await client.getPhoneAsync(request); //Parse/print the phone's model name to the console model = [email protected]; } catch (Exception ex) { Console.WriteLine($"\nError: getPhone: { ex.Message }"); Environment.Exit(-1); } Console.WriteLine($"\ngetPhone: SUCCESS model: { model }\n"); }