|
//------------------------------------------------------------------------------
// <copyright from='1997' to='2001' company='Microsoft Corporation'>
// Copyright (c) Microsoft Corporation. All Rights Reserved.
// Information Contained Herein is Proprietary and Confidential.
// </copyright>
//------------------------------------------------------------------------------
namespace System.Web.Services.Description {
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Serialization.Advanced;
using System.Xml.Schema;
using System.Collections;
using System;
using System.Data;
using System.Data.Design;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Web.Services.Configuration;
using System.Diagnostics;
using System.ComponentModel;
using System.Security.Permissions;
using System.Globalization;
using System.Threading;
internal class SoapParameters {
XmlMemberMapping ret;
ArrayList parameters = new ArrayList();
ArrayList inParameters = new ArrayList();
ArrayList outParameters = new ArrayList();
int checkSpecifiedCount;
int inCheckSpecifiedCount;
int outCheckSpecifiedCount;
internal SoapParameters(XmlMembersMapping request, XmlMembersMapping response, string[] parameterOrder, CodeIdentifiers identifiers) {
ArrayList requestList = new ArrayList();
ArrayList responseList = new ArrayList();
AddMappings(requestList, request);
if (response != null) AddMappings(responseList, response);
if (parameterOrder != null) {
for (int i = 0; i < parameterOrder.Length; i++) {
string elementName = parameterOrder[i];
XmlMemberMapping requestMapping = FindMapping(requestList, elementName);
SoapParameter parameter = new SoapParameter();
if (requestMapping != null) {
if (RemoveByRefMapping(responseList, requestMapping))
parameter.codeFlags = CodeFlags.IsByRef;
parameter.mapping = requestMapping;
requestList.Remove(requestMapping);
AddParameter(parameter);
}
else {
XmlMemberMapping responseMapping = FindMapping(responseList, elementName);
if (responseMapping != null) {
parameter.codeFlags = CodeFlags.IsOut;
parameter.mapping = responseMapping;
responseList.Remove(responseMapping);
AddParameter(parameter);
}
}
}
}
foreach (XmlMemberMapping requestMapping in requestList) {
SoapParameter parameter = new SoapParameter();
if (RemoveByRefMapping(responseList, requestMapping))
parameter.codeFlags = CodeFlags.IsByRef;
parameter.mapping = requestMapping;
AddParameter(parameter);
}
if (responseList.Count > 0) {
if (!((XmlMemberMapping) responseList[0]).CheckSpecified) {
ret = (XmlMemberMapping)responseList[0];
responseList.RemoveAt(0);
}
foreach (XmlMemberMapping responseMapping in responseList) {
SoapParameter parameter = new SoapParameter();
parameter.mapping = responseMapping;
parameter.codeFlags = CodeFlags.IsOut;
AddParameter(parameter);
}
}
foreach (SoapParameter parameter in parameters) {
parameter.name = identifiers.MakeUnique(CodeIdentifier.MakeValid(parameter.mapping.MemberName));
}
}
void AddParameter(SoapParameter parameter) {
parameters.Add(parameter);
if (parameter.mapping.CheckSpecified) {
checkSpecifiedCount++;
}
if (parameter.IsByRef) {
inParameters.Add(parameter);
outParameters.Add(parameter);
if (parameter.mapping.CheckSpecified) {
inCheckSpecifiedCount++;
outCheckSpecifiedCount++;
}
} else if (parameter.IsOut) {
outParameters.Add(parameter);
if (parameter.mapping.CheckSpecified)
outCheckSpecifiedCount++;
}
else {
inParameters.Add(parameter);
if (parameter.mapping.CheckSpecified)
inCheckSpecifiedCount++;
}
}
static bool RemoveByRefMapping(ArrayList responseList, XmlMemberMapping requestMapping) {
XmlMemberMapping responseMapping = FindMapping(responseList, requestMapping.ElementName);
if (responseMapping == null) return false;
if (requestMapping.TypeFullName != responseMapping.TypeFullName) return false;
if (requestMapping.Namespace != responseMapping.Namespace) return false;
if (requestMapping.MemberName != responseMapping.MemberName) return false;
responseList.Remove(responseMapping);
return true;
}
static void AddMappings(ArrayList mappingsList, XmlMembersMapping mappings) {
for (int i = 0; i < mappings.Count; i++) {
mappingsList.Add(mappings[i]);
}
}
static XmlMemberMapping FindMapping(ArrayList mappingsList, string elementName) {
foreach (XmlMemberMapping mapping in mappingsList)
if (mapping.ElementName == elementName)
return mapping;
return null;
}
internal XmlMemberMapping Return {
get { return ret; }
}
internal IList Parameters {
get { return parameters; }
}
internal IList InParameters {
get { return inParameters; }
}
internal IList OutParameters {
get { return outParameters; }
}
internal int CheckSpecifiedCount {
get { return checkSpecifiedCount; }
}
internal int InCheckSpecifiedCount {
get { return inCheckSpecifiedCount; }
}
internal int OutCheckSpecifiedCount {
get { return outCheckSpecifiedCount; }
}
}
internal class SoapParameter {
internal CodeFlags codeFlags;
internal string name;
internal XmlMemberMapping mapping;
internal string specifiedName;
internal bool IsOut {
get { return (codeFlags & CodeFlags.IsOut) != 0; }
}
internal bool IsByRef {
get { return (codeFlags & CodeFlags.IsByRef) != 0; }
}
internal static string[] GetTypeFullNames(IList parameters, int specifiedCount, CodeDomProvider codeProvider) {
string[] typeFullNames = new string[parameters.Count + specifiedCount];
GetTypeFullNames(parameters, typeFullNames, 0, specifiedCount, codeProvider);
return typeFullNames;
}
internal static void GetTypeFullNames(IList parameters, string[] typeFullNames, int start, int specifiedCount, CodeDomProvider codeProvider) {
int specified = 0;
for (int i = 0; i < parameters.Count; i++) {
typeFullNames[i + start + specified] = WebCodeGenerator.FullTypeName(((SoapParameter)parameters[i]).mapping, codeProvider);
if (((SoapParameter) parameters[i]).mapping.CheckSpecified) {
specified++;
typeFullNames[i + start + specified] = typeof(bool).FullName;
}
}
}
internal static string[] GetNames(IList parameters, int specifiedCount) {
string[] names = new string[parameters.Count + specifiedCount];
GetNames(parameters, names, 0, specifiedCount);
return names;
}
internal static void GetNames(IList parameters, string[] names, int start, int specifiedCount) {
int specified = 0;
for (int i = 0; i < parameters.Count; i++) {
names[i + start + specified] = ((SoapParameter)parameters[i]).name;
if (((SoapParameter) parameters[i]).mapping.CheckSpecified) {
specified++;
names[i + start + specified] = ((SoapParameter) parameters[i]).specifiedName;
}
}
}
internal static CodeFlags[] GetCodeFlags(IList parameters, int specifiedCount) {
CodeFlags[] codeFlags = new CodeFlags[parameters.Count + specifiedCount];
GetCodeFlags(parameters, codeFlags, 0, specifiedCount);
return codeFlags;
}
internal static void GetCodeFlags(IList parameters, CodeFlags[] codeFlags, int start, int specifiedCount) {
int specified = 0;
for (int i = 0; i < parameters.Count; i++) {
codeFlags[i + start + specified] = ((SoapParameter)parameters[i]).codeFlags;
if (((SoapParameter) parameters[i]).mapping.CheckSpecified) {
specified++;
codeFlags[i + start + specified] = ((SoapParameter) parameters[i]).codeFlags;
}
}
}
}
internal class GlobalSoapHeader {
internal string fieldName;
internal XmlTypeMapping mapping;
internal bool isEncoded;
}
internal class LocalSoapHeader {
internal SoapHeaderDirection direction;
internal string fieldName;
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
[PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust")]
public class SoapProtocolImporter : ProtocolImporter {
XmlSchemaImporter xmlImporter;
XmlCodeExporter xmlExporter;
SoapSchemaImporter soapImporter;
SoapCodeExporter soapExporter;
ArrayList xmlMembers = new ArrayList();
ArrayList soapMembers = new ArrayList();
Hashtable headers = new Hashtable();
Hashtable classHeaders = new Hashtable();
ArrayList propertyNames = new ArrayList();
ArrayList propertyValues = new ArrayList();
SoapExtensionImporter[] extensions;
SoapTransportImporter transport;
SoapBinding soapBinding;
ArrayList codeClasses = new ArrayList();
static TypedDataSetSchemaImporterExtension typedDataSetSchemaImporterExtension;
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.ProtocolName"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public override string ProtocolName {
get { return "Soap"; }
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.SoapBinding"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public SoapBinding SoapBinding {
get { return soapBinding; }
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.SoapImporter"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public SoapSchemaImporter SoapImporter {
get { return soapImporter; }
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.XmlImporter"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public XmlSchemaImporter XmlImporter {
get { return xmlImporter; }
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.XmlExporter"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public XmlCodeExporter XmlExporter {
get { return xmlExporter; }
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.SoapExporter"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public SoapCodeExporter SoapExporter {
get { return soapExporter; }
}
static TypedDataSetSchemaImporterExtension TypedDataSetSchemaImporterExtension {
get {
if (typedDataSetSchemaImporterExtension == null) {
typedDataSetSchemaImporterExtension = new TypedDataSetSchemaImporterExtension();
}
return typedDataSetSchemaImporterExtension;
}
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.BeginNamespace"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
protected override void BeginNamespace() {
try {
MethodNames.Clear();
ExtraCodeClasses.Clear();
soapImporter = new SoapSchemaImporter(AbstractSchemas, ServiceImporter.CodeGenerationOptions, ImportContext);
xmlImporter = new XmlSchemaImporter(ConcreteSchemas, ServiceImporter.CodeGenerationOptions, ServiceImporter.CodeGenerator, ImportContext);
foreach (Type extensionType in ServiceImporter.Extensions) {
xmlImporter.Extensions.Add(extensionType.FullName, extensionType);
}
// use cached version of typed DataSetSchemaImporterExtension for /sharetypes feature
//
xmlImporter.Extensions.Add(TypedDataSetSchemaImporterExtension);
xmlImporter.Extensions.Add(new DataSetSchemaImporterExtension());
xmlExporter = new XmlCodeExporter(this.CodeNamespace, ServiceImporter.CodeCompileUnit, ServiceImporter.CodeGenerator, ServiceImporter.CodeGenerationOptions, ExportContext);
soapExporter = new SoapCodeExporter(this.CodeNamespace, null, ServiceImporter.CodeGenerator, ServiceImporter.CodeGenerationOptions, ExportContext);
}
catch (Exception e) {
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
throw;
}
throw new InvalidOperationException(Res.GetString(Res.InitFailed), e);
}
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.EndNamespace"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
protected override void EndNamespace() {
// need to preprocess all exported schemas to make sure that IXmlSerializable schemas are Merged and the resulting set is valid
ConcreteSchemas.Compile(null, false);
foreach (GlobalSoapHeader soapHeader in headers.Values) {
if (soapHeader.isEncoded)
soapExporter.ExportTypeMapping(soapHeader.mapping);
else
xmlExporter.ExportTypeMapping(soapHeader.mapping);
}
foreach (XmlMembersMapping member in xmlMembers)
xmlExporter.ExportMembersMapping(member);
foreach (XmlMembersMapping member in soapMembers)
soapExporter.ExportMembersMapping(member);
// NOTE, Microsoft, we are sharing the SoapInclude and XmlInclude attributes of the
// class among ALL classes generated, This is probably OK, since doing to per
// class would probably result in the same set of includes if the user
// has object as a return value (meaning 'all' types are OK).
foreach (CodeTypeDeclaration codeClass in codeClasses) {
foreach (CodeAttributeDeclaration attribute in xmlExporter.IncludeMetadata) {
codeClass.CustomAttributes.Add(attribute);
}
foreach (CodeAttributeDeclaration attribute in soapExporter.IncludeMetadata) {
codeClass.CustomAttributes.Add(attribute);
}
}
foreach (CodeTypeDeclaration declaration in ExtraCodeClasses) {
this.CodeNamespace.Types.Add(declaration);
}
CodeGenerator.ValidateIdentifiers(CodeNamespace);
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.IsBindingSupported"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
protected override bool IsBindingSupported() {
SoapBinding soapBinding = (SoapBinding)Binding.Extensions.Find(typeof(SoapBinding));
if (soapBinding == null || soapBinding.GetType() != typeof(SoapBinding)) return false;
if (GetTransport(soapBinding.Transport) == null) {
UnsupportedBindingWarning(Res.GetString(Res.ThereIsNoSoapTransportImporterThatUnderstands1, soapBinding.Transport));
return false;
}
return true;
}
internal SoapTransportImporter GetTransport(string transport) {
foreach (Type type in WebServicesSection.Current.SoapTransportImporters)
{
SoapTransportImporter transportImporter = (SoapTransportImporter)Activator.CreateInstance(type);
transportImporter.ImportContext = this;
if (transportImporter.IsSupportedTransport(transport)) return transportImporter;
}
return null;
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.BeginClass"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
protected override CodeTypeDeclaration BeginClass() {
MethodNames.Clear();
soapBinding = (SoapBinding)Binding.Extensions.Find(typeof(SoapBinding));
transport = GetTransport(soapBinding.Transport);
Type[] requiredTypes = new Type[] { typeof(SoapDocumentMethodAttribute), typeof(XmlAttributeAttribute), typeof(WebService), typeof(Object), typeof(DebuggerStepThroughAttribute), typeof(DesignerCategoryAttribute) };
WebCodeGenerator.AddImports(this.CodeNamespace, WebCodeGenerator.GetNamespacesForTypes(requiredTypes));
CodeFlags flags = 0;
if (Style == ServiceDescriptionImportStyle.Server)
flags = CodeFlags.IsAbstract;
else if (Style == ServiceDescriptionImportStyle.ServerInterface)
flags = CodeFlags.IsInterface;
CodeTypeDeclaration codeClass = WebCodeGenerator.CreateClass(this.ClassName, null,
new string[0], null, CodeFlags.IsPublic | flags,
ServiceImporter.CodeGenerator.Supports(GeneratorSupport.PartialTypes));
codeClass.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
if (Style == ServiceDescriptionImportStyle.Client) {
codeClass.CustomAttributes.Add(new CodeAttributeDeclaration(typeof(DebuggerStepThroughAttribute).FullName));
codeClass.CustomAttributes.Add(new CodeAttributeDeclaration(typeof(DesignerCategoryAttribute).FullName, new CodeAttributeArgument[] { new CodeAttributeArgument(new CodePrimitiveExpression("code")) }));
}
else if (Style == ServiceDescriptionImportStyle.Server) {
CodeAttributeDeclaration webService = new CodeAttributeDeclaration(typeof(WebServiceAttribute).FullName);
string targetNs = Service != null ? Service.ServiceDescription.TargetNamespace : Binding.ServiceDescription.TargetNamespace;
webService.Arguments.Add(new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(targetNs)));
codeClass.CustomAttributes.Add(webService);
}
CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(typeof(WebServiceBindingAttribute).FullName);
attribute.Arguments.Add(new CodeAttributeArgument("Name", new CodePrimitiveExpression(XmlConvert.DecodeName(Binding.Name))));
attribute.Arguments.Add(new CodeAttributeArgument("Namespace", new CodePrimitiveExpression(Binding.ServiceDescription.TargetNamespace)));
codeClass.CustomAttributes.Add(attribute);
codeClasses.Add(codeClass);
classHeaders.Clear();
return codeClass;
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.EndClass"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
protected override void EndClass() {
if (transport != null)
transport.ImportClass();
soapBinding = null;
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.IsOperationFlowSupported"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
protected override bool IsOperationFlowSupported(OperationFlow flow) {
return flow == OperationFlow.OneWay || flow == OperationFlow.RequestResponse;
}
void BeginMetadata() {
propertyNames.Clear();
propertyValues.Clear();
}
bool MetadataPropertiesAdded {
get { return propertyNames.Count > 0; }
}
void AddMetadataProperty(string name, object value) {
AddMetadataProperty(name, new CodePrimitiveExpression(value));
}
void AddMetadataProperty(string name, CodeExpression expr) {
propertyNames.Add(name);
propertyValues.Add(expr);
}
void EndMetadata(CodeAttributeDeclarationCollection metadata, Type attributeType, string parameter) {
CodeExpression[] parameters;
if (parameter == null) {
parameters = new CodeExpression[0];
}
else {
parameters = new CodeExpression[1] { new CodePrimitiveExpression(parameter) };
}
WebCodeGenerator.AddCustomAttribute(metadata, attributeType, parameters,
(string[])propertyNames.ToArray(typeof(string)),
(CodeExpression[])propertyValues.ToArray(typeof(CodeExpression)));
}
void GenerateExtensionMetadata(CodeAttributeDeclarationCollection metadata) {
if (extensions == null) {
TypeElementCollection extensionTypes = WebServicesSection.Current.SoapExtensionImporterTypes;
extensions = new SoapExtensionImporter[extensionTypes.Count];
for (int i = 0; i < extensions.Length; i++) {
SoapExtensionImporter extension = (SoapExtensionImporter)Activator.CreateInstance(extensionTypes[i].Type);
extension.ImportContext = this;
extensions[i] = extension;
}
}
foreach (SoapExtensionImporter extension in extensions) {
extension.ImportMethod(metadata);
}
}
void PrepareHeaders(MessageBinding messageBinding) {
// By default, map all headers to properties on the generated class
// ExtensionImporters can modify this behavior by clearing the flag
SoapHeaderBinding[] headers = (SoapHeaderBinding[])messageBinding.Extensions.FindAll(typeof(SoapHeaderBinding));
foreach (SoapHeaderBinding header in headers) {
header.MapToProperty = true;
}
}
void GenerateHeaders(CodeAttributeDeclarationCollection metadata, SoapBindingUse use, bool rpc, MessageBinding requestMessage, MessageBinding responseMessage) {
Hashtable localHeaders = new Hashtable();
for (int i = 0; i < 2; ++i) {
MessageBinding messageBinding;
SoapHeaderDirection direction;
if (i == 0) {
messageBinding = requestMessage;
direction = SoapHeaderDirection.In;
}
else if (responseMessage != null) {
messageBinding = responseMessage;
direction = SoapHeaderDirection.Out;
}
else
continue;
SoapHeaderBinding[] headerBindings = (SoapHeaderBinding[])messageBinding.Extensions.FindAll(typeof(SoapHeaderBinding));
foreach (SoapHeaderBinding header in headerBindings) {
// Skip headers which should not be mapped to properties (extension importers can control this)
if (!header.MapToProperty) continue;
if (use != header.Use) throw new InvalidOperationException(Res.GetString(Res.WebDescriptionHeaderAndBodyUseMismatch));
if (use == SoapBindingUse.Encoded && !IsSoapEncodingPresent(header.Encoding) )
throw new InvalidOperationException(Res.GetString(Res.WebUnknownEncodingStyle, header.Encoding));
Message message = ServiceDescriptions.GetMessage(header.Message);
if (message == null) throw new InvalidOperationException(Res.GetString(Res.MissingMessage2, header.Message.Name, header.Message.Namespace));
MessagePart part = message.FindPartByName(header.Part);
if (part == null) throw new InvalidOperationException(Res.GetString(Res.MissingMessagePartForMessageFromNamespace3, part.Name, header.Message.Name, header.Message.Namespace));
XmlTypeMapping mapping;
string key;
if (use == SoapBindingUse.Encoded) {
if (part.Type.IsEmpty) throw new InvalidOperationException(Res.GetString(Res.WebDescriptionPartTypeRequired, part.Name, header.Message.Name, header.Message.Namespace));
if (!part.Element.IsEmpty) UnsupportedOperationBindingWarning(Res.GetString(Res.WebDescriptionPartElementWarning, part.Name, header.Message.Name, header.Message.Namespace));
mapping = soapImporter.ImportDerivedTypeMapping(part.Type, typeof(SoapHeader), true);
key = "type=" + part.Type.ToString();
}
else {
if (part.Element.IsEmpty) throw new InvalidOperationException(Res.GetString(Res.WebDescriptionPartElementRequired, part.Name, header.Message.Name, header.Message.Namespace));
if (!part.Type.IsEmpty) UnsupportedOperationBindingWarning(Res.GetString(Res.WebDescriptionPartTypeWarning, part.Name, header.Message.Name, header.Message.Namespace));
mapping = xmlImporter.ImportDerivedTypeMapping(part.Element, typeof(SoapHeader), true);
key = "element=" + part.Element.ToString();
}
LocalSoapHeader localHeader = (LocalSoapHeader)localHeaders[key];
if (localHeader == null) {
GlobalSoapHeader globalHeader = (GlobalSoapHeader)classHeaders[key];
if (globalHeader == null) {
globalHeader = new GlobalSoapHeader();
globalHeader.isEncoded = use == SoapBindingUse.Encoded;
string fieldName = CodeIdentifier.MakeValid(mapping.ElementName);
if (fieldName == mapping.TypeName) fieldName += "Value";
fieldName = MethodNames.AddUnique(fieldName, mapping);
globalHeader.fieldName = fieldName;
WebCodeGenerator.AddMember(CodeTypeDeclaration, mapping.TypeFullName, globalHeader.fieldName, null, null, CodeFlags.IsPublic, ServiceImporter.CodeGenerationOptions);
globalHeader.mapping = mapping;
classHeaders.Add(key, globalHeader);
if (headers[key] == null)
headers.Add(key, globalHeader);
}
localHeader = new LocalSoapHeader();
localHeader.fieldName = globalHeader.fieldName;
localHeader.direction = direction;
localHeaders.Add(key, localHeader);
}
else {
if (localHeader.direction != direction)
localHeader.direction = SoapHeaderDirection.InOut;
}
}
}
foreach (LocalSoapHeader soapHeader in localHeaders.Values) {
BeginMetadata();
if (soapHeader.direction == SoapHeaderDirection.Out) {
AddMetadataProperty("Direction", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapHeaderDirection).FullName), SoapHeaderDirection.Out.ToString()));
}
else if (soapHeader.direction == SoapHeaderDirection.InOut) {
AddMetadataProperty("Direction", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapHeaderDirection).FullName), SoapHeaderDirection.InOut.ToString()));
}
EndMetadata(metadata, typeof(SoapHeaderAttribute), soapHeader.fieldName);
}
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.GenerateMethod"]/*' />
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
protected override CodeMemberMethod GenerateMethod() {
Message requestMessage;
Message responseMessage;
string[] parameterOrder;
SoapBodyBinding soapRequestBinding;
SoapBodyBinding soapResponseBinding;
MessageBinding requestBinding;
MessageBinding responseBinding;
SoapOperationBinding soapOperationBinding = (SoapOperationBinding)this.OperationBinding.Extensions.Find(typeof(SoapOperationBinding));
if (soapOperationBinding == null) throw OperationBindingSyntaxException(Res.GetString(Res.MissingSoapOperationBinding0));
SoapBindingStyle soapBindingStyle = soapOperationBinding.Style;
if (soapBindingStyle == SoapBindingStyle.Default)
soapBindingStyle = SoapBinding.Style;
if (soapBindingStyle == SoapBindingStyle.Default)
soapBindingStyle = SoapBindingStyle.Document;
parameterOrder = this.Operation.ParameterOrder;
requestMessage = this.InputMessage;
requestBinding = this.OperationBinding.Input;
soapRequestBinding = (SoapBodyBinding)this.OperationBinding.Input.Extensions.Find(typeof(SoapBodyBinding));
if (soapRequestBinding == null) {
UnsupportedOperationBindingWarning(Res.GetString(Res.MissingSoapBodyInputBinding0));
return null;
}
if (this.Operation.Messages.Output != null) {
responseMessage = this.OutputMessage;
responseBinding = this.OperationBinding.Output;
soapResponseBinding = (SoapBodyBinding)this.OperationBinding.Output.Extensions.Find(typeof(SoapBodyBinding));
if (soapResponseBinding == null) {
UnsupportedOperationBindingWarning(Res.GetString(Res.MissingSoapBodyOutputBinding0));
return null;
}
}
else {
responseMessage = null;
responseBinding = null;
soapResponseBinding = null;
}
CodeAttributeDeclarationCollection metadata = new CodeAttributeDeclarationCollection();
PrepareHeaders(requestBinding);
if (responseBinding != null) PrepareHeaders(responseBinding);
string requestMessageName;
string responseMessageName = null;
requestMessageName = !String.IsNullOrEmpty(requestBinding.Name) && soapBindingStyle != SoapBindingStyle.Rpc ? requestBinding.Name : this.Operation.Name; // per WSDL 1.1 sec 3.5
requestMessageName = XmlConvert.DecodeName(requestMessageName);
if (responseBinding != null) {
responseMessageName = !String.IsNullOrEmpty(responseBinding.Name) && soapBindingStyle != SoapBindingStyle.Rpc ? responseBinding.Name : this.Operation.Name + "Response"; // per WSDL 1.1 sec 3.5
responseMessageName = XmlConvert.DecodeName(responseMessageName);
}
GenerateExtensionMetadata(metadata);
GenerateHeaders(metadata, soapRequestBinding.Use, soapBindingStyle == SoapBindingStyle.Rpc, requestBinding, responseBinding);
MessagePart[] requestParts = GetMessageParts(requestMessage, soapRequestBinding);
bool hasWrapper;
if (!CheckMessageStyles(MethodName, requestParts, soapRequestBinding, soapBindingStyle, out hasWrapper))
return null;
MessagePart[] responseParts = null;
if (responseMessage != null) {
responseParts = GetMessageParts(responseMessage, soapResponseBinding);
bool responseHasWrapper;
if (!CheckMessageStyles(MethodName, responseParts, soapResponseBinding, soapBindingStyle, out responseHasWrapper))
return null;
// since we're using a potentially inaccurate heuristic to determine whether there's a wrapper,
// if we disagree about the request and response we should assume there isn't a wrapper.
if (hasWrapper != responseHasWrapper)
hasWrapper = false;
}
bool wrapperNamesMatter = (soapBindingStyle != SoapBindingStyle.Rpc && hasWrapper) || (soapRequestBinding.Use == SoapBindingUse.Literal && soapBindingStyle == SoapBindingStyle.Rpc);
XmlMembersMapping request = ImportMessage(requestMessageName, requestParts, soapRequestBinding, soapBindingStyle, hasWrapper);
if (request == null) return null;
XmlMembersMapping response = null;
if (responseMessage != null) {
response = ImportMessage(responseMessageName, responseParts, soapResponseBinding, soapBindingStyle, hasWrapper);
if (response == null) return null;
}
string methodName = CodeIdentifier.MakeValid(XmlConvert.DecodeName(this.Operation.Name));
if (ClassName == methodName) {
methodName = "Call" + methodName;
}
string uniqueMethodName = MethodNames.AddUnique(CodeIdentifier.MakeValid(XmlConvert.DecodeName(methodName)), this.Operation);
bool differentNames = methodName != uniqueMethodName;
CodeIdentifiers localIdentifiers = new CodeIdentifiers(false);
localIdentifiers.AddReserved(uniqueMethodName);
SoapParameters parameters = new SoapParameters(request, response, parameterOrder, MethodNames);
foreach (SoapParameter param in parameters.Parameters) {
if ((param.IsOut || param.IsByRef) && !ServiceImporter.CodeGenerator.Supports(GeneratorSupport.ReferenceParameters)) {
UnsupportedOperationWarning(Res.GetString(Res.CodeGenSupportReferenceParameters, ServiceImporter.CodeGenerator.GetType().Name));
return null;
}
param.name = localIdentifiers.AddUnique(param.name, null);
if (param.mapping.CheckSpecified)
param.specifiedName = localIdentifiers.AddUnique(param.name + "Specified", null);
}
if (!(Style == ServiceDescriptionImportStyle.Client) || differentNames) {
BeginMetadata();
if (differentNames) AddMetadataProperty("MessageName", uniqueMethodName);
EndMetadata(metadata, typeof(WebMethodAttribute), null);
}
BeginMetadata();
if (wrapperNamesMatter && request.ElementName.Length > 0 && request.ElementName != uniqueMethodName)
AddMetadataProperty("RequestElementName", request.ElementName);
if (request.Namespace != null)
AddMetadataProperty("RequestNamespace", request.Namespace);
if (response == null) {
AddMetadataProperty("OneWay", true);
}
else {
if (wrapperNamesMatter && response.ElementName.Length > 0 && response.ElementName != (uniqueMethodName + "Response"))
AddMetadataProperty("ResponseElementName", response.ElementName);
if (response.Namespace != null)
AddMetadataProperty("ResponseNamespace", response.Namespace);
}
if (soapBindingStyle == SoapBindingStyle.Rpc) {
if (soapRequestBinding.Use != SoapBindingUse.Encoded) {
AddMetadataProperty("Use", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapBindingUse).FullName), Enum.Format(typeof(SoapBindingUse), soapRequestBinding.Use, "G")));
}
EndMetadata(metadata, typeof(SoapRpcMethodAttribute), soapOperationBinding.SoapAction);
}
else {
AddMetadataProperty("Use", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapBindingUse).FullName), Enum.Format(typeof(SoapBindingUse), soapRequestBinding.Use, "G")));
AddMetadataProperty("ParameterStyle", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(SoapParameterStyle).FullName), Enum.Format(typeof(SoapParameterStyle), hasWrapper ? SoapParameterStyle.Wrapped : SoapParameterStyle.Bare, "G")));
EndMetadata(metadata, typeof(SoapDocumentMethodAttribute), soapOperationBinding.SoapAction);
}
IsEncodedBinding = IsEncodedBinding || (soapRequestBinding.Use == SoapBindingUse.Encoded);
CodeAttributeDeclarationCollection[] paramsMetadata = new CodeAttributeDeclarationCollection[parameters.Parameters.Count + parameters.CheckSpecifiedCount];
int j = 0;
CodeAttributeDeclaration ignoreAttribute = new CodeAttributeDeclaration(typeof(XmlIgnoreAttribute).FullName);
foreach (SoapParameter parameter in parameters.Parameters) {
paramsMetadata[j] = new CodeAttributeDeclarationCollection();
if (soapRequestBinding.Use == SoapBindingUse.Encoded)
soapExporter.AddMappingMetadata(paramsMetadata[j], parameter.mapping, parameter.name != parameter.mapping.MemberName);
else {
string ns = soapBindingStyle == SoapBindingStyle.Rpc ? parameter.mapping.Namespace : parameter.IsOut ? response.Namespace : request.Namespace;
bool forceUseMemberName = parameter.name != parameter.mapping.MemberName;
xmlExporter.AddMappingMetadata(paramsMetadata[j], parameter.mapping, ns, forceUseMemberName);
if (parameter.mapping.CheckSpecified) {
j++;
paramsMetadata[j] = new CodeAttributeDeclarationCollection();
xmlExporter.AddMappingMetadata(paramsMetadata[j], parameter.mapping, ns, parameter.specifiedName != parameter.mapping.MemberName + "Specified");
paramsMetadata[j].Add(ignoreAttribute);
}
}
if (paramsMetadata[j].Count > 0 && !ServiceImporter.CodeGenerator.Supports(GeneratorSupport.ParameterAttributes)) {
UnsupportedOperationWarning(Res.GetString(Res.CodeGenSupportParameterAttributes, ServiceImporter.CodeGenerator.GetType().Name));
return null;
}
j++;
}
CodeFlags[] parameterFlags = SoapParameter.GetCodeFlags(parameters.Parameters, parameters.CheckSpecifiedCount);
string[] parameterTypes = SoapParameter.GetTypeFullNames(parameters.Parameters, parameters.CheckSpecifiedCount, ServiceImporter.CodeGenerator);
string returnType = parameters.Return == null ? typeof(void).FullName : WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator);
CodeMemberMethod mainCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, methodName,
parameterFlags,
parameterTypes,
SoapParameter.GetNames(parameters.Parameters, parameters.CheckSpecifiedCount),
paramsMetadata,
returnType,
metadata,
CodeFlags.IsPublic | (Style == ServiceDescriptionImportStyle.Client ? 0 : CodeFlags.IsAbstract));
mainCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
if (parameters.Return != null) {
if (soapRequestBinding.Use == SoapBindingUse.Encoded)
soapExporter.AddMappingMetadata(mainCodeMethod.ReturnTypeCustomAttributes, parameters.Return, parameters.Return.ElementName != uniqueMethodName + "Result");
else
xmlExporter.AddMappingMetadata(mainCodeMethod.ReturnTypeCustomAttributes, parameters.Return, response.Namespace, parameters.Return.ElementName != uniqueMethodName + "Result");
if (mainCodeMethod.ReturnTypeCustomAttributes.Count != 0 && !ServiceImporter.CodeGenerator.Supports(GeneratorSupport.ReturnTypeAttributes)) {
UnsupportedOperationWarning(Res.GetString(Res.CodeGenSupportReturnTypeAttributes, ServiceImporter.CodeGenerator.GetType().Name));
return null;
}
}
string resultsName = localIdentifiers.MakeUnique("results");
if (Style == ServiceDescriptionImportStyle.Client) {
bool oldAsync = (ServiceImporter.CodeGenerationOptions & CodeGenerationOptions.GenerateOldAsync) != 0;
bool newAsync = (ServiceImporter.CodeGenerationOptions & CodeGenerationOptions.GenerateNewAsync) != 0 &&
ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareEvents) &&
ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareDelegates);
CodeExpression[] invokeParams = new CodeExpression[2];
CreateInvokeParams(invokeParams, uniqueMethodName, parameters.InParameters, parameters.InCheckSpecifiedCount);
CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "Invoke", invokeParams);
WriteReturnMappings(mainCodeMethod, invoke, parameters, resultsName);
if (oldAsync) {
int inCount = parameters.InParameters.Count + parameters.InCheckSpecifiedCount;
string[] asyncParameterTypes = new string[inCount + 2];
SoapParameter.GetTypeFullNames(parameters.InParameters, asyncParameterTypes, 0, parameters.InCheckSpecifiedCount, ServiceImporter.CodeGenerator);
asyncParameterTypes[inCount] = typeof(AsyncCallback).FullName;
asyncParameterTypes[inCount + 1] = typeof(object).FullName;
string[] asyncParameterNames = new string[inCount + 2];
SoapParameter.GetNames(parameters.InParameters, asyncParameterNames, 0, parameters.InCheckSpecifiedCount);
asyncParameterNames[inCount] = "callback";
asyncParameterNames[inCount + 1] = "asyncState";
CodeFlags[] asyncParameterFlags = new CodeFlags[inCount + 2];
CodeMemberMethod beginCodeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, "Begin" + uniqueMethodName,
asyncParameterFlags,
asyncParameterTypes,
asyncParameterNames,
typeof(IAsyncResult).FullName,
null,
CodeFlags.IsPublic);
beginCodeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
invokeParams = new CodeExpression[4];
CreateInvokeParams(invokeParams, uniqueMethodName, parameters.InParameters, parameters.InCheckSpecifiedCount);
invokeParams[2] = new CodeArgumentReferenceExpression("callback");
invokeParams[3] = new CodeArgumentReferenceExpression("asyncState");
invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "BeginInvoke", invokeParams);
beginCodeMethod.Statements.Add(new CodeMethodReturnStatement(invoke));
int outCount = parameters.OutParameters.Count + parameters.OutCheckSpecifiedCount;
string[] asyncReturnTypes = new string[outCount + 1];
SoapParameter.GetTypeFullNames(parameters.OutParameters, asyncReturnTypes, 1, parameters.OutCheckSpecifiedCount, ServiceImporter.CodeGenerator);
asyncReturnTypes[0] = typeof(IAsyncResult).FullName;
string[] asyncReturnNames = new string[outCount + 1];
SoapParameter.GetNames(parameters.OutParameters, asyncReturnNames, 1, parameters.OutCheckSpecifiedCount);
asyncReturnNames[0] = "asyncResult";
CodeFlags[] asyncReturnFlags = new CodeFlags[outCount + 1];
for (int i = 0; i < outCount; i++)
asyncReturnFlags[i + 1] = CodeFlags.IsOut;
CodeMemberMethod codeMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, "End" + uniqueMethodName,
asyncReturnFlags,
asyncReturnTypes,
asyncReturnNames,
parameters.Return == null ? typeof(void).FullName : WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator),
null,
CodeFlags.IsPublic);
codeMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
CodeExpression invokeParam = new CodeArgumentReferenceExpression("asyncResult");
invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "EndInvoke", new CodeExpression[] { invokeParam });
WriteReturnMappings(codeMethod, invoke, parameters, resultsName);
}
// new RAD Async pattern
if (newAsync) {
string methodKey = MethodSignature(uniqueMethodName, returnType, parameterFlags, parameterTypes);
DelegateInfo delegateInfo = (DelegateInfo)ExportContext[methodKey];
if (delegateInfo == null) {
string handlerType = ClassNames.AddUnique(uniqueMethodName + "CompletedEventHandler", uniqueMethodName);
string handlerArgs = ClassNames.AddUnique(uniqueMethodName + "CompletedEventArgs", uniqueMethodName);
delegateInfo = new DelegateInfo(handlerType, handlerArgs);
}
string handlerName = MethodNames.AddUnique(uniqueMethodName + "Completed", uniqueMethodName);
string asyncName = MethodNames.AddUnique(uniqueMethodName + "Async", uniqueMethodName);
string callbackMember = MethodNames.AddUnique(uniqueMethodName + "OperationCompleted", uniqueMethodName);
string callbackName = MethodNames.AddUnique("On" + uniqueMethodName + "OperationCompleted", uniqueMethodName);
// public event xxxCompletedEventHandler xxxCompleted;
WebCodeGenerator.AddEvent(this.CodeTypeDeclaration.Members, delegateInfo.handlerType, handlerName);
// private SendOrPostCallback xxxOperationCompleted;
WebCodeGenerator.AddCallbackDeclaration(this.CodeTypeDeclaration.Members, callbackMember);
// create the pair of xxxAsync methods
string[] inParamNames = SoapParameter.GetNames(parameters.InParameters, parameters.InCheckSpecifiedCount);
string userState = UniqueName("userState", inParamNames);
CodeMemberMethod asyncCodeMethod = WebCodeGenerator.AddAsyncMethod(this.CodeTypeDeclaration, asyncName,
SoapParameter.GetTypeFullNames(parameters.InParameters, parameters.InCheckSpecifiedCount, ServiceImporter.CodeGenerator), inParamNames, callbackMember, callbackName, userState);
// Generate InvokeAsync call
invokeParams = new CodeExpression[4];
CreateInvokeParams(invokeParams, uniqueMethodName, parameters.InParameters, parameters.InCheckSpecifiedCount);
invokeParams[2] = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), callbackMember);
invokeParams[3] = new CodeArgumentReferenceExpression(userState);
invoke = new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "InvokeAsync", invokeParams);
asyncCodeMethod.Statements.Add(invoke);
// private void On_xxx_OperationCompleted(object arg) {..}
bool methodHasOutParameters = parameters.Return != null || parameters.OutParameters.Count > 0;
WebCodeGenerator.AddCallbackImplementation(this.CodeTypeDeclaration, callbackName, handlerName, delegateInfo.handlerArgs, methodHasOutParameters);
if (ExportContext[methodKey] == null) {
// public delegate void xxxCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs args);
WebCodeGenerator.AddDelegate(ExtraCodeClasses, delegateInfo.handlerType, methodHasOutParameters ? delegateInfo.handlerArgs : typeof(AsyncCompletedEventArgs).FullName);
// Create strongly-typed Args class
if (methodHasOutParameters) {
int outCount = parameters.OutParameters.Count + parameters.OutCheckSpecifiedCount;
string[] asyncReturnTypes = new string[outCount + 1];
SoapParameter.GetTypeFullNames(parameters.OutParameters, asyncReturnTypes, 1, parameters.OutCheckSpecifiedCount, ServiceImporter.CodeGenerator);
asyncReturnTypes[0] = parameters.Return == null ? null : WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator);
string[] asyncReturnNames = new string[outCount + 1];
SoapParameter.GetNames(parameters.OutParameters, asyncReturnNames, 1, parameters.OutCheckSpecifiedCount);
asyncReturnNames[0] = parameters.Return == null ? null : "Result";
ExtraCodeClasses.Add(WebCodeGenerator.CreateArgsClass(delegateInfo.handlerArgs, asyncReturnTypes, asyncReturnNames, ServiceImporter.CodeGenerator.Supports(GeneratorSupport.PartialTypes)));
}
ExportContext[methodKey] = delegateInfo;
}
}
}
return mainCodeMethod;
}
void WriteReturnMappings(CodeMemberMethod codeMethod, CodeExpression invoke, SoapParameters parameters, string resultsName) {
if (parameters.Return == null && parameters.OutParameters.Count == 0) {
codeMethod.Statements.Add(new CodeExpressionStatement(invoke));
}
else {
codeMethod.Statements.Add(new CodeVariableDeclarationStatement(typeof(object[]), resultsName, invoke));
int count = parameters.Return == null ? 0 : 1;
for (int i = 0; i < parameters.OutParameters.Count; i++) {
SoapParameter parameter = (SoapParameter)parameters.OutParameters[i];
CodeExpression target = new CodeArgumentReferenceExpression(parameter.name);
CodeExpression value = new CodeArrayIndexerExpression();
((CodeArrayIndexerExpression)value).TargetObject = new CodeVariableReferenceExpression(resultsName);
((CodeArrayIndexerExpression)value).Indices.Add(new CodePrimitiveExpression(count++));
value = new CodeCastExpression(WebCodeGenerator.FullTypeName(parameter.mapping, ServiceImporter.CodeGenerator), value);
codeMethod.Statements.Add(new CodeAssignStatement(target, value));
if (parameter.mapping.CheckSpecified) {
target = new CodeArgumentReferenceExpression(parameter.name + "Specified");
value = new CodeArrayIndexerExpression();
((CodeArrayIndexerExpression) value).TargetObject = new CodeVariableReferenceExpression(resultsName);
((CodeArrayIndexerExpression)value).Indices.Add(new CodePrimitiveExpression(count++));
value = new CodeCastExpression(typeof(bool).FullName, value);
codeMethod.Statements.Add(new CodeAssignStatement(target, value));
}
}
if (parameters.Return != null) {
CodeExpression value = new CodeArrayIndexerExpression();
((CodeArrayIndexerExpression)value).TargetObject = new CodeVariableReferenceExpression(resultsName);
((CodeArrayIndexerExpression)value).Indices.Add(new CodePrimitiveExpression(0));
value = new CodeCastExpression(WebCodeGenerator.FullTypeName(parameters.Return, ServiceImporter.CodeGenerator), value);
codeMethod.Statements.Add(new CodeMethodReturnStatement(value));
}
}
}
void CreateInvokeParams(CodeExpression[] invokeParams, string methodName, IList parameters, int checkSpecifiedCount) {
invokeParams[0] = new CodePrimitiveExpression(methodName);
CodeExpression[] values = new CodeExpression[parameters.Count + checkSpecifiedCount];
int value = 0;
for (int i = 0; i < parameters.Count; i++) {
SoapParameter parameter = (SoapParameter)parameters[i];
values[value++] = new CodeArgumentReferenceExpression(parameter.name);
if (parameter.mapping.CheckSpecified)
values[value++] = new CodeArgumentReferenceExpression(parameter.specifiedName);
}
invokeParams[1] = new CodeArrayCreateExpression(typeof(object).FullName, values);
}
// returns false if we didn't like the message -- otherwise caller is safe to use body binding and binding style
bool CheckMessageStyles(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle, out bool hasWrapper) {
hasWrapper = false;
if (soapBodyBinding.Use == SoapBindingUse.Default) {
soapBodyBinding.Use = SoapBindingUse.Literal;
}
if (soapBodyBinding.Use == SoapBindingUse.Literal) {
if (soapBindingStyle == SoapBindingStyle.Rpc) {
foreach (MessagePart part in parts) {
if (!part.Element.IsEmpty) {
UnsupportedOperationBindingWarning(Res.GetString(Res.EachMessagePartInRpcUseLiteralMessageMustSpecify0));
return false;
}
}
return true;
}
if (parts.Length == 1 && !parts[0].Type.IsEmpty) {
// special top-level any case
if (!parts[0].Element.IsEmpty) {
UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingATypeForUseLiteralMessagesIs0));
return false;
}
XmlMembersMapping membersMapping = xmlImporter.ImportAnyType(parts[0].Type, parts[0].Name);
if (membersMapping == null) {
UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingATypeForUseLiteralMessagesIsAny, parts[0].Type.Name, parts[0].Type.Namespace));
return false;
}
return true;
}
else {
foreach (MessagePart part in parts) {
if (!part.Type.IsEmpty) {
UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingATypeForUseLiteralMessagesIs0));
return false;
}
if (part.Element.IsEmpty) {
UnsupportedOperationBindingWarning(Res.GetString(Res.EachMessagePartInAUseLiteralMessageMustSpecify0));
return false;
}
}
}
}
else if (soapBodyBinding.Use == SoapBindingUse.Encoded) {
if (!IsSoapEncodingPresent(soapBodyBinding.Encoding)) {
UnsupportedOperationBindingWarning(Res.GetString(Res.TheEncodingIsNotSupported1, soapBodyBinding.Encoding));
return false;
}
foreach (MessagePart part in parts) {
if (!part.Element.IsEmpty) {
UnsupportedOperationBindingWarning(Res.GetString(Res.SpecifyingAnElementForUseEncodedMessageParts0));
return false;
}
if (part.Type.IsEmpty) {
UnsupportedOperationBindingWarning(Res.GetString(Res.EachMessagePartInAnUseEncodedMessageMustSpecify0));
return false;
}
}
}
if (soapBindingStyle == SoapBindingStyle.Rpc) {
return true;
}
else if (soapBindingStyle == SoapBindingStyle.Document) {
// NOTE, Microsoft. WSDL doesn't really let us figure out whether a document is
// in fact a struct containing parameters, so we apply a little heuristic here
// in order to produce the appropriate programming model.
hasWrapper = (parts.Length == 1 && string.Compare(parts[0].Name, "parameters", StringComparison.Ordinal) == 0);
return true;
}
return false;
}
/// <include file='doc\SoapProtocolImporter.uex' path='docs/doc[@for="SoapProtocolImporter.IsSoapEncodingPresent"]/*' />
/// <internalonly/>
protected virtual bool IsSoapEncodingPresent(string uriList) {
int iStart = 0;
do {
iStart = uriList.IndexOf(Soap.Encoding, iStart, StringComparison.Ordinal);
if (iStart < 0)
return false;
int iEnd = iStart + Soap.Encoding.Length;
if (iStart == 0 || uriList[iStart - 1] == ' ')
if (iEnd == uriList.Length || uriList[iEnd] == ' ')
return true;
iStart = iEnd;
} while (iStart < uriList.Length);
return false;
}
MessagePart[] GetMessageParts(Message message, SoapBodyBinding soapBodyBinding) {
MessagePart[] parts;
if (soapBodyBinding.Parts == null) {
parts = new MessagePart[message.Parts.Count];
message.Parts.CopyTo(parts, 0);
}
else {
parts = message.FindPartsByName(soapBodyBinding.Parts);
}
return parts;
}
XmlMembersMapping ImportMessage(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle, bool wrapped) {
if (soapBodyBinding.Use == SoapBindingUse.Encoded)
return ImportEncodedMessage(messageName, parts, soapBodyBinding, wrapped);
else
return ImportLiteralMessage(messageName, parts, soapBodyBinding, soapBindingStyle, wrapped);
}
XmlMembersMapping ImportEncodedMessage(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, bool wrapped) {
XmlMembersMapping membersMapping;
if (wrapped) {
SoapSchemaMember schemaMember = new SoapSchemaMember();
schemaMember.MemberName = parts[0].Name;
schemaMember.MemberType = parts[0].Type;
membersMapping = soapImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, schemaMember);
}
else {
SoapSchemaMember[] schemaMembers = new SoapSchemaMember[parts.Length];
for (int i = 0; i < schemaMembers.Length; i++) {
MessagePart part = parts[i];
SoapSchemaMember schemaMember = new SoapSchemaMember();
schemaMember.MemberName = part.Name;
schemaMember.MemberType = part.Type;
schemaMembers[i] = schemaMember;
}
membersMapping = soapImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, schemaMembers);
}
soapMembers.Add(membersMapping);
return membersMapping;
}
XmlMembersMapping ImportLiteralMessage(string messageName, MessagePart[] parts, SoapBodyBinding soapBodyBinding, SoapBindingStyle soapBindingStyle, bool wrapped) {
XmlMembersMapping membersMapping;
if (soapBindingStyle == SoapBindingStyle.Rpc) {
SoapSchemaMember[] schemaMembers = new SoapSchemaMember[parts.Length];
for (int i = 0; i < schemaMembers.Length; i++) {
MessagePart part = parts[i];
SoapSchemaMember schemaMember = new SoapSchemaMember();
schemaMember.MemberName = part.Name;
schemaMember.MemberType = part.Type;
schemaMembers[i] = schemaMember;
}
membersMapping = xmlImporter.ImportMembersMapping(messageName, soapBodyBinding.Namespace, schemaMembers);
}
else if (wrapped) {
membersMapping = xmlImporter.ImportMembersMapping(parts[0].Element);
}
else {
if (parts.Length == 1 && !parts[0].Type.IsEmpty) {
// special case for <any> at root
// we know this will work because we tried it earlier in CheckMessageStyles.
membersMapping = xmlImporter.ImportAnyType(parts[0].Type, parts[0].Name);
xmlMembers.Add(membersMapping);
return membersMapping;
}
XmlQualifiedName[] names = new XmlQualifiedName[parts.Length];
for (int i = 0; i < parts.Length; i++)
names[i] = parts[i].Element;
membersMapping = xmlImporter.ImportMembersMapping(names);
}
xmlMembers.Add(membersMapping);
return membersMapping;
}
}
}
|