Ответ WCF без учета

#wcf #rest

#wcf #rest

Вопрос:

Я, наконец, начинаю что-то делать с WCF, но столкнулся с другой проблемой. Отправленный ответ не включает заголовок

 <?xml version="1.0" encoding="utf-8" ?>
  

Мой контракт на обслуживание

  [ServiceContract]
    public interface IService1
    {
        // you can have optional parameters by simply specifying them and they will return null if there is nothing in there
        [WebGet(UriTemplate="testing={value}", ResponseFormat = WebMessageFormat.Xml)]
        [OperationContract]
        XElement GetData(string value);
    }


 [XmlSerializerFormat]
    public class Service1 : IService1
    {
        public XElement GetData(string value)
        {
            return new XElement("Somename", value); 
        }
   }
  

возвращает это (3 — указанное значение)

 <Somename>3</Somename>
  

Возможно ли также легко обернуть ответ в корневой элемент? Что-то вроде <response></response> ?

Ответ №1:

Ответ Результатом вызова метода getData является содержимое того, что вы возвращаете в методе. Если вам нужна оболочка, верните что-то вроде:

 [XmlSerializerFormat]
public class Service1 : IService1
{
    public XElement GetData(string value)
    {
        return new XElement("response",
                       new XElement("Somename", value));
    }
}
  

Редактировать:

Чтобы добавить XML-объявление (что на самом деле может быть не очень хорошей идеей, но вы знаете лучше), сделайте что-то вроде этого:

 var doc = new XDocument(
            new XElement("response",
                           new XElement("Somename", value)));

doc.Declaration = new XDeclaration("1.0", "utf-8", "true");

return doc.Root;
  

Комментарии:

1. Я думал, что хорошей практикой было возвращать xml-объявление, но я, честно говоря, не знаю.

2. Второй вариант у меня не работает. Когда я ввожу параметр, ничего не возвращается

3. Я посоветовал соблюдать осторожность, потому что результат будет встроен в HTTP-ответ, который будет где-то десериализован клиентом. Это процесс десериализации (если таковой имеется), который может иметь проблемы с объявлением XML. Я бы не стал этого делать, если у вас нет реальной причины нуждаться в этом.

4. Я добавил ссылку на свойство Root в примере, чтобы устранить проблему.

5. По какой-то причине он по-прежнему не добавляет его в выходные данные.

Ответ №2:

Я сам искал ответ на этот вопрос и наткнулся на эту статью:

http://shevaspace.blogspot.com/2009/01/include-xml-declaration-in-wcf-restful.html

Это решило проблему в моей ситуации, возможно, это поможет и другим. В нем описывается пользовательский атрибут, IncludeXmlDeclaration который вы можете вставить в свой метод, и он будет выводить xml-заголовок.

Для полноты картины, вот код, скопированный из статьи:

 public class XmlDeclarationMessage : Message
{
    private Message message;
    public XmlDeclarationMessage(Message message)
    {
        this.message = message;
    }

    public override MessageHeaders Headers
    {
        get { return message.Headers; }
    }

    protected override void OnWriteBodyContents(System.Xml.XmlDictionaryWriter writer)
    {
        // WCF XML serialization doesn't support emitting XML DOCTYPE, you need to roll up your own here.
        writer.WriteStartDocument();
        message.WriteBodyContents(writer);
    }


    public override MessageProperties Properties
    {
        get { return message.Properties; }
    }

    public override MessageVersion Version
    {
        get { return message.Version; }
    }
}

public class XmlDeclarationMessageFormatter : IDispatchMessageFormatter
{
    private IDispatchMessageFormatter formatter;
    public XmlDeclarationMessageFormatter(IDispatchMessageFormatter formatter)
    {
        this.formatter = formatter;
    }

    public void DeserializeRequest(Message message, object[] parameters)
    {
        formatter.DeserializeRequest(message, parameters);
    }

    public Message SerializeReply(MessageVersion messageVersion, Object[] parameters, Object result)
    {
        var message = formatter.SerializeReply(messageVersion, parameters, result);
        return new XmlDeclarationMessage(message);
    }
}

public class IncludeXmlDeclarationAttribute : Attribute, IOperationBehavior
{
    public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
    {
    }

    public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
    {
        dispatchOperation.Formatter = new XmlDeclarationMessageFormatter(dispatchOperation.Formatter);
    }

    public void Validate(OperationDescription operationDescription)
    {
    }
}