3

I put together a simple REST service in WCF as such:

....
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Xml, UriTemplate = "{uid}/{pwd}/{exrcsPrgmId}/{exchEnum}")]
string GetLiftDataExchange(string uid, string pwd, string exrcsPrgmId, string exchEnum);
....

When calling it however I do not get back XML exactly. I get HTXML (my own made up acronym)

Instead of what I expect:

<Exercise>
  <AccountName>Joe Muscle</AccountName>
  <UserID>8008008</UserID>

I get the XML with html encoding:

&lt;Exercise&gt;&#xD;
  &lt;AccountName&gt;John Bonner&lt;/AccountName&gt;&#xD;
  &lt;UserID&gt;8008008&lt;/UserID&gt;&#xD;

In other words I have no need to see this data in the browser instead it will be accessed and parsed in an application so straight up XML will work just fine.

What am I doing wrong with the service decorations to return this encoded xml?

carlosfigueira
  • 85,035
  • 14
  • 131
  • 171
GPGVM
  • 5,515
  • 10
  • 56
  • 97

1 Answers1

11

When you return a string, and the result type is XML, you'll get the string encoded to be able to represent all characters in the string - which causes the XML characters to be escaped.

You have two options for your scenario. If you want to return "pure" XML (i.e., XHTML, or HTML which happens to be well-formed XML), you can use the return type as either XmlElement or XElement. That is telling WCF that you do want to return arbitrary XML. If you do like the code below, you'll get the "pure" XML which you need.

[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate = "...")]
public XElement GetLiftDataExchange(string uid, string pwd, string exrcsPrgmId, string exchEnum)
{
    return XElement.Parse(@"<Exercise>
            <AccountName>Joe Muscle</AccountName>
            <UserID>8008008</UserID>
        </Exercise>");
}

Another alternative is to return a Stream - which means that you control the output (see this blog post for more details), and your code would look something like the one below. The advantage of this method is that your HTML doesn't need to be well-formed XML (i.e., you can have things like <br> or <hr> which are valid HTML but not valid XML).

[OperationContract]
[WebGet(UriTemplate = "...")]
public Stream GetLiftDataExchange(string uid, string pwd, string exrcsPrgmId, string exchEnum)
{
    var str = @"<html><head><title>This is my page</title></head>
            <body><h1>Exercise</h1><ul>
            <li><b>AccountName</b>: Joe Muscle</li>
            <li><b>UserID</b>: 8008008</li></body></html>";
    WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
    return new MemoryStream(Encoding.UTF8.GetBytes(str));
}

On a related node, please don't use [WebInvoke(Method="GET")], use [WebGet] instead.

carlosfigueira
  • 85,035
  • 14
  • 131
  • 171