2012-01-27 85 views
1

我有一個Flattened WSDL的WCF服務,而另一端的用戶告訴我nillable =「true」屬性正在將它們關閉。我嘗試在服務合同中設置EmitDefaultValue = false,但我沒有注意到行爲有任何變化。無可否認,在這個級別之前,我從來不需要深入研究WSDL的一代,所以我有點迷路。也許在下面的代碼中可以做一些調整,這可能會解決我的問題?如果我至少在正確的地方,我會繼續調查。WCF WSDL + Nillable屬性

是否有一種簡單的方法從我的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

你必須寫自己WsdlExportExtension。 查看此答案的示例:http://stackoverflow.com/questions/10602749/setting-nillable-false-with-wcf/23366064#23366064 – Vizu 2014-04-29 13:33:05

回答

1

沒有直接簡單的方法來實現這一點。你必須使用WsdlExporter來實現它。它是否會帶來意想不到的後果取決於你的意圖:-)

編輯:

看一看的IWSDLExportExtension MSDN的例子。它會讓你做到你想要的。無可否認,讓它正確無誤是一件麻煩事,但你正朝着正確的方向發展。

+0

我選擇了最終沒有采取任何行動,但如果我嘗試要刪除nillable屬性,我會在ExportEndpoint方法中使用WsdlExporter。 – 2012-01-30 22:15:12

+0

.Net 4.5中的這種行爲是否有所改變?我現在即將面臨同樣的情況。項目中沒有IWSDLExportExtension。 – DoomerDGR8 2012-09-06 12:04:31

1

在爲我們搜索了互聯網後,我和我的團隊決定採用不同的方法來擺脫nillable =「true」。我們所做的是以下情況:

  1. 註冊在應用程序啓動特殊HttpModule
  2. 此模塊向BeginRequest事件註冊了一個處理程序。
  3. 在請求WSDL或XSD(通過查看查詢字符串進行檢查)的情況下,掛鉤處理程序將用裝飾器(Stream)替換默認的Response.Filter
  4. 這個裝飾器會緩衝寫入的數據直到達到文檔末尾。
  5. 當所有數據被寫入時,裝飾器根據這些數據建立一個XDocument,並通過該文檔設置(除其他外,例如添加文檔)nillable =「false」。

這個作品都很可愛。

使用Response.Filter的想法被發現here

這裏的HTTP模塊:

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); 
    }