jQuery 如何从跨域调用的 ASP.NET Web 服务生成 JSONP?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14221429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 13:21:59  来源:igfitidea点击:

How can I produce JSONP from an ASP.NET web service for cross-domain calls?

asp.netjquerycross-domainjsonp

提问by NickG

I've written a webservice which returns JSON and I've tried to call it using jQuery like this:

我编写了一个返回 JSON 的网络服务,我尝试使用 jQuery 调用它,如下所示:

$.ajax({
    contentType: "application/json; charset=utf-8",
    url: "http://examplewebsite.com/service.asmx/GetData",
    data: { projectID: 1 },
    dataType: "jsonp",
    success: function () {alert("success");}
});

However the code never calls the success function, despite the webservice call being successful when looking at the HTTP traffic using Fiddler. I think this is because my web service is returning raw JSON instead of JSONP.

然而,尽管使用 Fiddler 查看 HTTP 流量时 webservice 调用成功,但代码从不调用成功函数。我认为这是因为我的 Web 服务返回原始 JSON 而不是 JSONP。

How can I produce JSONP as the response from a standard .NET webservice method like this:

如何生成 JSONP 作为来自标准 .NET webservice 方法的响应,如下所示:

[WebMethod(), ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public Project GetData(int projectID)
{
    Project p = new Project();
    p.Name = "foobar";
    return p;
}

Thanks.

谢谢。

回答by NickG

OK, I've eventually figured it out myself. As I found it so hard to find a complete working solution on the web, I've decided to document my working solution here.

好吧,我终于自己弄明白了。由于我发现在网络上很难找到完整的工作解决方案,因此我决定在此处记录我的工作解决方案。

A JSONP response is just standard JSON string wrapped in a function call. ASP.NET doesn't seem to provide any way to return the reponse in this format directly, but it's very simple to do this yourself. You do though, have to override the default method of JSON encoding.

JSONP 响应只是封装在函数调用中的标准 JSON 字符串。ASP.NET 似乎没有提供任何直接返回这种格式的响应的方法,但是自己这样做非常简单。但是,您必须覆盖 JSON 编码的默认方法。

Below is an example of JSONP.

下面是一个 JSONP 的例子。

functionName({ name: 'value';});

functionName({ name: 'value';});

..now this bit: { name: 'value';}is just standard JSON that any JSON serializer will give you, so all we need to do is tack on the function call wrapper. Unfortunately, doing that means we have to 'unwire' (or bypass) the existing JSON encoding which is handled transparently by the framework when you return an object from the web service function.

..现在这一点: { name: 'value';}只是任何 JSON 序列化程序都会给你的标准 JSON,所以我们需要做的就是添加函数调用包装器。不幸的是,这样做意味着我们必须“取消连接”(或绕过)现有的 JSON 编码,当您从 Web 服务函数返回对象时,该编码由框架透明处理。

This is done by overriding the response from the web service function completely by writing the JSONP to the output stream (Response) using our own code. This is actually quite straightforward and I've included an example below.

这是通过使用我们自己的代码将 JSONP 写入输出流 (Response) 来完全覆盖来自 Web 服务功能的响应来完成的。这实际上非常简单,我在下面包含了一个示例。

You can use either the built in DataContractJsonSerializer(from the System.Runtime.Serialization.Json namespace in ASP.NET 3.5+) or the NewtonSoft JSONserializer, and both examples are shown below. I prefer to use the the NewtonSoft JSON(installed from nuget) rather than the built in JSON serializer as I find it gives you more control and also can output nicely formatted human readable JSON for debugging. It's also much faster on paper!

您可以使用内置的DataContractJsonSerializer(来自 ASP.NET 3.5+ 中的 System.Runtime.Serialization.Json 命名空间)或NewtonSoft JSON序列化器,两个示例如下所示。我更喜欢使用NewtonSoft JSON(从 nuget 安装)而不是内置的 JSON 序列化程序,因为我发现它可以为您提供更多控制,并且还可以输出格式良好的人类可读 JSON 以进行调试。在纸上也快得多!

[WebMethod()]
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public void GetData(int projectID, string callback)
{
    List<Video> videos = null;
    // <code here to populate list on line above>

    // Method 1: use built-in serializer:
    StringBuilder sb = new StringBuilder();
    JavaScriptSerializer js = new JavaScriptSerializer();
    sb.Append(callback + "(");
    sb.Append(js.Serialize(videos));
    sb.Append(");");    

    // Method 2: NewtonSoft JSON serializer (delete as applicable)
    // StringBuilder sb = new StringBuilder();
    // sb.Append(callback + "(");
    // sb.Append(JsonConvert.SerializeObject(videos, Formatting.Indented)); // indentation is just for ease of reading while testing
    // sb.Append(");");     

    Context.Response.Clear();
    Context.Response.ContentType = "application/json";
    Context.Response.Write(sb.ToString());
    Context.Response.End();
}

This method can then be called using the following JQuery code:

然后可以使用以下 JQuery 代码调用此方法:

$.ajax({
    crossDomain: true,
    contentType: "application/json; charset=utf-8",
    url: "http://examplewebsite.com/service.asmx/GetData",
    data: { projectID: 1 }, // example of parameter being passed
    dataType: "jsonp",
    success: onDataReceived
});

function onDataReceived(data)
{
    alert("Data received");
    // Do your client side work here.
    // 'data' is an object containing the data sent from the web service 
    // Put a JS breakpoint on this line to explore the data object
}

回答by Joe Ramos

Thanks Nick, that was an excellent answer to a problem that I too had a hard time finding at first online. Worked great for me as well.

谢谢尼克,这是我最初在网上也很难找到的问题的一个很好的答案。对我也很有用。

Wanted to make sure this this line of post got the attention it deserves.

想要确保这一行帖子得到应有的关注。

Just wanted to add that I used the built in serializer (System.Runtime.Serialization.Json) and it worked like a charm as well.

只是想补充一点,我使用了内置的序列化程序(System.Runtime.Serialization.Json),它的工作方式也很有魅力。

        List<orderHistory> orderHistory = null;

        StringBuilder sb = new StringBuilder();
        JavaScriptSerializer js = new JavaScriptSerializer();
        sb.Append(callback + "(");
        sb.Append(js.Serialize(orderHistory));
        sb.Append(");");

        Context.Response.Clear();
        Context.Response.ContentType = "application/json";
        Context.Response.Write(sb.ToString());
        Context.Response.End();

回答by Dmitry Pavlov

In case someone is looking for sample how to return JSONPfrom ASP.NETWeb APIaction:

如果有人正在寻找如何JSONPASP.NETWeb API行动中返回的示例:

// GET api/values
public JsonpResult Get()
{
    var values = new string[] { "value1", "value2" };
    return new JsonpResult(values);
}

JsonpResulthelper class encapsulating the JSONPwrapping.

JsonpResult封装JSONP包装的辅助类。

public class JsonpResult : JsonResult
{
    object _data = null;

    public JsonpResult(object data)
    {
        _data = data;
    }

    public override void ExecuteResult(ControllerContext controllerContext)
    {
        if (controllerContext != null)
        {
            var response = controllerContext.HttpContext.Response;
            var request = controllerContext.HttpContext.Request;

            var callBackFunction = request["callback"];
            if (string.IsNullOrEmpty(callBackFunction))
            {
                throw new Exception("Callback function name must be provided in the request!");
            }
            response.ContentType = "application/x-javascript";
            if (_data != null)
            {
                var serializer = new JavaScriptSerializer();
                response.Write(string.Format("{0}({1});", callBackFunction, serializer.Serialize(_data)));
            }
        }
    }
}