我有一个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<XmlSchema> importsList = new List<XmlSchema>();
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...
}
答案 0 :(得分:1)
没有直接的简单方法来实现这一目标。您必须自己使用WsdlExporter来实现它。是否会产生意想不到的后果取决于您的意图: - )
编辑:
查看IWSDLExportExtension的MSDN示例。它将允许您完全按照自己的意愿行事。不可否认,要做到这一点有点麻烦,但你正朝着正确的方向前进。
答案 1 :(得分:1)
在网上搜索了我们之后,我和我的团队决定采用不同的方法来摆脱nillable =“true”。我们做了以下几点:
HttpModule
。Response.Filter
。XDocument
并通过该文档进行设置(除其他外,例如添加文档)nillable =“false”。这非常可爱。
找到使用Response.Filter
的想法here。
这是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 = "</wsdl:definitions>";
private const string SchemaEndOfFileMarker = "</xs:schema>";
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("<wsdl:definitions");
int schemaTagIndex = valueToWrite.IndexOf("<xs:schema");
if (definitionTagIndex > -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);
}