Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return JSONP in proper format WCF

I'm trying to output a correctly wrapped JSONP value for jQuery to consume.

The output I'm looking for is:

jsoncallback({"Status": "OK"})

But the atm it's outputting:

"jsoncallback({"Status": "OK"})"

Evidently this is not in correct JSONP format as the jQuery request can't handle the response.

My OperationContract in C# is:

[OperationContract]
[WebInvoke(Method = "GET",
   ResponseFormat = WebMessageFormat.Json,
   UriTemplate = "returndata?s={s}")]
Stream EchoWithGet(string s);

    public string EchoWithGet(string s)
    {
        string json = @"jsoncallback({'Status':'OK'})";
        Console.WriteLine("Call Made: " + s);
        return json;
    }

I've tried using JSON.NET and also the System.Web.Script Namespace to use the JavaScriptSerializer.

But nothing is working for me all I actually want to do is get rid of two double quotes.

like image 839
Sandeep Bansal Avatar asked Jun 18 '12 20:06

Sandeep Bansal


People also ask

What is JSONP datatype?

JSONP stands for JSON with Padding. Requesting a file from another domain can cause problems, due to cross-domain policy. Requesting an external script from another domain does not have this problem. JSONP uses this advantage, and request files using the script tag instead of the XMLHttpRequest object.

What is JSONP callback?

JSONP is an informal protocol that allows you to make cross-domain calls by producing script tags on the current page and awaiting a response to a callback handler you provide.

Which element is added to the DOM to create a JSONP request?

The <script> element is injected into the HTML DOM, with the URL of the desired JSONP endpoint set as the "src" attribute. This dynamic script element injection is usually done by a JavaScript helper library.


2 Answers

If you're submitting an ajax request with jQuery and asks for dataType: "jsonp", jQuery will pass a name for the callback function in the request (e.g., /returndata?s=hello&callback=jquery123456789), so returning a constant "jsonCallback" will not work in that case.

Also, in your question you have the operation contract definition returning Stream, while on the operation itself you're returning string - something is wrong there.

What you need to do: you have two options. The first one is to let WCF handle the JSONP padding for you. Your operation would need to return a data type with a property "Status", and just return it. You'd also need to enable the CrossDomainScriptAccessEnabled property on the WebHttpBinding used by your endpoint. Your operation would look something like the code below:

public class MyType
{
    public string Status { get; set; }
}

[ServiceContract]
public class Service
{
    [WebGet(UriTemplate = "returndata?s={s}")]
    public MyType ReturnData(string s)
    {
        return new MyType { Status = "OK" };
    }
}

The second option, if you want to create the JSONP code yourself, would be to take an additional parameter in the URI for the callback function name, then use it when creating your response. You'd also need to return it as a Stream, so that you don't get the response as a string (which is probably what you have right now). That would look like this:

[ServiceContract]
public class Service
{
    [WebGet(UriTemplate = "ReturnData?s={s}&callback={callbackFunctionName}")]
    public Stream EchoWithGet(string s, string callbackFunctionName)
    {
        string jsCode = callbackFunctionName + "({\"Status\":\"OK\"});";
        WebOperationContext.Current.OutgoingResponse.ContentType = "application/javascript";
        return new MemoryStream(Encoding.UTF8.GetBytes(jsCode));
    }
}

And this jQuery code can be used to access this service:

    function StackOverflow_11090835_Test() {
        var url = "/StackOverflow_11090835.svc/ReturnData";
        var data = { s: "Hello world" };
        $.ajax({
            type: 'GET',
            url: url,
            data: data,
            dataType: "jsonp",
            success: function (result) {
                $("#result").text(result.Status);
            }
        });
    }
like image 73
carlosfigueira Avatar answered Oct 16 '22 08:10

carlosfigueira


You need to eval the output from your WCF call. See this fiddle.

You're getting a string back from your WCF call. You essentially need to compile it and then execute it.

Here's the code from the fiddle:

function jsonCallback(obj){
    alert(obj.Status);
}

$(document).ready(function(){
    var js = "jsonCallback({'Status':'OK'})";
    eval(js);
});​

The js variable is your output from the WCF call. As soon as I eval it, it will compile and execute.

like image 43
David Hoerster Avatar answered Oct 16 '22 07:10

David Hoerster