кросс-доменный вызов с помощью jQuery jsonp в веб-сервис ASP.NET - PullRequest
5 голосов
/ 16 января 2012

Моя проблема - известная проблема, обсуждаемая здесь и здесь . Но даже после прочтения и реализации предложенных решений я не могу выполнить эту работу.

Проблема : веб-сервис, возвращающий 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):
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>


веб-сервис:

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(")");
            }
        }
    }
}

СТОРОНА КЛИЕНТА (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" />

так что я тут делаю не так? Вы можете проверить это сами, это живой веб-сервис. Спасибо за вашу помощь.

1 Ответ

8 голосов
/ 17 января 2012

Кажется, что все настройки и атрибуты созданы для того, чтобы веб-сервис возвращал JSON, но я заметил в вашем запросе jQuery, что вы не указываете тип содержимого данных, которые вы передаете. Я добавил его в код ниже:

$.ajax({
  url: "http://tonofweb.com/MyService.asmx/Sum",
  contentType: "application/json; charset=utf-8",
  data: { x: JSON.stringify("1"), y: JSON.stringify("2") },
  dataType: "jsonp",
  success: function (json) {
    alert(json.d);
  },
  error: function () {
    alert("Hit error fn!");
  }
});

Обратите внимание, я добавил contentType: "application/json; charset=utf-8", в настройки запроса.

Я проверил этот код, перейдя к http://tonofweb.com (который в настоящий момент возвращает 403), включая jQuery с использованием jQuerify букмарклета , а затем сначала запускаю код из вашего вопроса ( без contentType), а затем код, который я разместил выше ( с contentType).

Вот ответы на вкладке Сеть в Инструментах разработчика Chrome:

Без contentType :

<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">"Now i am getting jsop string""2nd param"</string>

С contentType :

{"d":"12"}

Таким образом, второе, по крайней мере, приводит к возвращению JSON с сервера. Поэтому при прочих равных условиях я бы добавил addType.

См. Здесь для объяснения требований для возврата JSON:

ASMX и JSON - Распространенные ошибки и неправильные представления

В HTTP-запросе должен быть указан тип содержимого application / json. это сообщает ScriptService, что он получит свои параметры в виде JSON и что он должен ответить тем же.

Теперь у вас все еще есть другая проблема, и это то, что запрос после завершения вызывает функцию ошибки. Если вы измените dataType: "jsonp" на dataType: "json", это вызовет функцию успеха. Так что что-то в вашей реализации оболочки обратного вызова неверно, потому что jQuery не может обработать ответ как JSONP.

Теперь я также не вижу обратного вызова, завернутого в ответ, для JSONP ответ должен выглядеть примерно так:

jQuery17106476630216930062_1326752446188({"d":"12"})

Я заметил, что вы ссылаетесь на этот пост о том, как сделать ответ JSONP от веб-службы, но вы не следуете совету: вы не используете Response.Filter, вместо этого вы используете Response.Write.

...