ASP.net MVC에서 JSONP 반환
도메인 전체에서 JSON을 반환하려고 합니다.이 방법은 순수 JSON이 아닌 JSONP를 사용하는 것으로 알고 있습니다.
저는 ASP.net MVC를 사용하고 있기 때문에, 이 머신을 확장하려고 생각하고 있습니다.JsonResult
컨트롤러를 입력하고 확장하여 Jsonp 메서드를 구현하도록 합니다.
이게 최선의 방법인가요 아니면 빌트인인가요?ActionResult
그게 더 나을까?
솔루션:나는 먼저 가서 그것을 했다.참고로 새로운 결과를 추가했습니다.
public class JsonpResult : System.Web.Mvc.JsonResult
{
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
{
response.ContentType = ContentType;
}
else
{
response.ContentType = "application/javascript";
}
if (ContentEncoding != null)
{
response.ContentEncoding = ContentEncoding;
}
if (Data != null)
{
// The JavaScriptSerializer type was marked as obsolete prior to .NET Framework 3.5 SP1
#pragma warning disable 0618
HttpRequestBase request = context.HttpContext.Request;
JavaScriptSerializer serializer = new JavaScriptSerializer();
response.Write(request.Params["jsoncallback"] + "(" + serializer.Serialize(Data) + ")");
#pragma warning restore 0618
}
}
}
모든 컨트롤러의 슈퍼클래스에 대한 몇 가지 방법도 있습니다.
protected internal JsonpResult Jsonp(object data)
{
return Jsonp(data, null /* contentType */);
}
protected internal JsonpResult Jsonp(object data, string contentType)
{
return Jsonp(data, contentType, null);
}
protected internal virtual JsonpResult Jsonp(object data, string contentType, Encoding contentEncoding)
{
return new JsonpResult
{
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding
};
}
마법처럼 작동한다.
작업 필터를 정의하지 않으려면 다음과 같은 간단한 해결책이 있습니다.
jQuery를 사용하는 클라이언트 측 코드:
$.ajax("http://www.myserver.com/Home/JsonpCall", { dataType: "jsonp" }).done(function (result) {});
MVC 컨트롤러 액션쿼리 문자열과 함께 제공된 콜백 함수를 실행하는 JavaScript 코드로 콘텐츠 결과를 반환합니다.또한 응답에 대한 JavaScript MIME 유형도 설정합니다.
public ContentResult JsonpCall(string callback)
{
return Content(String.Format("{0}({1});",
callback,
new JavaScriptSerializer().Serialize(new { a = 1 })),
"application/javascript");
}
컨트롤러를 Jsonp() 메서드로 서브 분류하는 것이 아니라 터치 클리너처럼 느껴지기 때문에 확장 메서드루트를 선택했습니다.JsonpResult의 장점은 JsonResult와 동일한 방법으로 테스트할 수 있다는 것입니다.
나는 했다:
public static class JsonResultExtensions
{
public static JsonpResult ToJsonp(this JsonResult json)
{
return new JsonpResult { ContentEncoding = json.ContentEncoding, ContentType = json.ContentType, Data = json.Data, JsonRequestBehavior = json.JsonRequestBehavior};
}
}
이렇게 하면 Jsonp() 오버로드를 모두 생성할 필요가 없습니다.JsonResult를 Jsonp 오버로드로 변환하기만 하면 됩니다.
Ranju의 블로그 투고(일명 "This blog post I found")는 훌륭합니다.이 글을 읽으면 컨트롤러가 같은 도메인 JSON 및 크로스 도메인 JSONP 요구를 (액션에서) 추가 코드 없이 우아하게 처리할 수 있도록 하기 위해 아래의 솔루션을 강화할 수 있습니다.
단, "give me the code" 타입의 경우 블로그가 다시 사라질 경우를 대비해서 여기에 있습니다.
컨트롤러(이 스니펫은 신규/비블로그 코드):
[AllowCrossSiteJson]
public ActionResult JsonpTime(string callback)
{
string msg = DateTime.UtcNow.ToString("o");
return new JsonpResult
{
Data = (new
{
time = msg
})
};
}
JsonpResult는 다음 훌륭한 블로그 투고에서 찾을 수 있습니다.
/// <summary>
/// Renders result as JSON and also wraps the JSON in a call
/// to the callback function specified in "JsonpResult.Callback".
/// http://blogorama.nerdworks.in/entry-EnablingJSONPcallsonASPNETMVC.aspx
/// </summary>
public class JsonpResult : JsonResult
{
/// <summary>
/// Gets or sets the javascript callback function that is
/// to be invoked in the resulting script output.
/// </summary>
/// <value>The callback function name.</value>
public string Callback { get; set; }
/// <summary>
/// Enables processing of the result of an action method by a
/// custom type that inherits from <see cref="T:System.Web.Mvc.ActionResult"/>.
/// </summary>
/// <param name="context">The context within which the
/// result is executed.</param>
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
HttpResponseBase response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
response.ContentType = ContentType;
else
response.ContentType = "application/javascript";
if (ContentEncoding != null)
response.ContentEncoding = ContentEncoding;
if (Callback == null || Callback.Length == 0)
Callback = context.HttpContext.Request.QueryString["callback"];
if (Data != null)
{
// The JavaScriptSerializer type was marked as obsolete
// prior to .NET Framework 3.5 SP1
#pragma warning disable 0618
JavaScriptSerializer serializer = new JavaScriptSerializer();
string ser = serializer.Serialize(Data);
response.Write(Callback + "(" + ser + ");");
#pragma warning restore 0618
}
}
}
주의: @Ranju 등의 OP 코멘트에 따라 커뮤니티 위키로서 Ranju의 블로그 투고에서 "최소한" 기능 코드를 게시할 가치가 있다고 생각했습니다.Ranju가 자신의 블로그에 자유롭게 사용하기 위해 위와 같은 코드를 추가했다고 해도 무방합니다만, 여기서 그의 말을 베끼지는 않겠습니다.
ASP의 경우.ASP가 아닌 NET Core.넷 MVC
이것은 ASP용으로 맞춤형 버전입니다.답변에 존재하는 솔루션의 NET Core
public class JsonpResult : JsonResult
{
public JsonpResult(object value) : base(value)
{
}
public override async Task ExecuteResultAsync(ActionContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
HttpResponse response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType))
response.ContentType = ContentType;
else
response.ContentType = "application/javascript";
if (Value != null)
{
HttpRequest request = context.HttpContext.Request;
string serializedJson = JsonConvert.SerializeObject(Value);
string result = $"{request.Query["callback"]}({serializedJson})";
await response.WriteAsync(result);
}
}
}
자극과 란주5가 참고한 글은 매우 유용하고 상황을 명확히 했다.
하지만 나는 온라인에서 찾은 MVC 코드와 관련하여 확장자를 사용하고 하위 분류하는 것에 대해 머리를 긁적거렸다.
저를 사로잡은 두 가지 요점이 있습니다.
- ActionResult에서 가져온 코드인데 ExecuteResult에 XML 또는 JSON을 반환하는 코드가 있습니다.
- 그런 다음 Generics 기반의 Action Result를 생성하여 반환한 데이터 유형에 관계없이 동일한 Execute Results가 사용되도록 했습니다.
따라서 JSONP를 반환하는 메커니즘을 추가하기 위해 추가 확장이나 하위 분류가 필요하지 않습니다.기존 ExecuteResults를 변경하기만 하면 됩니다.
이그제큐트 결과를 재코딩하지 않고 Json Result를 도출하거나 확장하는 방법을 찾고 있었습니다.JSONP는 사실상 프리픽스와 서픽스가 붙은 JSON 문자열이기 때문에 아까운 것 같습니다.단, 밑줄 ExecuteResult에서는 respone이 사용됩니다.write - 따라서 가장 안전한 변경 방법은 다양한 게시물이 제공하는 대로 ExecuteResults를 다시 코드화하는 것입니다.
도움이 된다면 몇 가지 코드를 올릴 수 있지만, 이 스레드에는 이미 꽤 많은 코드가 있습니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
namespace Template.Web.Helpers
{
public class JsonpResult : JsonResult
{
public JsonpResult(string callbackName)
{
CallbackName = callbackName;
}
public JsonpResult()
: this("jsoncallback")
{
}
public string CallbackName { get; set; }
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
var request = context.HttpContext.Request;
var response = context.HttpContext.Response;
string jsoncallback = ((context.RouteData.Values[CallbackName] as string) ?? request[CallbackName]) ?? CallbackName;
if (!string.IsNullOrEmpty(jsoncallback))
{
if (string.IsNullOrEmpty(base.ContentType))
{
base.ContentType = "application/x-javascript";
}
response.Write(string.Format("{0}(", jsoncallback));
}
base.ExecuteResult(context);
if (!string.IsNullOrEmpty(jsoncallback))
{
response.Write(")");
}
}
}
public static class ControllerExtensions
{
public static JsonpResult Jsonp(this Controller controller, object data, string callbackName = "callback")
{
return new JsonpResult(callbackName)
{
Data = data,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
public static T DeserializeObject<T>(this Controller controller, string key) where T : class
{
var value = controller.HttpContext.Request.QueryString.Get(key);
if (string.IsNullOrEmpty(value))
{
return null;
}
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
return javaScriptSerializer.Deserialize<T>(value);
}
}
}
//Example of using the Jsonp function::
// 1-
public JsonResult Read()
{
IEnumerable<User> result = context.All();
return this.Jsonp(result);
}
//2-
public JsonResult Update()
{
var models = this.DeserializeObject<IEnumerable<User>>("models");
if (models != null)
{
Update(models); //Update properties & save change in database
}
return this.Jsonp(models);
}
위의 솔루션은 좋은 작업 방법이지만 Json을 반환하는 메서드가 아닌 새로운 유형의 결과로 확장해야 합니다.결과에는 자신의 결과 유형을 반환하는 메서드를 작성해야 합니다.
public JsonPResult testMethod() {
// use the other guys code to write a method that returns something
}
public class JsonPResult : JsonResult
{
public FileUploadJsonResult(JsonResult data) {
this.Data = data;
}
public override void ExecuteResult(ControllerContext context)
{
this.ContentType = "text/html";
context.HttpContext.Response.Write("<textarea>");
base.ExecuteResult(context);
context.HttpContext.Response.Write("</textarea>");
}
}
언급URL : https://stackoverflow.com/questions/758879/asp-net-mvc-returning-jsonp
'sourcecode' 카테고리의 다른 글
유성 전개 앱에서 데이터를 쉽게 내보낼 수 있는 방법이 있나요? (0) | 2023.03.09 |
---|---|
발신기지 'Authorization' 헤더와 jquery.ajax()의 교차 발신 (0) | 2023.03.09 |
urlib2 및 json (0) | 2023.03.09 |
react render()가 componentDidMount()보다 먼저 호출되고 있습니다. (0) | 2023.03.04 |
React.js에서 리치 데이터 구조 편집 (0) | 2023.03.04 |