目前我们遇到WCF问题并生成singleWsdl。
我们创建了一个可以将标头添加到wcf服务的行为。 这个名为IncomingHeaderBehavior的行为实现了IWsdlExportExtension和ExportEndpoint方法。此方法加载Header xsd并将其添加到wsdl。 (代码包含在附件中)。
结果: 生成的wsdl包含下面显示的标头定义,但singleWsdl不包含。
<xsd:schema targetNamespace="http://www.randomsite.nl/Header">
<xsd:element name="Header">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="rgh:HeaderVersion"/>
<xsd:element ref="rgh:MessageId"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="HeaderVersion">
<xsd:annotation>
<xsd:documentation>Version of the header</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="MessageId">
<xsd:annotation>
<xsd:documentation>Id of the message</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="30"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:schema>
SoapUI为wsdl生成以下请求:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:head="http://www.randomsite.nl/Header" xmlns:ser="http://www.asite.com/Service1/">
<soapenv:Header>
<head:Header>
<head:HeaderVersion>?</head:HeaderVersion>
<head:MessageId>?</head:MessageId>
</head:Header>
</soapenv:Header>
<soapenv:Body>
<ser:GetData>
<!--Optional:-->
<ser:value>?</ser:value>
</ser:GetData>
</soapenv:Body>
</soapenv:Envelope>
如您所见,SingleWSDL的标头中缺少HeaderVersion和MessageId字段,但我不知道如何解决这个问题。
此处的附件是相关的代码段:Complete code example
行为延伸:
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Xml.Linq;
namespace WcfHeaderBehaviorLibrary
{
public class IncomingHeaderBehavior : BehaviorExtensionElement, IDispatchMessageInspector, IEndpointBehavior, IWsdlExportExtension
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
var messageHeaders = request.Headers;
HeaderInput headerInput;
try
{
headerInput = messageHeaders.GetHeader<HeaderInput>("HeaderName", ServiceMetadata.HEADER_NAMESPACE);
}
catch (Exception)
{
return null;
}
return headerInput;
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
if (correlationState != null)
{
var state = (HeaderInput)correlationState;
var headerInput = new HeaderInput
{
HeaderVersion = VersionService.HeaderVersion,
MessageId = state.MessageId,
};
var header = MessageHeader.CreateHeader("HeaderName", ServiceMetadata.HEADER_NAMESPACE, headerInput);
reply.Headers.Add(header);
}
}
public void Validate(ServiceEndpoint endpoint)
{
}
protected override object CreateBehavior()
{
return this;
}
public override Type BehaviorType
{
get { return GetType(); }
}
public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
{
}
public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
{
IncomingWsdlExport.ExportEndpoint(exporter, context);
}
}
}
WSDLExport类:
using System;
using System.Reflection;
using System.ServiceModel.Description;
using System.Web.Services.Description;
using System.Xml;
using System.Xml.Schema;
using ServiceDescription = System.Web.Services.Description.ServiceDescription;
namespace WcfHeaderBehaviorLibrary
{
public class IncomingWsdlExport
{
public static void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
{
var headerXsd = Assembly.GetExecutingAssembly().GetManifestResourceStream("WcfHeaderBehaviorLibrary.xsd.Header.xsd");
var customSoapHeaderSchema = XmlSchema.Read(headerXsd, ValidationCallBack);
var headerMessage = CreateHeaderMessage(customSoapHeaderSchema);
foreach (ServiceDescription wsdl in exporter.GeneratedWsdlDocuments)
{
wsdl.Types.Schemas.Add(customSoapHeaderSchema);
wsdl.Namespaces.Add("rgh", customSoapHeaderSchema.TargetNamespace);
wsdl.Messages.Add(headerMessage);
}
AddHeaderToOperations(headerMessage, context);
}
private static Message CreateHeaderMessage(XmlSchema customSoapHeaderSchema)
{
var headerMessage = new Message { Name = "Header" };
var part = new MessagePart
{
Name = "header",
Element = new XmlQualifiedName("Header", customSoapHeaderSchema.TargetNamespace)
};
headerMessage.Parts.Add(part);
return headerMessage;
}
private static void AddHeaderToOperations(Message headerMessage, WsdlEndpointConversionContext context)
{
var header = new XmlQualifiedName(headerMessage.Name, headerMessage.ServiceDescription.TargetNamespace);
foreach (OperationBinding operation in context.WsdlBinding.Operations)
{
ExportMessageHeaderBinding(operation.Input, header, false);
ExportMessageHeaderBinding(operation.Output, header, false);
}
}
private static void ExportMessageHeaderBinding(MessageBinding messageBinding, XmlQualifiedName header, bool isEncoded)
{
var binding = new Soap12HeaderBinding
{
Part = "header",
Message = header,
Use = isEncoded ? SoapBindingUse.Encoded : SoapBindingUse.Literal
};
messageBinding.Extensions.Add(binding);
}
private static void ValidationCallBack(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
Console.WriteLine("\tWarning: Matching schema not found. No validation occurred." + args.Message);
else
Console.WriteLine("\tValidation error: " + args.Message);
}
}
}