2011-01-25 13 views
7

Phil Haack ma doskonałe blog post na temat korzystania z JSON, powiązania danych i sprawdzania poprawności danych.ASP.NET MVC 3 JSONP: Czy to działa z JsonValueProviderFactory?

Wprowadź ograniczenia "tej samej zasady co do zasady pochodzenia przeglądarki". i JSONP, w którym używa się $ .getJSON() do pobierania treści.

Czy jest to wbudowane w MVC 3 sposób, czy muszę postępować zgodnie z radą posts like this? Czy możesz publikować treści? Pytam, ponieważ mój kolega wdrożył między innymi JsonPfilterAttribute, aby to działało. To oczywiście wolał uniknąć że jeśli coś już istnieje w MVC 3.

Edit:

Podsumowanie: wszystko działa z wyjątkiem dostępu do zmiennej POST, czyli w jaki sposób mogę uzyskać dostęp do zmiennej POST w kontekst? (komentarz zaznaczając go w ostatniej sekcji kodu)

I postanowiła wykorzystać ten format zadzwonić serwer:

$.ajax({ 
    type: "GET", 
    url: "GetMyDataJSONP", 
    data: {}, 
    contentType: "application/json; charset=utf-8", 
    dataType: "jsonp", 
    jsonpCallback: "randomFunctionName" 
}); 

który produkuje tej odpowiedzi:

randomFunctionName([{"firstField":"111","secondField":"222"}]); 

A wszystko to działa bardzo dobrze, jeśli używam GET. Jednak nadal nie mogę tego uruchomić jako POST. Oto oryginalny kod opublikowany przez Nathan Bridgewater here. Linia ta nie znajdzie danych POST:

context.HttpContext.Request["callback"]; 

Albo Byłbym dostępu Form w jakiś sposób, lub zatwierdzające danych MVC są stripping się zmienne POST.

W jaki sposób należy napisać context.HttpContext.Request["callback"];, aby uzyskać dostęp do zmiennej POST, czy też MVC usuwa te wartości z jakiegoś powodu?

namespace System.Web.Mvc 
{ public class JsonpResult : ActionResult 
    { public JsonpResult() {} 

     public Encoding ContentEncoding { get; set; } 
     public string ContentType { get; set; } 
     public object Data { get; set; } 
     public string JsonCallback { get; set; } 

     public override void ExecuteResult(ControllerContext context) 
     { if (context == null) 
       throw new ArgumentNullException("context"); 

      this.JsonCallback = context.HttpContext.Request["jsoncallback"]; 

      // This is the line I need to alter to find the form variable: 

      if (string.IsNullOrEmpty(this.JsonCallback)) 
       this.JsonCallback = context.HttpContext.Request["callback"]; 

      if (string.IsNullOrEmpty(this.JsonCallback)) 
       throw new ArgumentNullException(
        "JsonCallback required for JSONP response."); 

      HttpResponseBase response = context.HttpContext.Response; 

      if (!String.IsNullOrEmpty(ContentType)) 
       response.ContentType = ContentType; 
      else 
       response.ContentType = "application/json; charset=utf-8"; 

      if (ContentEncoding != null) 
       response.ContentEncoding = ContentEncoding; 

      if (Data != null) 
      { JavaScriptSerializer serializer = new JavaScriptSerializer(); 
       response.Write(string.Format("{0}({1});", this.JsonCallback, 
        serializer.Serialize(Data))); 
    } } } 

    //extension methods for the controller to allow jsonp. 
    public static class ContollerExtensions 
    { 
     public static JsonpResult Jsonp(this Controller controller, 
       object data) 
     { 
      JsonpResult result = new JsonpResult(); 
      result.Data = data; 
      result.ExecuteResult(controller.ControllerContext); 
      return result; 
     } 
    } 
} 

Odpowiedz

39

miarę otrzymywania ciąg JSON i wiążące go do modelu jest zainteresowane JsonValueProviderFactory czyni tę pracę po wyjęciu z pudełka w ASP.NET MVC 3. Ale nie ma nic wbudowanej do wyprowadzania jsonp. Można napisać zwyczaj JsonpResult:

public class JsonpResult : JsonResult 
{ 
    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["jsoncallback"] as string) ?? request["jsoncallback"]; 
     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(")"); 
     } 
    } 
} 

a potem w swoim działaniu Kontroler:

public ActionResult Foo() 
{ 
    return new JsonpResult 
    { 
     Data = new { Prop1 = "value1", Prop2 = "value2" }, 
     JsonRequestBehavior = JsonRequestBehavior.AllowGet 
    }; 
} 

które mogą być spożywane z innej domeny z $.getJSON():

$.getJSON('http://domain.com/home/foo?jsoncallback=?', function(data) { 
    alert(data.Prop1); 
}); 
+0

edytowany pytanie do refleksji twoja odpowiedź (dobra odpowiedź), potrzebujesz jeszcze jednego kawałka pracującego. –

+2

@Dr. Zim, 'JSONP' działa tylko z żądaniami GET zaimplementowanymi przez jQuery. Nie ma tutaj żadnej magii, jQuery po prostu wstawia znacznik '

Powiązane problemy