//
// 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