views:

764

answers:

1

How can I define a [OperationContract] [WebGet] method to return XML that is stored in a string, without HTML encoding the string?

The application is using WCF service to return XML/XHTML content which has been stored as a string. The XML does not correspond to any specific class via [DataContract]. It is meant to be consumed by an XSLT.

[OperationContract]
[WebGet]
public XmlContent GetContent()
{
   return new XmlContent("<p>given content</p>");
}

I have this class:

[XmlRoot]
public class XmlContent : IXmlSerializable
{
 public XmlContent(string content)
 {
  this.Content = content;
 }
 public string Content { get; set; }

 #region IXmlSerializable Members

 public System.Xml.Schema.XmlSchema GetSchema()
 {
  return null;
 }

 public void ReadXml(XmlReader reader)
 {
  throw new NotImplementedException();
 }

 public void WriteXml(XmlWriter writer)
 {

  writer.WriteRaw(this.Content);
 }
 #endregion
}

But when serialized, there is a root tag the wraps the given content.

<XmlContent>
  <p>given content</p>
</XmlContent>

I know how to change the name of the root tag ([XmlRoot(ElementName = "div")]), but I need to omit the root tag, if at all possible.

I have also tried [DataContract] instead of IXmlSerializable, but it seems less flexible.

+3  A: 

Return an XmlElement. You don't need IXmlSerializable. You don't need a wrapper class.

example service interface:

namespace Cheeso.Samples.Webservices._2009Jun01
{
    [ServiceContract(Namespace="urn:Cheeso.Samples.Webservices" )]
    public interface IWebGetService
    {
        [OperationContract]
        [WebGet(
                BodyStyle = WebMessageBodyStyle.Bare,
                    RequestFormat = WebMessageFormat.Xml,
                    ResponseFormat = WebMessageFormat.Xml,
                    UriTemplate = "/Greet/{greeting}")]
        XmlElement Greet(String greeting);
    }
}

service implementation:

namespace Cheeso.Samples.Webservices._2009Jun01
{
    [ServiceBehavior(Name="WcfWebGetService",
                     Namespace="urn:Cheeso.Samples.WebServices",
                     IncludeExceptionDetailInFaults=true)]

    public class WcfWebGetService : IWebGetService
    {
        public XmlElement Greet (String greeting)
        {
            string rawXml = "<p>Stuff here</p>";
            XmlDocument doc = new XmlDocument();
            doc.Load(new System.IO.StringReader(rawXml));
            return doc.DocumentElement;
        }
    }
}

See also, this similar question, but without the WebGet twist:
serializing-generic-xml-data-across-wcf-web-service-requests.

Cheeso
Thanks! That works, but does have the downside of deserializing the XML and then re-serializing it. Not as efficient as I would like, but at least it eliminates the root tag. Thanks for the alternative.
Doug D
Yup, I think if your original data is stored as a string, you have to go through that multi-step process. If it is just static strings, you could de-ser only once and then cache the result. Supposing it is a template that you fill in for the final document fragment - you could cache the template and fill in the dynamic bits with each request.
Cheeso