12.10.2010, 15:05 | #1 |
Участник
|
Rahul Sharma: Consuming ASMX WebService or WCF Service in Dynamics Ax
Источник: http://feedproxy.google.com/~r/Rahul...ce-or-wcf.html
============== This post is a quick reference on consuming asmx / svc services in Dynamics Ax. We will also see how to pass .Net types to / from X++ code. There are two methods available in .Net to create web services, one is old ASMX style and another is WCF service. (How to create web service? Do google / bing.) I have created a ASMX web service and deployed it on my local Windows 7 64-bit IIS 7 laptop, http://rahul:200/TestWebService/HelloWorldWS.asmx. This web service contains two web methods. First method takes an integer argument and returns a string value. Second method takes an array as input and returns an array. ASMX C# code: 1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Web; 5: using System.Web.Services; 6: 7: [WebService(Namespace = "http://tempuri.org/")] 8: [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 9: // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 10: // [System.Web.Script.Services.ScriptService] 11: public class HelloWorldWS : System.Web.Services.WebService 12: { 13: public HelloWorldWS () { 14: //Uncomment the following line if using designed components 15: //InitializeComponent(); 16: } 17: 18: [WebMethod] 19: public string GetData(int value) 20: { 21: return string.Format("You entered: {0}", value); 22: } 23: 24: [WebMethod] 25: public string[] GetDataArray(string[] value) 26: { 27: string[] ret = value; 28: 29: return ret; 30: } 31: 32: } With same functionality WCF service code will look like this and it is also deployed on my laptop at http://rahul:201/Service.svc. WCF C# code: 1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Runtime.Serialization; 5: using System.ServiceModel; 6: using System.ServiceModel.Web; 7: using System.Text; 8: 9: // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service" in code, svc and config file together. 10: public class Service : IService 11: { 12: public string GetData(int value) 13: { 14: return string.Format("You entered: {0}", value); 15: } 16: 17: public string[] GetDataArray(string[] value) 18: { 19: string[] ret = value; 20: 21: return ret; 22: } 23: } Add reference for above web services in Dynamics Ax. You need to go to AOT --> References --> Add service reference. Here you need to add WSDL URL for your web services. You get WSDL URL by adding "?wsdl" at the end of your web service URL. ASMX WSDL is: http://rahul:200/TestWebService/HelloWorldWS.asmx?wsdl WCF WSDL is: http://rahul:201/Service.svc?wsdl AX will generate a proxy .net assembly (namespace provided in above figure) and configuration file for the web service. You can find this in your AX installation path at \50\Application\Appl\DynamicsAx50\ServiceReferences Create a wrapper AX class for the proxy. Now we will create a wrapper class for the generated web service proxy. By design, AX needs this class to be running on server tier. So, set class RunOn property to server and create two methods GetData(int _input) & GetDataArray(Container _inputContainer). You can also create a main() to test web service call at server tier. Then we will create a job that will run on client tier to call our wrapper class. X++ code: 1: //X++ (ASMX web service wrapper) class running on server (RunOn: Server) 2: public class HelloWorldWS 3: { 4: } 5: 6: //this methods passes int value to web service that return System.String 7: public static server str GetData(int _input = 0) 8: { 9: Rah.HelloWorldWS.HelloWorldWSSoapClient ws;//web service proxy 10: System.String wsResult;//web method's return value 11: str retStr; 12: ; 13: 14: try 15: { 16: new InteropPermission(InteropKind::ClrInterop).assert(); 17: 18: //call web service 19: ws = new Rah.HelloWorldWS.HelloWorldWSSoapClient("HelloWorldWSSoap"); 20: wsResult = ws.GetData(_input); 21: 22: //check if web service call returned value. 23: //web service can return a null object and this null object is not supported in x++ 24: if (!CLRInterop::isNull(wsResult)) 25: { 26: info("wrapper: " + any2str(CLRInterop::getAnyTypeForObject(wsResult))); 27: retStr = any2str(CLRInterop::getAnyTypeForObject(wsResult)); 28: } 29: CodeAccessPermission::revertAssert(); 30: return retStr; 31: } 32: catch (Exception::CLRError) 33: { 34: throw error(AifUtil::getClrErrorMessage()); 35: } 36: } 37: 38: //this method passes System.String[] as input parameter to web service and 39: //receives System.String[] as output 40: public static server container GetDataArray(container _inputContainer = connull()) 41: { 42: Rah.HelloWorldWS.HelloWorldWSSoapClient ws;//web service proxy 43: System.String[] wsInputArrS;//web method's input argument 44: System.Array wsResultArr;//web method's return value 45: int wsResultArrLen;//return value's length 46: 47: int i; 48: container retCon;//array converted to x++ container, to pass it on client tier 49: int inputConLen; 50: ; 51: 52: if (_inputContainer != connull()) 53: { 54: inputConLen = conlen(_inputContainer); 55: 56: } 57: else 58: return retCon; 59: 60: try 61: { 62: new InteropPermission(InteropKind::ClrInterop).assert(); 63: 64: //initialize .NET Framework array by special X++ syntax, note () at the end 65: wsInputArrS = new System.String[inputConLen](); 66: 67: //prepare input 68: for (i = 0; i < inputConLen; i++) 69: { 70: wsInputArrS.SetValue(CLRInterop::getObjectForAnyType(conpeek(_inputContainer, i+1)), i); 71: } 72: 73: //call web service 74: ws = new Rah.HelloWorldWS.HelloWorldWSSoapClient("HelloWorldWSSoap"); 75: wsResultArr = ws.GetDataArray(wsInputArrS); 76: 77: //check if web service call returned value. 78: //web service can return a null object and this null object is not supported in x++ 79: if (!CLRInterop::isNull(wsResultArr)) 80: { 81: wsResultArrLen = wsResultArr.get_Length(); 82: for (i = 0; i < wsResultArrLen; i++) 83: { 84: info("wrapper: " + any2str(CLRInterop::getAnyTypeForObject(wsResultArr.GetValue(i)))); 85: retCon += any2str(CLRInterop::getAnyTypeForObject(wsResultArr.GetValue(i))); 86: } 87: } 88: CodeAccessPermission::revertAssert(); 89: return retCon; 90: } 91: catch (Exception::CLRError) 92: { 93: throw error(AifUtil::getClrErrorMessage()); 94: } 95: } 96: 97: //test web service call on server tier 98: public static void main(Args _args) 99: { 100: str ret; 101: container retCon, con; 102: int i; 103: ; 104: 105: ret = HelloWorldWS::GetData(123); 106: 107: con += "hello-"; 108: con += "world"; 109: retCon = HelloWorldWS::GetDataArray(con); 110: 111: //use web service results 112: info("main: " + ret); 113: ret = ''; 114: 115: for (i = 0; i < conlen(retCon); i++) 116: { 117: ret += conpeek(retCon, i+1); 118: } 119: 120: info("main arr: " + ret); 121: } Also try to call this from AX job. 1: public static void HelloWorldWS_Arr(Args _args) 2: { 3: str ret; 4: container retCon, con; 5: int i; 6: ; 7: 8: ret = HelloWorldWS::GetData(123); 9: 10: con += "hello-"; 11: con += "world"; 12: retCon = HelloWorldWS::GetDataArray(con); 13: 14: //use web service results 15: info("job: " + ret); 16: ret = ''; 17: 18: for (i = 0; i < conlen(retCon); i++) 19: { 20: ret += conpeek(retCon, i+1); 21: } 22: 23: info("job arr: " + ret); 24: } Same logic can be applied to create wrapper class for WCF service. Please join this blog if you liked this post. Also feel free to post your comment / feedback / queries.www.RahulSharma.in Источник: http://feedproxy.google.com/~r/Rahul...ce-or-wcf.html |
|
|
|