Thursday, 16 May 2013

Creating an API to create the WebServices Proxy Wrapper classes/asmx files

Following from Running the Asmx WebServices WebMethod invocation wrapper on a local WebServer (i.e Hacmebank UserManagement.asmx) the next step is to wrap this code in an easy to consume API.

So let’s open the O2 Development Environment tool (available from the main O2 platform menu)


image

which looks like this:

image

in the bottom left tree, I navigated into the Languages/DotNet folder and created a new WSDL folder

image

then I opened that new folder and chose to create a new file:

image

called  API_ASMX_Proxies.cs

image

with this first test content:

image

To test this script, open a C# REPL GUI,  from the main O2 Platform GUI, or from here:

image

In the C# REPL, add a reference to the new file (using the syntax //O2File:{filePath} )

image

and create an instance of the API_ASMX_Proxies object

image

note that the intelisense will pick up the new method:

image

which can be used as normal (note the value in the TextArea and the Output window)

image

Next we convert the original Lambda methods into Extension Methods, so that they can be consumed like this:

image

which is part of this code snippet (also based on the original code):

image

To refactor this code, we add a number of properties to the API_ASMX_Proxy.cs file

image

and these two extension methods:

image

and now we can create a proxy class like this:

image

in fact using topPanel.add_FolderViewers(…) is a better way to see the files created

image


Scripts used in this post
1) first version of the API_ASMX_Proxies.cs file
   1: using System;
   2: using System.Linq;
   3: using System.Collections.Generic;
   4: using System.Windows.Forms;
   5: using System.Text;
   6: using O2.DotNetWrappers.ExtensionMethods;
   7: using O2.XRules.Database.Utils;
   8:  
   9: namespace O2.XRules.Database.APIs
  10: {
  11:     public class API_ASMX_Proxies
  12:     {
  13:         public string hello_API_ASMX_Proxies(string name)
  14:         {
  15:             return "Hello " + name;
  16:         }
  17:     }
  18: }

2) C# REPL script that consumed the first version of the API_ASMX_Proxies.cs file (shown above)

   1: //var topPanel = "{name}".popupWindow(700,400);
   2: var topPanel = panel.clear().add_Panel();
   3: var textBox = topPanel.add_TextBox(true);
   4:  
   5: var asmxProxies = new API_ASMX_Proxies();
   6: var value = asmxProxies.hello_API_ASMX_Proxies("Joe");
   7: textBox.set_Text("hello world");
   8: return asmxProxies;
   9: //O2File:E:\O2\O2.Platform.Scripts\Languages\AspNet\WSDL\API_ASMX_Proxies.cs


3) first conversion of the lambda methods into ExtensionMethods (in the API_ASMX_Proxy.cs file)
   1: // This file is part of the OWASP O2 Platform (http://www.owasp.org/index.php/OWASP_O2_Platform) and is released under the Apache 2.0 License (http://www.apache.org/licenses/LICENSE-2.0)
   2: using System;
   3: using System.Linq;
   4: using System.Collections.Generic;
   5: using System.Windows.Forms;
   6: using System.Text;
   7: using O2.DotNetWrappers.ExtensionMethods;
   8: using O2.XRules.Database.Utils;
   9: using ICSharpCode.NRefactory.Ast;
  10: using O2.API.AST.ExtensionMethods.CSharp;
  11:  
  12: //O2File:_Extra_methods_To_Add_to_Main_CodeBase.cs
  13:  
  14: namespace O2.XRules.Database.APIs
  15: {
  16:     public class API_ASMX_Proxy
  17:     {
  18:         public CompilationUnit Proxy_CompilationUnit { get; set; }
  19:         
  20:         public API_ASMX_Proxy()
  21:         {
  22:             SetUp();
  23:         }
  24:         
  25:         public API_ASMX_Proxy SetUp()
  26:         {
  27:             Proxy_CompilationUnit = new CompilationUnit();            
  28:             Proxy_CompilationUnit.add_Using("System");
  29:             Proxy_CompilationUnit.add_Using("System.Web.Services"); 
  30:             return this;
  31:         }
  32:     }
  33:     
  34:     
  35:     public static class API_ASMX_Proxy_ExtensionMethods

  36:     {

  37:         public static API_ASMX_Proxy add_Property_To_Type_Constructor(this API_ASMX_Proxy asmxProxy, TypeDeclaration targetType, string propertyName, TypeDeclaration propertyType)
  38:         {
  39:             targetType.add_Property(propertyName,propertyType)    
  40:                       .add_Ctor()                                
  41:                       .body()                                    
  42:                       .add_Assignment(propertyName, propertyType);
  43:             return asmxProxy;
  44:         }
  45:  
  46:          public static MethodDeclaration create_ProxyMethod(this API_ASMX_Proxy asmxProxy, MethodDeclaration methodToProxy, string webServicesObjectName)
  47:         {            
  48:             var proxyMethod = methodToProxy.clone()
  49:                                            .remove_Attributes();
  50:             var body = proxyMethod.add_Body();        
  51:             
  52:             proxyMethod.add_Attribute("WebMethod");
  53:             
  54:             var parameters = methodToProxy.parameters().names().ast_Identifiers().ToArray();
  55:             var invocation = webServicesObjectName.ast_Invocation_onType(methodToProxy.Name,parameters);
  56:             
  57:             if(proxyMethod.TypeReference.name() =="void" || proxyMethod.TypeReference.name() == "System.Void")
  58:             {
  59:                 body.append(invocation.expressionStatement());
  60:             }
  61:             else
  62:             {
  63:                 var result = body.add_Variable("result", invocation, methodToProxy.TypeReference);
  64:                 body.add_Return(result.Name.ast_Identifier());
  65:             }
  66:             return proxyMethod;
  67:          }
  68:     
  69:         public static string create_Wrapper_CSharpCode(this API_ASMX_Proxy asmxProxy, TypeDeclaration wsClass,string wsFileName)    
  70:         {
  71:             var compilationUnit = asmxProxy.Proxy_CompilationUnit;
  72:             var wrapperType  = compilationUnit.add_Type(wsClass.Name + "_Wrapper");
  73:             var propName = "_web_Service";
  74:             asmxProxy.add_Property_To_Type_Constructor(wrapperType,propName, wsClass);
  75:             
  76:             var wsMethods = wsClass.methods_with_Attribute("System.Web.Services.Protocols.SoapDocumentMethodAttribute");
  77:             foreach(var wsMethod in wsMethods)
  78:             { 
  79:                 wrapperType.append(asmxProxy.create_ProxyMethod(wsMethod,propName));      
  80:             }
  81:             var csharpCode = compilationUnit.csharpCode()
  82:                         .insertAt(0, @"//O2File:{0}".format(wsFileName).line());;
  83:             return csharpCode;
  84:         }
  85:         public static API_ASMX_Proxy create_Wrapper_SourceCodeFile(this API_ASMX_Proxy asmxProxy, string sourceFile, string targetFile)
  86:         {
  87:             var fileAst = sourceFile.csharpAst();
  88:             var _wsClass = fileAst.type_with_BaseType("System.Web.Services.Protocols.SoapHttpClientProtocol");  
  89:                 var _csharpCode = asmxProxy.create_Wrapper_CSharpCode(_wsClass, sourceFile.fileName());
  90:                 _csharpCode.saveAs(targetFile);
  91:             return asmxProxy;
  92:         }
  93:     
  94:         public static API_ASMX_Proxy createAsmxFile(this API_ASMX_Proxy asmxProxy, string className, string targetFile)
  95:         {
  96:             var asmxCodeContent = @"<%@ WebService Language=""c#"" Class=""{0}"" %>"
  97:                                        .format(className);
  98:             asmxCodeContent.saveAs(targetFile);    
  99:             return asmxProxy;
 100:         }
 101:     }
 102: }

4) C# Script that consumes the version of the API_ASMX_Proxy.cs shown above:
   1: //var topPanel = "{name}".popupWindow(700,400);
   2: var topPanel = panel.clear().add_Panel();
   3:  
   4: var codeEditor = topPanel.add_SourceCodeEditor();
   5:  
   6: var sourcefile = @"E:\O2\O2.Temp\5_10_2013\wsdl_tmpC5E1\WS_UserManagement.cs";
   7:  
   8: var webRoot_Folder = "_wsTest".tempDir(false);
   9: var appCode_Folder = webRoot_Folder.pathCombine("App_Code").createDir();
  10: var wsdlfile = sourcefile.file_Copy(appCode_Folder);
  11: var wrapperFile = appCode_Folder.pathCombine("_WebMethod_" + wsdlfile.fileName());
  12: var asmxFile = webRoot_Folder.pathCombine("UserManagement.asmx");
  13:  
  14: var asmx_Proxy = new API_ASMX_Proxy();
  15: asmx_Proxy.createAsmxFile("WS_UserManagement_Wrapper", asmxFile)
  16:           .create_Wrapper_SourceCodeFile(wsdlfile, wrapperFile);                  
  17:  
  18: codeEditor.open("").open(wrapperFile);
  19:  
  20: return "done"; 
  21: //O2File:E:\O2\O2.Platform.Scripts\Languages\AspNet\WSDL\API_ASMX_Proxy.cs

5) final version of the API_ASMX_Proxy.cs file
   1: // This file is part of the OWASP O2 Platform (http://www.owasp.org/index.php/OWASP_O2_Platform) and is released under the Apache 2.0 License (http://www.apache.org/licenses/LICENSE-2.0)
   2: using System;
   3: using System.Linq;
   4: using System.Collections.Generic;
   5: using System.Windows.Forms;
   6: using System.Text;
   7: using O2.DotNetWrappers.ExtensionMethods;
   8: using O2.XRules.Database.Utils;
   9: using ICSharpCode.NRefactory.Ast;
  10: using O2.API.AST.ExtensionMethods.CSharp;
  11:  
  12: //O2File:_Extra_methods_To_Add_to_Main_CodeBase.cs
  13:  
  14: namespace O2.XRules.Database.APIs
  15: {
  16:     public class API_ASMX_Proxy
  17:     {
  18:         public CompilationUnit     Proxy_CompilationUnit             { get; set; }
  19:         public string              WebRoot_Folder                     { get; set; }
  20:         public string             AppCode_Folder                    { get; set; }
  21:         public string              Wsdl_CS_File_OriginalLocation    { get; set; }
  22:         public string              Wsdl_CS_File_In_AppCode            { get; set; }
  23:         public string              Proxy_Wrapper_CS_File            { get; set; }
  24:         public string              AsmxFile                        { get; set; }
  25:         
  26:         public API_ASMX_Proxy()
  27:         {
  28:             SetUp();
  29:         }
  30:         
  31:         public API_ASMX_Proxy SetUp()
  32:         {
  33:             Proxy_CompilationUnit = new CompilationUnit();            
  34:             Proxy_CompilationUnit.add_Using("System");
  35:             Proxy_CompilationUnit.add_Using("System.Web.Services"); 
  36:             return this;
  37:         }    
  38:     }
  39:         
  40:     
  41:     
  42:     
  43:     public static class API_ASMX_Proxy_ExtensionMethods
  44:     {
  45:         public static API_ASMX_Proxy set_Target_Values_and_Folders(this API_ASMX_Proxy asmxProxy, string webRoot_Folder, string wsdl_CS_File, string asmxFileName)
  46:         {
  47:             asmxProxy.Wsdl_CS_File_OriginalLocation = wsdl_CS_File;    
  48:             asmxProxy.WebRoot_Folder                 = webRoot_Folder;
  49:             asmxProxy.AppCode_Folder                 = asmxProxy.WebRoot_Folder.pathCombine("App_Code").createDir();
  50:             asmxProxy.Wsdl_CS_File_In_AppCode         = asmxProxy.Wsdl_CS_File_OriginalLocation.file_Copy(asmxProxy.AppCode_Folder);

  51:             asmxProxy.Proxy_Wrapper_CS_File            = asmxProxy.AppCode_Folder.pathCombine("_WebMethod_" + wsdl_CS_File.fileName());
  52:             asmxProxy.AsmxFile                         = asmxProxy.WebRoot_Folder.pathCombine(asmxFileName);
  53:             return asmxProxy;
  54:         }
  55:         
  56:         public static API_ASMX_Proxy create_Proxy_Files_For_WSDL(this API_ASMX_Proxy asmxProxy, string webRoot_Folder, string wsdl_CS_File, string asmxFileName)
  57:         {
  58:             return  asmxProxy.set_Target_Values_and_Folders(webRoot_Folder, wsdl_CS_File, asmxFileName)
  59:                              .createAsmxFile("WS_UserManagement_Wrapper", asmxProxy.AsmxFile)
  60:                                  .create_Wrapper_SourceCodeFile(asmxProxy.Wsdl_CS_File_In_AppCode, asmxProxy.Proxy_Wrapper_CS_File    );            
  61:         }
  62:         
  63:     
  64:  
  65:     
  66:         public static API_ASMX_Proxy add_Property_To_Type_Constructor(this API_ASMX_Proxy asmxProxy, TypeDeclaration targetType, string propertyName, TypeDeclaration propertyType)
  67:         {
  68:             targetType.add_Property(propertyName,propertyType)    
  69:                       .add_Ctor()                                
  70:                       .body()                                    
  71:                       .add_Assignment(propertyName, propertyType);
  72:             return asmxProxy;
  73:         }
  74:  
  75:          public static MethodDeclaration create_ProxyMethod(this API_ASMX_Proxy asmxProxy, MethodDeclaration methodToProxy, string webServicesObjectName)
  76:         {            
  77:             var proxyMethod = methodToProxy.clone()
  78:                                            .remove_Attributes();
  79:             var body = proxyMethod.add_Body();        
  80:             
  81:             proxyMethod.add_Attribute("WebMethod");
  82:             
  83:             var parameters = methodToProxy.parameters().names().ast_Identifiers().ToArray();
  84:             var invocation = webServicesObjectName.ast_Invocation_onType(methodToProxy.Name,parameters);
  85:             
  86:             if(proxyMethod.TypeReference.name() =="void" || proxyMethod.TypeReference.name() == "System.Void")
  87:             {
  88:                 body.append(invocation.expressionStatement());
  89:             }
  90:             else
  91:             {
  92:                 var result = body.add_Variable("result", invocation, methodToProxy.TypeReference);
  93:                 body.add_Return(result.Name.ast_Identifier());
  94:             }
  95:             return proxyMethod;
  96:          }
  97:     
  98:         public static string create_Wrapper_CSharpCode(this API_ASMX_Proxy asmxProxy, TypeDeclaration wsClass,string wsFileName)    
  99:         {
 100:             var compilationUnit = asmxProxy.Proxy_CompilationUnit;
 101:             var wrapperType  = compilationUnit.add_Type(wsClass.Name + "_Wrapper");
 102:             var propName = "_web_Service";
 103:             asmxProxy.add_Property_To_Type_Constructor(wrapperType,propName, wsClass);
 104:             
 105:             var wsMethods = wsClass.methods_with_Attribute("System.Web.Services.Protocols.SoapDocumentMethodAttribute");
 106:             foreach(var wsMethod in wsMethods)
 107:             { 
 108:                 wrapperType.append(asmxProxy.create_ProxyMethod(wsMethod,propName));      
 109:                 break;
 110:             }
 111:             var csharpCode = compilationUnit.csharpCode()
 112:                         .insertAt(0, @"//O2File:{0}".format(wsFileName).line());;
 113:             return csharpCode;
 114:         }
 115:         public static API_ASMX_Proxy create_Wrapper_SourceCodeFile(this API_ASMX_Proxy asmxProxy, string sourceFile, string targetFile)
 116:         {
 117:             var fileAst = sourceFile.csharpAst();
 118:             var _wsClass = fileAst.type_with_BaseType("System.Web.Services.Protocols.SoapHttpClientProtocol");  
 119:                 var _csharpCode = asmxProxy.create_Wrapper_CSharpCode(_wsClass, sourceFile.fileName());
 120:                 _csharpCode.saveAs(targetFile);
 121:             return asmxProxy;
 122:         }
 123:
 124:         public static API_ASMX_Proxy createAsmxFile(this API_ASMX_Proxy asmxProxy, string className, string targetFile)
 125:         {
 126:             var asmxCodeContent = @"<%@ WebService Language=""c#"" Class=""{0}"" %>"
 127:                                        .format(className);
 128:             asmxCodeContent.saveAs(targetFile);    
 129:             return asmxProxy;
 130:         }
 131:     }
 132: }

6) C# script that conumed the final version of API_ASMX_Proxy.cs file
   1: //var topPanel = "{name}".popupWindow(700,400);
   2: var topPanel = panel.clear().add_Panel(); 
   3:  
   4: var sourcefile = @"E:\O2\O2.Temp\5_10_2013\wsdl_tmpC5E1\WS_UserManagement.cs";
   5: var webRoot_Folder = "_wsTest".tempDir(false);
   6: var asmxFileName  = "UserManagement.asmx";
   7:  
   8: var apiAsmx = new API_ASMX_Proxy();
   9: apiAsmx.create_Proxy_Files_For_WSDL(webRoot_Folder, sourcefile, asmxFileName);
  10:  
  11: topPanel.add_FolderViewer(webRoot_Folder);
  12:  
  13: return "done"; 
  14: //O2File:API_ASMX_Proxy.cs