Previous posts have dealt successfully with how to consume a web service and how to use the SmartOffice DynamicWs classes. This post will help if you need something which is dynamic, yet decoupled from SmartOffice.
This is a sample based on the WCF Dynamic Proxy classes available under a Microsoft Public License in the msdn archive.
For initial reference we have a standard C# invocation using a generated service reference. The web service we are using is API_MNS150MI_GetUserData.
The only tricky part here is ensuring the http authentication is set so that Web services accepts you as a valid user.
Here is the code for the static call against the generated service reference.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.IO; using WebServiceStatic.API131; using System.ServiceModel; namespace WebServiceStatic { class Program { static void Main(string[] args) { // Create a client with basic http credentials API_MNS150MI_GetUserDataClient client = new API_MNS150MI_GetUserDataClient(); System.ServiceModel.BasicHttpBinding binding = new System.ServiceModel.BasicHttpBinding(); binding.Security.Mode = BasicHttpSecurityMode.Transport; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic; binding.MaxReceivedMessageSize = 25 * 1024 * 1024; client.Endpoint.Binding = binding; // show endpoint address Console.WriteLine(client.Endpoint.Address); Console.WriteLine(client.Endpoint.Name); // ask for UserID and password Console.Write("User ID : "); client.ClientCredentials.UserName.UserName = Console.ReadLine().Trim(); Console.Write("Password: "); client.ClientCredentials.UserName.Password = Console.ReadLine().Trim(); // Create LWS header lws header = new lws(); header.user = client.ClientCredentials.UserName.UserName; header.password = client.ClientCredentials.UserName.Password; // Create a requests item GetUserDataItem item1 = new GetUserDataItem(); item1.USID = client.ClientCredentials.UserName.UserName; // construct a collection for the request item (only 1 accepted?) GetUserDataCollection collection = new GetUserDataCollection(); collection.GetUserDataItem = new GetUserDataItem[] { item1 }; try { // execute the web service GetUserDataResponseItem[] response = client.GetUserData(header, collection); // loop through the response items (only 1) and output to console foreach (GetUserDataResponseItem responseItem in response) { Console.WriteLine("User '{0}' description '{1}'", responseItem.USID, responseItem.TX40); } } catch (Exception e) { // catch and display any errors Console.WriteLine(e.Message); } // wait for user to press a key Console.WriteLine("Press any key to continue..."); Console.ReadKey(); } } }
The result shows we have connected to the web service and retrieved the Users ID (USID) and description (TX40).
Now we have the basic hard-coded example code as a template, we can use the DynamicProxyLibrary to do the same.
This dynamically creates an Assembly (dll) containing the service reference which we can use in place of a hard-coded Service reference.
This can be done without the DynamicProxyLibrary however as the DynamicProxy handles most of the Assembly/Reflection plumbing it is much easier to read and work with.
First create a project referencing the DynamicProxyLibrary in Visual Studio.
Now it is possible to use the Dynamic proxy to call the web service without using a hard-coded service references, all field/property/class references can be coded as text.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace WebServiceDynamic { using WcfSamples.DynamicProxy; using System.ServiceModel.Description; using System.ServiceModel; using System.Reflection; class Program { static void Main(string[] args) { string serviceWsdlUri = "https://m3app-2013.gdeinfor2.com:41964/mws-ws/services/API_MNS150MI_GetUserData?wsdl"; if (args.Length > 0) serviceWsdlUri = args[0]; // create the dynamic proxy factory, that downloads the service metadata // and create the dynamic factory. Console.WriteLine("Creating DynamicProxyFactory for " + serviceWsdlUri); DynamicProxyFactory factory = new DynamicProxyFactory(serviceWsdlUri); // list the endpoints. int count = 0; foreach (ServiceEndpoint endpoint in factory.Endpoints) { // create proxy client Console.WriteLine("Service Endpoint[{0}]", count); Console.WriteLine("\tAddress = " + endpoint.Address); Console.WriteLine("\tContract = " + endpoint.Contract.Name); Console.WriteLine("\tBinding = " + endpoint.Binding.Name); DynamicProxy clientProxy = factory.CreateProxy(endpoint.Contract.Name); // Create a client with basic http credentials System.ServiceModel.BasicHttpBinding binding = new System.ServiceModel.BasicHttpBinding(); binding.Security.Mode = BasicHttpSecurityMode.Transport; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic; binding.MaxReceivedMessageSize = 25 * 1024 * 1024; ServiceEndpoint clientEndpoint = (ServiceEndpoint)clientProxy.GetProperty("Endpoint"); clientEndpoint.Binding = binding; // ask for UserID and password ClientCredentials credentials = (ClientCredentials)clientProxy.GetProperty("ClientCredentials"); Console.Write("User ID : "); credentials.UserName.UserName = Console.ReadLine().Trim(); Console.Write("Password: "); credentials.UserName.Password = Console.ReadLine().Trim(); // Create LWS header Type lwsType = clientProxy.ProxyType.Assembly.GetType("lws"); DynamicObject header = new DynamicObject(lwsType); header.CallConstructor(); header.SetProperty("user", credentials.UserName.UserName); header.SetProperty("password", credentials.UserName.Password); // Create a requests item Type itemType = clientProxy.ProxyType.Assembly.GetType("GetUserDataItem"); DynamicObject item = new DynamicObject(itemType); item.CallConstructor(); item.SetProperty("USID", credentials.UserName.UserName); // Add the user request item to an array of 1 Array itemArray = Array.CreateInstance(item.ObjectType, 1); itemArray.SetValue(item.ObjectInstance, 0); // construct a collection for the request item (only 1 accepted?) Type collectionType = clientProxy.ProxyType.Assembly.GetType("GetUserDataCollection"); DynamicObject collection = new DynamicObject(collectionType); collection.CallConstructor(); collection.SetProperty("GetUserDataItem", itemArray); try { // execute the web service Array responseCollection = (Array)clientProxy.CallMethod("GetUserData", new object[] { header.ObjectInstance, collection.ObjectInstance }); // loop through the response items (only 1) and output to console foreach (object responseItemObject in responseCollection) { DynamicObject responseItem = new DynamicObject(responseItemObject); Console.WriteLine("User '{0}' description '{1}'", responseItem.GetProperty("USID"), responseItem.GetProperty("TX40")); } } catch (Exception e) { // catch and display exceptions Console.WriteLine(e.Message); // catch and display inner exception (this is the real error from the web service call) if (e.InnerException != null) { Console.WriteLine(e.InnerException.Message); } } // close the connection clientProxy.Close(); } Console.WriteLine("Press any key..."); Console.ReadKey(); } } }
The result shows that we can use the DynamicProxyFactory to get some basic information about the web service, then consume the web service.
Regards,
Lee Flaherty
UPDATE: This was tested against M3 10.1 and M3 13.1 both running on the grid. It may, or may not, work on other versions.
Hi Lee,
Do you have a sample client in Java that demonstrates on how to consume M3 LWS services?
Thank you.
LikeLike
Hi Deepak, the Lawson Web Services Designer will generate sample code for you. For that, right-click your web service in the repository, and select Generate sample client code. You can also use any other Java SOAP stub generator on the market. It’s all standard SOAP. /Thibaud
LikeLike
Hi, Deepak, Thibaud is correct, the easiest way to generate a simple stub client is in Web services Designer (a.k.a. Web Services Studio). If you have a test setup in your web service it can use the data from this as a sample. To get this tested and working as a slim client you can build a project in your IDE which includes some jar files from the Apache Axis project, or you can use MEC (M3 E-Collaborator) as a container for your Java program. /Lee
LikeLike