|
//------------------------------------------------------------------------------
// <copyright file="SoapProtocolReflector.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </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.Schema;
using System.Collections;
using System;
using System.Reflection;
using System.Web.Services.Configuration;
internal class SoapProtocolReflector : ProtocolReflector {
// SoapProtocolInfo protocolInfo;
ArrayList mappings = new ArrayList();
SoapExtensionReflector[] extensions;
SoapReflectedMethod soapMethod;
internal override WsiProfiles ConformsTo {
get { return WsiProfiles.BasicProfile1_1; }
}
public override string ProtocolName {
get { return "Soap"; }
}
internal SoapReflectedMethod SoapMethod {
get { return soapMethod; }
}
internal SoapReflectionImporter SoapImporter {
get {
SoapReflectionImporter soapImporter = ReflectionContext[typeof(SoapReflectionImporter)] as SoapReflectionImporter;
if (soapImporter == null) {
soapImporter = SoapReflector.CreateSoapImporter(DefaultNamespace, SoapReflector.ServiceDefaultIsEncoded(ServiceType));
ReflectionContext[typeof(SoapReflectionImporter)] = soapImporter;
}
return soapImporter;
}
}
internal SoapSchemaExporter SoapExporter {
get {
SoapSchemaExporter soapExporter = ReflectionContext[typeof(SoapSchemaExporter)] as SoapSchemaExporter;
if (soapExporter == null) {
soapExporter = new SoapSchemaExporter(ServiceDescription.Types.Schemas);
ReflectionContext[typeof(SoapSchemaExporter)] = soapExporter;
}
return soapExporter;
}
}
protected override bool ReflectMethod() {
soapMethod = ReflectionContext[Method] as SoapReflectedMethod;
if (soapMethod == null) {
soapMethod = SoapReflector.ReflectMethod(Method, false, ReflectionImporter, SoapImporter, DefaultNamespace);
ReflectionContext[Method] = soapMethod;
soapMethod.portType = Binding != null ? Binding.Type : null;
}
WebMethodAttribute methodAttr = Method.MethodAttribute;
OperationBinding.Extensions.Add(CreateSoapOperationBinding(soapMethod.rpc ? SoapBindingStyle.Rpc : SoapBindingStyle.Document, soapMethod.action));
CreateMessage(soapMethod.rpc, soapMethod.use, soapMethod.paramStyle, InputMessage, OperationBinding.Input, soapMethod.requestMappings);
if (!soapMethod.oneWay)
CreateMessage(soapMethod.rpc, soapMethod.use, soapMethod.paramStyle, OutputMessage, OperationBinding.Output, soapMethod.responseMappings);
CreateHeaderMessages(soapMethod.name, soapMethod.use, soapMethod.inHeaderMappings, soapMethod.outHeaderMappings, soapMethod.headers, soapMethod.rpc);
if (soapMethod.rpc && soapMethod.use == SoapBindingUse.Encoded && soapMethod.methodInfo.OutParameters.Length > 0)
Operation.ParameterOrder = GetParameterOrder(soapMethod.methodInfo);
AllowExtensionsToReflectMethod();
return true;
}
protected override void ReflectDescription() {
AllowExtensionsToReflectDescription();
}
void CreateHeaderMessages(string methodName, SoapBindingUse use, XmlMembersMapping inHeaderMappings, XmlMembersMapping outHeaderMappings, SoapReflectedHeader[] headers, bool rpc) {
//
if (use == SoapBindingUse.Encoded) {
SoapExporter.ExportMembersMapping(inHeaderMappings, false);
if (outHeaderMappings != null)
SoapExporter.ExportMembersMapping(outHeaderMappings, false);
}
else {
SchemaExporter.ExportMembersMapping(inHeaderMappings);
if (outHeaderMappings != null)
SchemaExporter.ExportMembersMapping(outHeaderMappings);
}
CodeIdentifiers identifiers = new CodeIdentifiers();
int inCount = 0, outCount = 0;
for (int i = 0; i < headers.Length; i++) {
SoapReflectedHeader soapHeader = headers[i];
if (!soapHeader.custom) continue;
XmlMemberMapping member;
if ((soapHeader.direction & SoapHeaderDirection.In) != 0) {
member = inHeaderMappings[inCount++];
if (soapHeader.direction != SoapHeaderDirection.In)
outCount++;
}
else {
member = outHeaderMappings[outCount++];
}
MessagePart part = new MessagePart();
part.Name = member.XsdElementName;
if (use == SoapBindingUse.Encoded)
part.Type = new XmlQualifiedName(member.TypeName, member.TypeNamespace);
else
part.Element = new XmlQualifiedName(member.XsdElementName, member.Namespace);
Message message = new Message();
message.Name = identifiers.AddUnique(methodName + part.Name, message);
message.Parts.Add(part);
HeaderMessages.Add(message);
ServiceDescriptionFormatExtension soapHeaderBinding = CreateSoapHeaderBinding(new XmlQualifiedName(message.Name, Binding.ServiceDescription.TargetNamespace), part.Name, rpc ? member.Namespace : null, use);
if ((soapHeader.direction & SoapHeaderDirection.In) != 0)
OperationBinding.Input.Extensions.Add(soapHeaderBinding);
if ((soapHeader.direction & SoapHeaderDirection.Out) != 0)
OperationBinding.Output.Extensions.Add(soapHeaderBinding);
if ((soapHeader.direction & SoapHeaderDirection.Fault) != 0) {
if (soapMethod.IsClaimsConformance) {
throw new InvalidOperationException(Res.GetString(Res.BPConformanceHeaderFault, soapMethod.methodInfo.ToString(), soapMethod.methodInfo.DeclaringType.FullName, "Direction", typeof(SoapHeaderDirection).Name, SoapHeaderDirection.Fault.ToString()));
}
OperationBinding.Output.Extensions.Add(soapHeaderBinding);
}
}
}
void CreateMessage(bool rpc, SoapBindingUse use, SoapParameterStyle paramStyle, Message message, MessageBinding messageBinding, XmlMembersMapping members) {
bool wrapped = paramStyle != SoapParameterStyle.Bare;
if (use == SoapBindingUse.Encoded)
CreateEncodedMessage(message, messageBinding, members, wrapped && !rpc);
else
CreateLiteralMessage(message, messageBinding, members, wrapped && !rpc, rpc);
}
void CreateEncodedMessage(Message message, MessageBinding messageBinding, XmlMembersMapping members, bool wrapped) {
SoapExporter.ExportMembersMapping(members, wrapped);
if (wrapped) {
MessagePart part = new MessagePart();
part.Name = "parameters";
part.Type = new XmlQualifiedName(members.TypeName, members.TypeNamespace);
message.Parts.Add(part);
}
else {
for (int i = 0; i < members.Count; i++) {
XmlMemberMapping member = members[i];
MessagePart part = new MessagePart();
part.Name = member.XsdElementName;
part.Type = new XmlQualifiedName(member.TypeName, member.TypeNamespace);
message.Parts.Add(part);
}
}
messageBinding.Extensions.Add(CreateSoapBodyBinding(SoapBindingUse.Encoded, members.Namespace));
}
void CreateLiteralMessage(Message message, MessageBinding messageBinding, XmlMembersMapping members, bool wrapped, bool rpc) {
if (members.Count == 1 && members[0].Any && members[0].ElementName.Length == 0 && !wrapped) {
string typeName = SchemaExporter.ExportAnyType(members[0].Namespace);
MessagePart part = new MessagePart();
part.Name = members[0].MemberName;
part.Type = new XmlQualifiedName(typeName, members[0].Namespace);
message.Parts.Add(part);
}
else {
SchemaExporter.ExportMembersMapping(members, !rpc);
if (wrapped) {
MessagePart part = new MessagePart();
part.Name = "parameters";
part.Element = new XmlQualifiedName(members.XsdElementName, members.Namespace);
message.Parts.Add(part);
}
else {
for (int i = 0; i < members.Count; i++) {
XmlMemberMapping member = members[i];
MessagePart part = new MessagePart();
if (rpc) {
// Generate massage part with the type attribute
if (member.TypeName == null || member.TypeName.Length == 0) {
throw new InvalidOperationException(Res.GetString(Res.WsdlGenRpcLitAnonimousType, Method.DeclaringType.Name, Method.Name, member.MemberName));
}
part.Name = member.XsdElementName;
part.Type = new XmlQualifiedName(member.TypeName, member.TypeNamespace);
}
else {
part.Name = XmlConvert.EncodeLocalName(member.MemberName);
part.Element = new XmlQualifiedName(member.XsdElementName, member.Namespace);
}
message.Parts.Add(part);
}
}
}
messageBinding.Extensions.Add(CreateSoapBodyBinding(SoapBindingUse.Literal, rpc ? members.Namespace : null));
}
static string[] GetParameterOrder(LogicalMethodInfo methodInfo) {
ParameterInfo[] parameters = methodInfo.Parameters;
string[] parameterOrder = new string[parameters.Length];
for (int i = 0; i < parameters.Length; i++) {
parameterOrder[i] = parameters[i].Name;
}
return parameterOrder;
}
protected override string ReflectMethodBinding() {
return SoapReflector.GetSoapMethodBinding(Method);
}
protected override void BeginClass() {
if (Binding != null) {
SoapBindingStyle style;
if (SoapReflector.GetSoapServiceAttribute(ServiceType) is SoapRpcServiceAttribute)
style = SoapBindingStyle.Rpc;
else
style = SoapBindingStyle.Document;
Binding.Extensions.Add(CreateSoapBinding(style));
SoapReflector.IncludeTypes(Methods, SoapImporter);
}
Port.Extensions.Add(CreateSoapAddressBinding(ServiceUrl));
}
void AllowExtensionsToReflectMethod() {
if (extensions == null) {
TypeElementCollection extensionTypes = WebServicesSection.Current.SoapExtensionReflectorTypes;
extensions = new SoapExtensionReflector[extensionTypes.Count];
for (int i = 0; i < extensions.Length; i++) {
SoapExtensionReflector extension = (SoapExtensionReflector)Activator.CreateInstance(extensionTypes[i].Type);
extension.ReflectionContext = this;
extensions[i] = extension;
}
}
foreach (SoapExtensionReflector extension in extensions) {
extension.ReflectMethod();
}
}
void AllowExtensionsToReflectDescription() {
if (extensions == null) {
TypeElementCollection extensionTypes = WebServicesSection.Current.SoapExtensionReflectorTypes;
extensions = new SoapExtensionReflector[extensionTypes.Count];
for (int i = 0; i < extensions.Length; i++) {
SoapExtensionReflector extension = (SoapExtensionReflector)Activator.CreateInstance(extensionTypes[i].Type);
extension.ReflectionContext = this;
extensions[i] = extension;
}
}
foreach (SoapExtensionReflector extension in extensions) {
extension.ReflectDescription();
}
}
protected virtual SoapBinding CreateSoapBinding(SoapBindingStyle style) {
SoapBinding soapBinding = new SoapBinding();
soapBinding.Transport = SoapBinding.HttpTransport;
soapBinding.Style = style;
return soapBinding;
}
protected virtual SoapAddressBinding CreateSoapAddressBinding(string serviceUrl) {
SoapAddressBinding soapAddress = new SoapAddressBinding();
soapAddress.Location = serviceUrl;
if (this.UriFixups != null)
{
this.UriFixups.Add(delegate(Uri current)
{
soapAddress.Location = DiscoveryServerType.CombineUris(current, soapAddress.Location);
});
}
return soapAddress;
}
protected virtual SoapOperationBinding CreateSoapOperationBinding(SoapBindingStyle style, string action) {
SoapOperationBinding soapOperation = new SoapOperationBinding();
soapOperation.SoapAction = action;
soapOperation.Style = style;
return soapOperation;
}
protected virtual SoapBodyBinding CreateSoapBodyBinding(SoapBindingUse use, string ns) {
SoapBodyBinding soapBodyBinding = new SoapBodyBinding();
soapBodyBinding.Use = use;
if (use == SoapBindingUse.Encoded)
soapBodyBinding.Encoding = Soap.Encoding;
soapBodyBinding.Namespace = ns;
return soapBodyBinding;
}
protected virtual SoapHeaderBinding CreateSoapHeaderBinding(XmlQualifiedName message, string partName, SoapBindingUse use) {
return CreateSoapHeaderBinding(message, partName, null, use);
}
protected virtual SoapHeaderBinding CreateSoapHeaderBinding(XmlQualifiedName message, string partName, string ns, SoapBindingUse use) {
SoapHeaderBinding soapHeaderBinding = new SoapHeaderBinding();
soapHeaderBinding.Message = message;
soapHeaderBinding.Part = partName;
soapHeaderBinding.Use = use;
if (use == SoapBindingUse.Encoded) {
soapHeaderBinding.Encoding = Soap.Encoding;
soapHeaderBinding.Namespace = ns;
}
return soapHeaderBinding;
}
}
}
|