// // System.Web.Services.Description.SoapProtocolImporter.cs // // Author: // Tim Coleman (tim@timcoleman.com) // Lluis Sanchez Gual (lluis@ximian.com) // // Copyright (C) Tim Coleman, 2002 // using System.CodeDom; using System.Web.Services; using System.Web.Services.Protocols; using System.Web.Services.Configuration; using System.Xml; using System.Xml.Serialization; using System.Configuration; using System.Collections; namespace System.Web.Services.Description { public sealed class SoapProtocolImporter : ProtocolImporter { #region Fields SoapBinding soapBinding; SoapCodeExporter soapExporter; SoapSchemaImporter soapImporter; XmlCodeExporter xmlExporter; XmlSchemaImporter xmlImporter; CodeIdentifiers memberIds; ArrayList extensionImporters; Hashtable headerVariables; #endregion // Fields #region Constructors public SoapProtocolImporter () { extensionImporters = ExtensionManager.BuildExtensionImporters (); } void SetBinding (SoapBinding soapBinding) { this.soapBinding = soapBinding; } #endregion // Constructors #region Properties public override string ProtocolName { get { return "Soap"; } } public SoapBinding SoapBinding { get { return soapBinding; } } public SoapCodeExporter SoapExporter { get { return soapExporter; } } public SoapSchemaImporter SoapImporter { get { return soapImporter; } } public XmlCodeExporter XmlExporter { get { return xmlExporter; } } public XmlSchemaImporter XmlImporter { get { return xmlImporter; } } #endregion // Properties #region Methods protected override CodeTypeDeclaration BeginClass () { soapBinding = (SoapBinding) Binding.Extensions.Find (typeof(SoapBinding)); if (soapBinding == null) throw new Exception ("None of the supported bindings was found"); if (soapBinding.Style != SoapBindingStyle.Document) throw new Exception ("Binding style not supported"); CodeTypeDeclaration codeClass = new CodeTypeDeclaration (ClassName); string url = GetServiceUrl (); CodeTypeReference ctr = new CodeTypeReference ("System.Web.Services.Protocols.SoapHttpClientProtocol"); codeClass.BaseTypes.Add (ctr); CodeConstructor cc = new CodeConstructor (); cc.Attributes = MemberAttributes.Public; CodeExpression ce = new CodeFieldReferenceExpression (new CodeThisReferenceExpression(), "Url"); CodeAssignStatement cas = new CodeAssignStatement (ce, new CodePrimitiveExpression (url)); cc.Statements.Add (cas); codeClass.Members.Add (cc); memberIds = new CodeIdentifiers (); headerVariables = new Hashtable (); return codeClass; } string GetServiceUrl () { string location = null; SoapAddressBinding sab = (SoapAddressBinding) Port.Extensions.Find (typeof(SoapAddressBinding)); if (sab != null) location = sab.Location; if (ImportInfo.AppSettingUrlKey == null || ImportInfo.AppSettingUrlKey == string.Empty) return location; else { string url; if (Style == ServiceDescriptionImportStyle.Server) throw new InvalidOperationException ("Cannot set appSettingUrlKey if Style is Server"); url = ConfigurationSettings.AppSettings [ImportInfo.AppSettingUrlKey]; if (ImportInfo.AppSettingBaseUrl != null && ImportInfo.AppSettingBaseUrl != string.Empty) url += "/" + ImportInfo.AppSettingBaseUrl + "/" + location; return url; } } protected override void BeginNamespace () { xmlImporter = new XmlSchemaImporter (Schemas); soapImporter = new SoapSchemaImporter (Schemas); xmlExporter = new XmlCodeExporter (CodeNamespace, null); } protected override void EndClass () { SoapTransportImporter transportImporter = SoapTransportImporter.FindTransportImporter (soapBinding.Transport); if (transportImporter == null) throw new Exception ("Transport '" + soapBinding.Transport + "' not supported"); transportImporter.ImportContext = this; transportImporter.ImportClass (); } protected override void EndNamespace () { } [MonoTODO] protected override bool IsBindingSupported () { throw new NotImplementedException (); } [MonoTODO] protected override bool IsOperationFlowSupported (OperationFlow flow) { throw new NotImplementedException (); } void AddComments (CodeTypeMember member, string comments) { if (comments == null || comments == "") member.Comments.Add (new CodeCommentStatement ("", true)); else member.Comments.Add (new CodeCommentStatement ("\n" + comments + "\n", true)); } protected override CodeMemberMethod GenerateMethod () { try { SoapOperationBinding soapOper = OperationBinding.Extensions.Find (typeof (SoapOperationBinding)) as SoapOperationBinding; if (soapOper == null) throw new Exception ("Soap operation binding not found in operation " + OperationBinding.Name); if (soapOper.Style != SoapBindingStyle.Document) throw new Exception ("Operation binding style not supported in operation " + OperationBinding.Name); SoapBodyBinding isbb = OperationBinding.Input.Extensions.Find (typeof(SoapBodyBinding)) as SoapBodyBinding; if (isbb == null) throw new Exception ("Soap body binding not found in operation " + OperationBinding.Name); SoapBodyBinding osbb = OperationBinding.Output.Extensions.Find (typeof(SoapBodyBinding)) as SoapBodyBinding; if (osbb == null) throw new Exception ("Soap body binding not found in operation " + OperationBinding.Name); XmlMembersMapping inputMembers = ImportMembersMapping (InputMessage, isbb, soapOper); if (inputMembers == null) throw new Exception ("Input message not declared in operation " + OperationBinding.Name); XmlMembersMapping outputMembers = ImportMembersMapping (OutputMessage, osbb, soapOper); if (outputMembers == null) throw new Exception ("Output message not declared in operation " + OperationBinding.Name); CodeMemberMethod met = GenerateMethod (memberIds, soapOper, isbb, inputMembers, outputMembers); xmlExporter.ExportMembersMapping (inputMembers); xmlExporter.ExportMembersMapping (outputMembers); foreach (SoapExtensionImporter eximporter in extensionImporters) { eximporter.ImportContext = this; eximporter.ImportMethod (met.CustomAttributes); } return met; } catch (Exception ex) { UnsupportedOperationBindingWarning (ex.Message); return null; } } XmlMembersMapping ImportMembersMapping (Message msg, SoapBodyBinding sbb, SoapOperationBinding soapOper) { XmlQualifiedName elem = null; if (msg.Parts.Count == 1 && msg.Parts[0].Name == "parameters") { // Wrapped parameter style MessagePart part = msg.Parts[0]; if (sbb.Use == SoapBindingUse.Encoded) { SoapSchemaMember ssm = new SoapSchemaMember (); ssm.MemberName = part.Name; ssm.MemberType = part.Type; return soapImporter.ImportMembersMapping (Operation.Name, part.Type.Namespace, ssm); } else return xmlImporter.ImportMembersMapping (part.Element); } else { if (sbb.Use == SoapBindingUse.Encoded) { SoapSchemaMember[] mems = new SoapSchemaMember [msg.Parts.Count]; for (int n=0; n 0) methodParams = new CodeArrayCreateExpression (typeof(object), paramArray); else methodParams = new CodeArrayCreateExpression (typeof(object), 0); // Assignment of output parameters CodeStatementCollection outAssign = new CodeStatementCollection (); CodeVariableReferenceExpression arrVar = new CodeVariableReferenceExpression (varResults); for (int n=0; n