WCF WSDL + Nillable属性

我有一个带有Flattened WSDL的WCF服务,而另一端的消费者告诉我nillable =“true”属性正在填充它们。 我尝试在服务合同中设置EmitDefaultValue = false,但我没有注意到行为的任何变化。

不可否认,我从来没有在这个级别深入研究WSDL生成,所以我有点迷失。 也许在下面发布的代码中可能会有一些调整可以解决我的问题? 如果我至少在正确的地方,我会继续调查。

有没有一种简单的方法可以从我的WSDL中删除nillable =“true”属性,这会产生意想不到的后果吗? 谢谢!

public class FlatWsdl : IWsdlExportExtension, IEndpointBehavior { public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context) { XmlSchemaSet schemaSet = exporter.GeneratedXmlSchemas; foreach (ServiceDescription wsdl in exporter.GeneratedWsdlDocuments) { List importsList = new List(); foreach (XmlSchema schema in wsdl.Types.Schemas) { AddImportedSchemas(schema, schemaSet, importsList); } wsdl.Types.Schemas.Clear(); foreach (XmlSchema schema in importsList) { RemoveXsdImports(schema); wsdl.Types.Schemas.Add(schema); } } } ...omitted the rest of FlatWsdl.cs for brevity... } 

没有直接的简单方法来实现这一目标。 你必须使用WsdlExporter自己实现它。 是否会产生意想不到的后果取决于您的意图:-)

编辑:

看看IWSDLExportExtension的MSDN示例。 它将允许您完全按照自己的意愿行事。 不可否认,要做到这一点有点麻烦,但你正朝着正确的方向前进。

在我们搜索了互联网之后,我和我的团队决定采用不同的方法来摆脱nillable =“true”。 我们做了以下事情:

  1. 在应用程序启动期间注册了一个特殊的HttpModule
  2. 该模块为BeginRequest事件注册了一个处理程序。
  3. 在请求WSDL或XSD(通过查看查询字符串进行检查)的情况下,钩子处理程序将使用装饰器(Stream)替换默认的Response.Filter
  4. 该装饰器将缓冲写入的数据,直到到达文档的末尾。
  5. 当所有数据都被写入时,装饰器会根据该数据构建一个XDocument ,并通过该文档进行设置(除其他外,例如添加文档)nillable =“false”。

这一切都非常可爱。

在这里找到了使用Response.Filter的想法。

这是HttpModule:

 public class WsdlInterceptionHttpModule : IHttpModule { public void Init(HttpApplication application) { application.BeginRequest += (sender, e) => { var context = application.Context; if (IsRequestForWsdl(context.Request)) { context.Response.Filter = new WsdlAnnotationsFilterDecorator(context.Response.Filter); } }; } private static bool IsRequestForWsdl(HttpRequest request) { ... } } 

这是WsdlAnnotationsFilterDecorator

 public class WsdlAnnotationsFilterDecorator : Stream { private const string DefinitionsEndOfFileMarker = ""; private const string SchemaEndOfFileMarker = ""; private readonly Stream inputStream; private readonly StringBuilder responseXml = new StringBuilder(); private bool firstWrite = true; private string endOfFileMarker = DefinitionsEndOfFileMarker; public WsdlAnnotationsFilterDecorator(Stream inputStream) { this.inputStream = inputStream; this.responseXml = new StringBuilder(); } public override bool CanRead { get { return true; } } public override bool CanSeek { get { return true; } } public override bool CanWrite { get { return true; } } public override long Length { get { return 0; } } public override long Position { get; set; } public override void Close() { inputStream.Close(); } public override void Flush() { inputStream.Flush(); } public override long Seek(long offset, SeekOrigin origin) { return inputStream.Seek(offset, origin); } public override void SetLength(long length) { inputStream.SetLength(length); } public override int Read(byte[] buffer, int offset, int count) { return inputStream.Read(buffer, offset, count); } public override void Write(byte[] buffer, int offset, int count) { string valueToWrite = UTF8Encoding.UTF8.GetString(buffer, offset, count); SetEndOfFileMarker(valueToWrite); if (!valueToWrite.EndsWith(this.endOfFileMarker)) { responseXml.Append(valueToWrite); } else { responseXml.Append(valueToWrite); string finalXml = responseXml.ToString(); finalXml = WsdlAnnotator.Annotate(finalXml); byte[] data = UTF8Encoding.UTF8.GetBytes(finalXml); inputStream.Write(data, 0, data.Length); } } private void SetEndOfFileMarker(string valueToWrite) { if (firstWrite) { int definitionTagIndex = valueToWrite.IndexOf(" -1 || schemaTagIndex > -1) { firstWrite = false; if (definitionTagIndex > -1 && schemaTagIndex > -1) { endOfFileMarker = definitionTagIndex < schemaTagIndex ? DefinitionsEndOfFileMarker : SchemaEndOfFileMarker; } else if (definitionTagIndex > -1) { endOfFileMarker = DefinitionsEndOfFileMarker; } else if (schemaTagIndex > -1) { endOfFileMarker = SchemaEndOfFileMarker; } } } } } 

WsdlAnnotator是所有魔法发生的地方:

 internal static class WsdlAnnotator { internal static string Annotate(string xml) { XDocument document = XDocument.Parse(xml); try { // Your magic here. } catch (Exception ex) { throw new InvalidOperationException( ex.Message + " Document: " + document.ToString(), ex); } return document.ToString(SaveOptions.None); }