WCF WSDL + Nillable Атрибуты - PullRequest
       3

WCF WSDL + Nillable Атрибуты

1 голос
/ 28 января 2012

У меня есть служба WCF с Flatlined WSDL , и потребитель на другом конце говорит мне, что атрибуты nillable = "true" скрывают их.Я попытался установить EmitDefaultValue = false в своем сервисном контракте, но я не заметил каких-либо изменений в поведении.

По общему признанию, мне никогда не приходилось копаться в генерации WSDL на этом уровне, поэтому я немного растерялся,Возможно, в приведенном ниже фрагменте кода будет внесена поправка, которая может решить мою проблему?Если я по крайней мере в правильном месте, я буду продолжать расследование.

Есть ли простой способ удалить атрибуты nillable = "true" из моего WSDL, и будет ли это иметь непредвиденные последствия?Спасибо!

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...
}

Ответы [ 2 ]

1 голос
/ 21 января 2014

После поиска нашего интернета я и моя команда решили пойти другим путем, чтобы избавиться от nillable = "true".Мы сделали следующее:

  1. Зарегистрировал специальный HttpModule во время запуска приложения.
  2. Этот модуль зарегистрировал обработчик для события BeginRequest.
  3. Весли запрашиваются WSDL или XSD (проверяется путем просмотра строки запроса), обработчик перехвата заменит значение по умолчанию 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 = "</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);
    }
1 голос
/ 28 января 2012

Нет прямого простого способа добиться этого.Вам придется использовать WsdlExporter , чтобы реализовать это самостоятельно.Будет ли это иметь непредвиденные последствия, зависит от ваших намерений: -)

РЕДАКТИРОВАТЬ:

Посмотрите на MSDN пример IWSDLExportExtension .Это позволит вам делать именно то, что вы хотите.По общему признанию, это немного хлопотно, чтобы понять это правильно, но вы смотрите в правильном направлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...