使用 jQuery jsonp 跨域调用 ASP.NET Web 服务
我的问题是已知问题并进行了讨论 此处 和 此处。 但即使在阅读并实施了建议的解决方案之后,我也无法完成这项工作。
问题:Web 服务返回 xml 而不是 json:
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">"Now i am getting jsop string""2nd param"</string>
现在让我们将代码分成几个部分:
远程服务器(IIS 7.0、.NET 4):
网络配置:
<?xml version="1.0"?>
<configuration>
<system.webServer>
<modules>
<add name="JsonHttpModule.JsonHttpModule" type="JsonHttpModule"/>
</modules>
</system.webServer>
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="102400"/>
</webServices>
</scripting>
</system.web.extensions>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
</system.web>
</configuration>
Web 服务:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;
using JsonHttpModule;
/// <summary>
/// Summary description for JSONP_EndPoint
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class MyService : System.Web.Services.WebService {
[WebMethod]
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public string Sum(string x, string y)
{
return x + y;
}
}
HttpModule 类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Text;
/// <summary>
/// Summary description for ContentTypeHttpModule
/// </summary>
namespace JsonHttpModule
{
public class JsonHttpModule : IHttpModule
{
private const string JSON_CONTENT_TYPE = "application/json; charset=utf-8";
public void Dispose()
{
}
public void Init(HttpApplication app)
{
app.BeginRequest += OnBeginRequest;
app.EndRequest += new EventHandler(OnEndRequest);
}
public void OnBeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
//Make sure we only apply to our Web Service
if (request.Url.AbsolutePath.ToLower().Contains("MyService.asmx"))
{
if (string.IsNullOrEmpty(app.Context.Request.ContentType))
{
app.Context.Request.ContentType = JSON_CONTENT_TYPE;
}
app.Context.Response.Write(app.Context.Request.Params["callback"] + "(");
}
}
void OnEndRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
if (request.Url.AbsolutePath.ToLower().Contains("MyService.asmx"))
{
app.Context.Response.Write(")");
}
}
}
}
客户端(本地主机):
<script>
$(function () {
$('#btn_test').click(function () {
$.ajax({ url: "http://tonofweb.com/MyService.asmx/Sum",
data: { x: JSON.stringify("Now i am getting jsop string"), y: JSON.stringify("2nd param") },
dataType: "jsonp",
success: function (json) {
alert(json.d);
},
error: function () {
alert("Hit error fn!");
}
});
});
});
</script>
<input id="btn_test" type="button" value="POST" />
那么我在这里做错了什么? 你可以自己测试一下,这是一个实时网络服务。 感谢您的帮助。
My problem is known issue and discussed here and here.
But even after reading and implementing the suggested solutions i am unable to make this work.
The problem: the web service returning xml insted of json:
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">"Now i am getting jsop string""2nd param"</string>
Now lets break the code into sections:
THE REMOTE SERVER (IIS 7.0, .NET 4):
web.config:
<?xml version="1.0"?>
<configuration>
<system.webServer>
<modules>
<add name="JsonHttpModule.JsonHttpModule" type="JsonHttpModule"/>
</modules>
</system.webServer>
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="102400"/>
</webServices>
</scripting>
</system.web.extensions>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
</system.web>
</configuration>
the web service:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;
using JsonHttpModule;
/// <summary>
/// Summary description for JSONP_EndPoint
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class MyService : System.Web.Services.WebService {
[WebMethod]
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public string Sum(string x, string y)
{
return x + y;
}
}
the HttpModule class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Text;
/// <summary>
/// Summary description for ContentTypeHttpModule
/// </summary>
namespace JsonHttpModule
{
public class JsonHttpModule : IHttpModule
{
private const string JSON_CONTENT_TYPE = "application/json; charset=utf-8";
public void Dispose()
{
}
public void Init(HttpApplication app)
{
app.BeginRequest += OnBeginRequest;
app.EndRequest += new EventHandler(OnEndRequest);
}
public void OnBeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
//Make sure we only apply to our Web Service
if (request.Url.AbsolutePath.ToLower().Contains("MyService.asmx"))
{
if (string.IsNullOrEmpty(app.Context.Request.ContentType))
{
app.Context.Request.ContentType = JSON_CONTENT_TYPE;
}
app.Context.Response.Write(app.Context.Request.Params["callback"] + "(");
}
}
void OnEndRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
if (request.Url.AbsolutePath.ToLower().Contains("MyService.asmx"))
{
app.Context.Response.Write(")");
}
}
}
}
CLIENT SIDE (localhost):
<script>
$(function () {
$('#btn_test').click(function () {
$.ajax({ url: "http://tonofweb.com/MyService.asmx/Sum",
data: { x: JSON.stringify("Now i am getting jsop string"), y: JSON.stringify("2nd param") },
dataType: "jsonp",
success: function (json) {
alert(json.d);
},
error: function () {
alert("Hit error fn!");
}
});
});
});
</script>
<input id="btn_test" type="button" value="POST" />
so what am i doing wrong here?
you can test it yourselves it's a live web service.
Thank you for your help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
似乎 Web 服务返回 JSON 的所有配置和属性都已到位,但我确实注意到在您的 jQuery 请求中,您没有指定传入数据的内容类型。我已将其添加到下面的代码中:
请注意,我将
contentType: "application/json; charset=utf-8",
添加到请求设置中。我通过浏览 http://tonofweb.com (此时返回 403)测试了此代码,包括使用 jQuerify bookmarklet,然后首先运行您的问题中的代码(没有< /强> contentType),然后是我上面发布的代码(与 contentType)。
以下是 Chrome 开发者工具中“网络”选项卡的响应:
不带 contentType:
带 contentType:
因此第二个至少会导致从服务器返回 JSON。因此,在其他条件相同的情况下,我会说添加 contentType。
有关返回 JSON 的要求的说明,请参阅此处:
ASMX 和 JSON – 常见错误和误解< /a>
现在还有另一个问题,那就是请求完成后调用错误函数。如果将
dataType: "jsonp"
更改为dataType: "json"
它将调用 success 函数。所以你的回调包装器的实现是错误的,因为 jQuery 无法将响应作为 JSONP 处理。现在我也没有看到响应中包含的回调,对于 JSONP,响应应该类似于:
我注意到您正在链接到 这篇文章介绍了如何从 Web 服务执行 JSONP 响应,但您不知道遵循建议:您不使用 Response.Filter,而是使用 Response.Write。
It seems all the configuration and attributes are in place for the web service to return JSON but I did notice in your jQuery request, you are not specifying the content type of the data you are passing in. I have added it to the code below:
Notice I added
contentType: "application/json; charset=utf-8",
to the request settings.I have tested this code by browsing to http://tonofweb.com (which returns a 403 at the moment), including jQuery using the jQuerify bookmarklet, and then running the code from your question first (without the contentType), and then the code I posted above (with the contentType).
Here are the responses from the Network tab in the Chrome Developer Tools:
Without contentType:
With contentType:
So the second one at least results in JSON being returned from the server. So all else being equal, I'd say add the contentType.
See here for an explanation of the requirements to return JSON:
ASMX and JSON – Common mistakes and misconceptions
Now you still have another problem, and that is that the request, upon completion, calls the error function. If you change
dataType: "jsonp"
todataType: "json"
it will call the success function. So something about your implementation of the callback wrapper is wrong, because jQuery can't handle the response as JSONP.Now I'm not seeing the callback wrapped in the response either, for JSONP, the response should be something like:
I notice you are linking to this post about how to do a JSONP response from a web service, but you are not following the advice: you don't use
Response.Filter
, instead you useResponse.Write
.