+1  A: 

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.

Jon Skeet
Thanks, so which is the right way to do that, please? Am I digging the correct direction at all?
BreakPhreak
I've also checked the result of what GetBytes() returns in the debugger. The array of bytes is returned and the values seem to be correct, such as arr[0] = 72 ('H'), arr[1] = 101 ('e') etc. It seems that the framework is mangling with the results.
BreakPhreak
The legacy code expects to receive a plain text/xml string. Let's assume that if "Hello World" is displayed in the browser and the content type is "text/ascii" - than we are on the right way.
BreakPhreak
@BreakPhreak: No, nothing's "mangling" the results. GetBytes() will be returning the result of base64-decoding the base64-encoded data, just as it should do. Basically if you try to get your web service to return an arbitrary array of bytes, this will happen. If you don't want that to happen, don't use a byte array.
Jon Skeet
I cleanly see the bytes array in the debugger and the values are correct. Can't get you about the random bytes, that's cleanly is NOT what I am asking about though :) If anything in the question is not clarified enough - feel welcome to ask; would be great to get and answer that points the right direction, I already know that I am doing something wrong :)
BreakPhreak
@BreakPhreak: For some reason I've lost the comment that I just wrote, but the gist of it was that you still seem convinced that the framework is doing something wrong: it's not. You asked it to transfer an opaque blob, so it's doing that, using Base64. If you use bytes, that's what will happen. If your legacy client can't handle that, you'll need to take a different approach. It sounds like it can't handle UTF-8 either... could you explain what it *can* handle?
Jon Skeet
Ah, no-no :) I am totally agreed that I am doing something wrong - maybe the "Gibberish" term causes that feeling. Yes, I need a different approach, being in a "winner" situation of hard deadlines and not-so-expert with WCF. The legacy client code sends raw HTTP request and expects to receive ASCII XML text. I already have that text in StringBuffer, all I need is to convert it to ASCII (only English letters and number etc of course) and still being able to utilize the UriTemplate functionality to parse the request. Does it all sound better now?
BreakPhreak
@BreakPhreak: Okay, so it sounds like you *possibly* just need to persuade WCF to use ASCII as the encoding instead of UTF-8. It's pretty weird for an XML parser not to accept UTF-8 though... it would be good if you could fix that. To be honest, I don't know the best way to change the server response here. One *possible* option is to insert a filter somewhere in the HTTP handler chain - read the XML document produced by WCF, and just rewrite it in ASCII. That's probably where I'd start looking, but it'll be ugly.
Jon Skeet
Yes, you are right - the best solution would be to modify/rewrite the legacy code, but it's not a viable option in production right now (though planned). I've figured out (as gentlemen below suggests) 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), which is not nice. Just clarifying my needs - in case someone will have an idea how to integrate the Message and UriRequest - would be great to know.
BreakPhreak
A: 

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.

Johann Blais
Thanks a lot! I will read the link and will try it right now. Will I still be able to get my request parsed with UriTemplate? (I'll try it meanwhile just as said, if there is any relevant info/pitfalls - please be kind to share).
BreakPhreak
Just tried. Operation 'DoIt' in contract 'IHello' has a UriTemplate that expects a parameter named 'data', but there is no input parameter with that name on the operation.
BreakPhreak
A: 

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.

BreakPhreak