Ответ 1
Хорошо, я в конце концов понял это сам. Поскольку мне так трудно найти полное рабочее решение в Интернете, я решил документировать свое рабочее решение здесь.
Ответ JSONP - это стандартная строка JSON, заключенная в вызов функции. ASP.NET, похоже, не дает возможности вернуть ответ в этом формате напрямую, но это очень просто сделать сами. Однако вы должны переопределить метод JSON по умолчанию.
Ниже приведен пример JSONP.
functionName({ name: 'value';});
.. теперь этот бит:
{ name: 'value';}
является стандартным JSON, который предоставит вам любой последовательный сериализатор JSON, поэтому все, что нам нужно сделать, - это привязка к оболочке вызова функций. К сожалению, это означает, что мы должны "освободить" (или обойти) существующую кодировку JSON, которая прозрачно обрабатывается каркасом при возврате объекта из функции веб-службы.
Это делается путем полного перекрытия ответа от функции веб-службы путем записи JSONP в выходной поток (Response) с использованием нашего собственного кода. Это на самом деле довольно просто, и я привел пример ниже.
Вы можете использовать встроенный DataContractJsonSerializer (из пространства имен System.Runtime.Serialization.Json в ASP.NET 3.5+) или 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();
}
Затем этот метод можно вызвать, используя следующий код 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
}