How to call external webservice using jquery “jsonp”?
Posting cross-domain JSON to ASP.NET with jQuery
Error while accessing ASP.net webservice using JQuery – JSONP
Set Headers with jQuery.ajax and JSONP?
http://www.codeproject.com/Articles/43038/Accessing-Remote-ASP-NET-Web-Services-Using-JSONP
http://encosia.com/using-jquery-to-consume-aspnet-json-web-services/
等等…
这是我的示例.NET Web方法:
[WebMethod] [ScriptMethod(UseHttpGet = true,ResponseFormat = ResponseFormat.Json)] public void GetEmployee(string employeeId,string callback) { // Get the employee object from the Factory. Employee requestedEmployee = EmployeeFactory.GetEmployee(employeeId); if(requestedEmployee != null) { // Return the padded JSON to the caller. CrossDomainUtility.SendJsonP(callback,requestedEmployee.ToJson()); } }
这是SendJsonP():
public static void SendJsonP(string callback,string json) { // Clear any response that has already been prepared. HttpContext.Current.Response.Clear(); // Set the content type to javascript,since we are technically returning Javascript code. HttpContext.Current.Response.ContentType = "application/javascript"; // Create a function call by wrapping the JSON with the callback function name. HttpContext.Current.Response.Write(String.Format("{0}({1})",callback,json)); // Complete this request,to prevent the ASMX web service from doing anything else. HttpContext.Current.ApplicationInstance.CompleteRequest(); }
这里有一些示例jquery代码:
$.ajax({ url: 'http://devserver/service/service.asmx/GetEmployee',dataType: 'jsonp',contentType: 'application/json',data: { employeeId: '123456789' } });
我有[ScriptService]装饰的Web服务,我将我的web.config配置为使用ScriptHandlerFactory处理* .asmx.
我尝试使用ASMX在Content-Type为’application / json’时使用的内置JSON序列化,但是有一些问题:它不能用于JSONP,因为填充需要包裹在.NET不支持的JSON.它也不起作用,因为为了序列化JSON,ASMX需要一个’ContentType:application / json’标头,但jQuery在发送GET请求时忽略ContentType标头(可能是因为它没有发送任何内容).我已经尝试在Global.asax Application_BeginRequest()中设置Request.ContentType =“application / json”但是没有做任何事情.我也尝试使用beforeSend()在jQuery中设置请求标头,但没有运气.
因为我无法使用内置的.NET管道轻松地工作,所以我推出了我自己的技术,它对Response主体执行原始写入(因此SendJsonP()方法).我仍然遇到问题,因为即使GetEmployee()Web方法没有返回值,.NET也会抛出序列化错误,因为它试图将对象序列化为XML,因为我无法传递ContentType的’应用程序/ json’与GET请求.
因此,无论我做什么都无法让jQuery添加ContentType,我想通过使用Fiddler2创建手动请求来测试我的Web服务:
GET http://devserver/service/service.asmx/GetEmployee?callback=createMember&memberId=123456789 User-Agent: Fiddler Content-Type: application/json Host: devserver
…它会出现以下错误,因为我的参数不是JSON:
{"Message":"Invalid JSON primitive: createMember [....] }
毕竟,我还有几个问题:
>有没有办法使用内置的.NET序列化将填充应用于JSON并将其返回给客户端?
>由于看起来我必须自己滚动,在将带参数的JSONP查询发送到ASMX页面时,我的查询字符串应如何显示?它必须是JSON格式,但我尝试了以下内容并收到“无效的JSON原语”错误:
GetEmployee?{callback:“createMember”,memberId:“99999999”}
?getEmployee的回调= {回调: “createMember”}&安培; MEMBERID = {MEMBERID: “123456789”}
>有没有办法让jQuery发送带有JSONP GET请求的ContentType标头?
解决方法
我已经创建了一个新的JsonPUtility助手类,我在HttpApplication.BeginRequest事件中添加了一个调用:
public class Global : System.Web.HttpApplication { protected void Application_BeginRequest(object sender,EventArgs e) { // Requests for JSONP requests must be handled manually due to the limitations of JSONP ASMX. JsonPUtility.ProcessJsonPRequest(); } }
这是JsonPUtility类:
/* * JSON is Javascript Object Notation,a standard way of serializing objects in Javascript and * other languages. For more information see http://www.json.org/. * * JSONP is a technique to enable the execution of Javascript that resides in a different domain. It * works by exploiting the exception granted to the <script> tag which allows content to be loaded * from a different domain. By contrast,making "regular" AJAX calls to a different domain will * not work,usually throwing an "Access Denied" or "No Transport" error. * * JSONP (the "P" stands for "Padding") is regular JSON wrapped in a Javascript function call (the * "Padding"). Take for example this standard JSON object: * { "Name" : "John","Age" : 14,"Gender" : "Male" } * * JSONP will turn that JSON into a valid Javascript function call by using the JSON as an argument * to the callback function provided by the caller. For example,if the caller provides a callback * value of 'processResults',the resulting JSONP looks like this: * processResults({ "Name" : "John","Gender" : "Male" }); * * The processResults() function will then be able to use the JSON object just like a regular object. * Note that the callback function must be implemented on the page that receives the JSONP,otherwise * a standard Javascript error will occur. * * The real "trick" to cross-domain script execution is dynamically creating a "script" tag on the * client for every JSONP request,using the web service URL as the "src" attribute. This will cause * the browser to automatically download and execute the script that is loaded from the URL,* effectively bypassing the same-domain origin policy. */ public static class JsonPUtility { /* * SendJsonP(string callback,string json) * * This method takes the provided 'json' string,wraps it so that it is a parameter to the 'callback' * function,clears any existing response text,writes the resulting Javascript code to the * response,and ends the response. * * For example,given these two parameters... * callback = "callbackFunction" * json = "{ 'FOO': 'BAR','JOO': 'MAR' }" * * ... the following code is returned to the client in an HTTP response with a content-type of * 'application/javascript': * callbackFunction({ 'FOO': 'BAR','JOO': 'MAR' }); * */ public static void SendJsonP(string callback,string json) { // Clear any response that has already been prepared. HttpContext.Current.Response.Clear(); // Set the content type to javascript,since we are technically returning Javascript code. HttpContext.Current.Response.ContentType = "application/javascript"; // Create a function call by wrapping the JSON with the callback function name. HttpContext.Current.Response.Write(String.Format("{0}({1});",json)); // Complete this request,to prevent the ASMX web service from doing anything else. HttpContext.Current.ApplicationInstance.CompleteRequest(); } /* * bool IsJsonPRequest() * * Determines whether or not the current request is for JSONP javascript code. * * This is the criteria for making a JSONP request to this web service: * 1. Include the jsonp parameter. Its value is not important - we recommend using jsonp=true * to increase clarity. * 2. Include the callback=string parameter so we know what function call to wrap around * the requested JSON. */ public static bool IsJsonPRequest() { // Store the context to the current request. var request = HttpContext.Current.Request; // If a 'jsonp' or a 'callback' parameter was not provided,this isn't a JSONP request. if (request.QueryString["jsonp"] == null || String.IsNullOrEmpty(request.QueryString["callback"])) return false; // Since both parameters were provided,this is a jsonp request. return true; } /* * ProcessJsonPRequest() * * Manual processing is required for JSONP requests due to limitations in ASMX web services. */ public static void ProcessJsonPRequest() { // If this isn't a JSONP request,simply return and continue regular request processing. if (!IsJsonPRequest()) return; // Store the context to the HTTP request. var request = HttpContext.Current.Request; // Store the callback function that will be wrapped around the JSON string. string callback = request.QueryString["callback"]; // Create a place to store the object that will be serialized into JSON. object objectForJson = null; // Store the web service method name that is being requested. It is always going to follow the // final slash after the .asmx extension,and will continue until the question mark that marks // the query string. int methodNameStartIndex = request.RawUrl.ToUpper().IndexOf(".ASMX/") + 6; int methodNameLength = (request.RawUrl.IndexOf("?")) - methodNameStartIndex; string requestMethod = request.RawUrl.Substring(methodNameStartIndex,methodNameLength); // Create a place to store the string ID of the object that is going to be looked-up. string lookupId = null; // Based on the request URL,figure out the method that will create a reference for the objectForJson variable. switch (requestMethod) { case "GetEmployee": // Get the employee's ID from the query string. lookupId = request.QueryString["employeeId"]; // If the employee ID was provided,get a Employee object. if (!String.IsNullOrEmpty(lookupId)) objectForJson = Factory.GetEmployee(lookupId); break; case "GetManager": // Get the manager's ID from the query string. lookupId = request.QueryString["managerId"]; // If the manager ID was provided,get a Manager object. if (!String.IsNullOrEmpty(lookupId)) objectForJson = Factory.GetManager(lookupId); break; case "GetOrder": // Get the order ID from the query string. lookupId = request.QueryString["orderId"]; // If the order ID was provided,get the object. if (!String.IsNullOrEmpty(lookupId)) objectForJson = Factory.GetOrder(lookupId); break; default: // If the request method wasn't handled,throw an exception. throw new ArgumentException("Unknown request method '" + requestMethod + "'."); } // Create a .NET framework object to serialize the object into JSON. JavaScriptSerializer jsonSerializer = new JavaScriptSerializer(); // Serialize the object into JSON. If objectForJson is null,the callback function will be passed a parameter of null (e.g. callback(null)). string json = jsonSerializer.Serialize(objectForJson); // Send the JSONP string back to the caller. SendJsonP(callback,json); } }
我希望这可以在将来帮助某人.
谢谢,文斯