Question

Here is a trivial example that is supposed to return "Hello World" string. However, a browser displays something like SGVsbG8gV29ybGQ=. Which is the right way to return plain text from an oldskul-style service?

please know that:

  1. I can't return a string: three Unicode characters will be automatically prepended and the legacy HTTP client won't be able to interoperate.

  2. I could return a Message, but still must keep parsing functionality to extract the data variable. Mixing Message and int types in the same method signature is not allowed AFAIK.

    [ServiceContract(SessionMode=SessionMode.NotAllowed)] 
    public interface IHello 
    {
      [WebGet(UriTemplate = "manager?data={data}")]
      [OperationContract]
      Byte[] DoIt(int data);
    }

    public class Hello : IHello { public Byte[] DoIt(int data) { return Encoding.ASCII.GetBytes("HelloWorld"); } }

UPDATE: It's not gibberish, but correctly encoded response. However, the format is not what I'd expect to receive. I've figured out (as gentlemen below suggest) that the ultimate control of the transport layer messaging format is gained with Message class. However, if I do use one - I loose the possibility of parsing the request (UriTemplate attribute). Hence, it would be great to know how to integrate the Message with UriRequest.

P.S. If the "clean" integration is not possible - than what's the most elegant workaround? Is there any code that is done behind the wire curtain that I can borrow and use in my implementation, please?

Was it helpful?

Solution 2

Googled for a proper way to integrate and found that people are stuck just as I am (please correct me if I am wrong on that). So far the following workaround works fine for me:

  public class Hello : IHello
  {
        [WebGet(UriTemplate = "manager")]
        [OperationContract]
        Message DoIt();
  }

  public class Hello : IHello
  {
        public Message DoIt()
        {
          var webContext = WebOperationContext.Current;
          var request = webContext.IncomingRequest;
          var queryParameters = request.UriTemplateMatch.QueryParameters;
          var data = queryParameters["data"];

          var result = new StringBuilder(@"
              <?xml version='1.0'?>
              ...
          ");

          var response = webContext.CreateTextResponse(result.ToString(), "application/xml", Encoding.ASCII);

          return response;
        }
  }

If there is a better alternative - it would be perfect to know about it.

OTHER TIPS

That's not gibberish - it's the base64-encoded version of the ASCII bytes for "Hello World" (with a space).

When you ask a web service to transmit bytes, it will use base64... your web service client will perform the base64 decoding automatically, to get you back the original bytes.

(I wouldn't suggest using Encoding.ASCII, mind you.)

It's not clear what your "legacy HTTP client" is, or what it's expecting, so we can't really tell whether returning a byte array is actually the best answer or not.

The SOAP specification states that raw binary data should be base64 encoded. So the behavior you witness is correct.

If you need to transmit ASCII character data. You can use one message contract and a raw Message.

Message DoIt(DoItRequest request)

The raw message will create the response containing ASCII data. The message contract is used to retrieve the int parameter you mentioned:

[MessageContract]
public class DoItRequest
{
  [MessageBodyMember] public int data;
}

This page explains how to work with the Message class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top