微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

jquery – JSONP和ASMX Web服务

我正在试图弄清楚如何使用jQuery对ASMX Web服务进行JSONP调用.这些只是我已经阅读过的一些页面,但没有找到任何解决方案:

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标头?

解决方法

我刚刚决定手动处理JSONP请求.在我的解决方案中,用户必须通过GET请求提供两个查询字符串参数,以表明他们需要JSONP结果:callback = callbackFunctionName和jsonp = true.如果收到这两个,我将手动处理,否则请求将继续到标准ASMX处理器.

我已经创建了一个新的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);
    }
}

我希望这可以在将来帮助某人.

谢谢,文斯

原文地址:https://www.jb51.cc/jquery/180902.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐