#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)
{
}
}