Returning raw json (string) in wcf
Asked Answered
B

4

52

I want to build my own JSON, and have the service return a string, here is the code

[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
public string GetCurrentCart()
{
    //Code ommited
    string jsonClient = null;
    var j = new { Content = response.Content, Display=response.Display, SubTotal=response.SubTotal};
    var s = new JavaScriptSerializer();
    jsonClient = s.Serialize(j);
    return jsonClient;
}

The response I am getting contains the \" used to create "'s in strings in c#.

The following is the response.

"{\"Content\":\"\\r\\n\\u003cdiv\\u003e\\r\\n\\u003cinput type=\\\"hidden\\\" name=\\\"__VIEWSTATE\\\" id=\\\"__VIEWSTATE\\\" value=\\\"\/wEPDwUBMA9kFgJmD2QWAmYPZBYGAgMPFgIeBFRleHQFKFlvdSBoYXZlIG5vIGl0ZW1zIGluIHlvdXIgc2hvcHBpbmcgY2FydC5kAgUPFgIeB1Zpc2libGVoZAIHDxQrAAIPFgIfAWhkZGQYAQUMY3RsMDEkbHZDYXJ0D2dkoWijqBUJaUxmDgFrkGdWUM0mLpgQmTOe8R8hc8bZco4=\\\" \/\\u003e\\r\\n\\u003c\/div\\u003e\\r\\n\\r\\n\\u003cdiv class=\\\"block block-shoppingcart\\\"\\u003e\\r\\n    \\u003cdiv class=\\\"title\\\"\\u003e\\r\\n        \\u003cspan\\u003eShopping Cart\\u003c\/span\\u003e\\r\\n    \\u003c\/div\\u003e\\r\\n    \\u003cdiv class=\\\"clear\\\"\\u003e\\r\\n    \\u003c\/div\\u003e\\r\\n    \\u003cdiv class=\\\"listbox\\\"\\u003e\\r\\n        You have no items in your shopping cart.\\r\\n        \\r\\n        \\r\\n    \\u003c\/div\\u003e\\r\\n\\u003c\/div\\u003e\\r\\n\",\"Display\":\"You have no items in your shopping cart.\",\"SubTotal\":null}"

The values are being correctly encoded, but the json itself is not properly formatted. These \'s cause it to go out of wack.

How do I return a string without the \'s in front of the "'s?

Bedfordshire answered 20/6, 2010 at 6:15 Comment(1)
when I set ResponseFormat=WebMessageFormat.Xml, the \'s are gone, but of couse the root xml node is there (which I don't want).Bedfordshire
M
119

Currently your web method returns a String together with ResponseFormat = WebMessageFormat.Json. It follows that your code will use the JSON encoding of the string. Corresponding to json.org, this means all double quotes in the string will be escaped using backslashes. So you currently have double JSON encoding.

The easiest way to return any kind of data is to change the output type of the GetCurrentCart() web method to Stream or Message (from System.ServiceModel.Channels) instead of String.

For code examples, see also...

Because you don't include in your question which version of .NET you use, I suggest you to use a universal (and the easiest) way:

public Stream GetCurrentCart()
{
    //Code ommitted
    var j = new { Content = response.Content, Display=response.Display,
                  SubTotal=response.SubTotal};
    var s = new JavaScriptSerializer();
    string jsonClient = s.Serialize(j);
    WebOperationContext.Current.OutgoingResponse.ContentType =
        "application/json; charset=utf-8";
    return new MemoryStream(Encoding.UTF8.GetBytes(jsonClient));
}
Mccaskill answered 20/6, 2010 at 13:6 Comment(16)
I have wasted hours on this. Thanks!Bedfordshire
Hi Oleg thank you so..much i waste the so much of time for this at finally i found this link..Really i thanks to you...Extraordinary
@Victor: I am glad to hear (to read) that I could help you. You are welcome!Mccaskill
Hi i have one more issue that when i return the json string at last showing the null can u refer this link once please restaurantmanager.testshell.net/api/Account/…Extraordinary
How can i solve this end the array it append the <?xml version="1.0" encoding="utf-8"?><Stream p1:nil="true" xmlns:p1="w3.org/2001/XMLSchema-instance" />Extraordinary
@Victor: sorry, but the url which you posted return <p class="heading1">Service</p><p>Endpoint not found.</p> error with the HTTP status cod "HTTP/1.1 404 Not Found". Do you have a question where you describes your probel? Could you post correct URL?Mccaskill
Hi Oleg can you test that link in Online Json valid tester in that it showing some errors and when check the view source page it showing the all data.Extraordinary
when i run this in Fiddler it showing like this [{"AccountId":1,"AccountNumber":"AC001","AccountType":"Restaurant","BusinessName":"Red Spice Inc","PrimaryContactFirstName":"Varma","PrimaryContactLastName":"Bhupatiraju","PrimaryContactPhone":"(949) 374 2114","PrimaryContactEmail":"[email protected]","AccountGuid":"918D3E66-CEFE-11E0-8C2F-0C0B4824019B","EntityState":1,"EntityKey":null}]<?xml version="1.0" encoding="utf-8"?><Stream p1:nil="true" xmlns:p1="w3.org/2001/XMLSchema-instance" />.Extraordinary
@Victor: I wrote you before that the link restaurantmanager.testshell.net/api/Account/… which you posted is wrong and return only the error "Endpoint not found." So I can't test anything.Mccaskill
@Mccaskill let us continue this discussion in chatExtraordinary
Thanks ,its really alos help me to get out to this problem that i am facing .Thanks a lot.Obtrude
@VikramSE: You are welcome! I'm glad to know that I could help you.Mccaskill
Do we need to close the memorystream?Landpoor
@Pilouk: No, it's not needed.Mccaskill
Your first link was EXACTLY what I was looking for. return string as json. done. ThanksCooky
@AdamHey: You are welcome! I'm glad that the old answer still helps.Mccaskill
M
6

I tried the method suggested by Oleg but found that when i used this method for a large amount of data null key word was appended at the end of the JSON string.

Example: for json with lots of data {"JsonExample":"xxxxx"}null

found a solution to address this problem at : http://wcf.codeplex.com/workitem/67 Wrote the following function which will accept a object and return a Pure Json output. So before returning my object in the main method i make a call to the below method.

  public HttpResponseMessage ReturnPureJson(object responseModel)
    {
        HttpResponseMessage response = new HttpResponseMessage();

        string jsonClient = Json.Encode(responseModel);
        byte[] resultBytes = Encoding.UTF8.GetBytes(jsonClient);
        response.Content = new StreamContent(new MemoryStream(resultBytes));
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");

        return response;
    }
Mayonnaise answered 22/2, 2012 at 6:46 Comment(1)
but you can't use HttpResponseMessage unless you have .NET 4.5Hulbert
W
3

I recommend to use Jil library to Serialize your JSON object or dynamic(ExpandoObject).

In my case, It will avoid some null value problem, like always get "{}" from JsonConvert.SerializeXXX and extend {aa:bb} to {key:aa, value:bb} from JavaScriptSerializer

full sample here as below.

Interface:

[OperationContract]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "json/GetCurrentCart")]
Stream GetCurrentCart(MyRequestParam Param);

Implementation:

public Stream GetCurrentCart(MyRequestParam Param)
{
    //code omitted
    dynamic j = new System.Dynamic.ExpandoObject();
    j.Content = response.Content;
    j.Display = response.Display; 
    j.SubTotal = response.SubTotal;
    string s = Jil.JSON.SerializeDynamic(j);
    WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
    return new MemoryStream(Encoding.UTF8.GetBytes(s));
} 
Wold answered 23/9, 2015 at 7:3 Comment(0)
T
2

That was great (Oleg Response) and all make sure that you add the line WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";

if you removed it result will be downloaded as file .

Toothed answered 12/2, 2015 at 1:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.