2016-04-27 10 views
2

JTokenオブジェクトに着信する動的JSONをバインドするMVCコントローラを取得する方法はありますか?JSONをMVCコントローラのJTokenにバインドする

私はこれを行うことができますAPIのコントローラーを使用する場合:

public class TestController : ApiController 
{ 
    public void Post(JToken json) 
    { 
    } 
} 

をして掲載JSONがJTokenオブジェクトに変換されます。 しかし、MVCコントローラを使用すると、サーバーエラーが発生します。

public class TestController : Controller 
{ 
    [HttpPost] 
    public ActionResult TestAction(JToken json) 
    { 
     return new HttpStatusCodeResult(HttpStatusCode.OK); 
    } 
} 

私が入ってくるデータを取得するが、他の方法を実現するが、私はMVCコントローラでJTokenとしてそれを受け取ることを好むだろう。

私は、カスタムValueProviderFactoryfrom hereを使用しようとしましたが、私はまだサーバーエラーが私のAJAX呼び出しから返され得る:

$.ajax({ 
    url: '/Test/TestAction', //or /api/Test 
    type: 'POST', 
    contentType: 'application/json', 
    data: JSON.stringify({foo:"bar",wibble:"wobble"}) 
}).done(function (res) { 
    alert('ok'); 
}).fail(function (xhr, status, error) { 
    alert('error') 
}); 

UPDATE:

注 - 私は交換した上で述べたようにデフォルトはJsonValueProviderFactoryで、1つはJson.NETに基づいています。

さらなる調査では、この問題はDefaultModelBinder.CreateModelメソッドで発生するようです。 がJTokenインスタンスを作成しようとすると、JTokenが抽象クラスであるため失敗します。 TestActionのパラメータをJObjectに変更しても、オブジェクトの階層構造の下にさらにJTokenのプロパティがあるため、おそらく失敗します。

+0

はfooとwibble特性を有するあなたのJTokenクラスですか? –

+0

@Karthik [Json.NET JToken Class](http://www.newtonsoft.com/json/help/html/t_newtonsoft_json_linq_jtoken.htm) –

+0

okです。そのクラスにはfooとwibbleプロパティが含まれていますか? –

答えて

1

この特定のケースでは、着信JSONのデフォルトシリアライザをwriting a custom ValueProviderFactoryで変更しても機能しませんでした。これは、JTokenが抽象クラスであり、デフォルトのModelBinderが抽象クラスが含まれるモデルインスタンスを作成できないためです。

public class JsonNetModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     if (!IsJSONRequest(controllerContext)) 
     { 
      return base.BindModel(controllerContext, bindingContext); 
     } 

     var request = controllerContext.HttpContext.Request; 
     request.InputStream.Seek(0, SeekOrigin.Begin); 
     var jsonStringData = new StreamReader(request.InputStream).ReadToEnd(); 

     return JsonConvert.DeserializeObject(jsonStringData, bindingContext.ModelType); 
    } 
    private static bool IsJSONRequest(ControllerContext controllerContext) 
    { 
     var contentType = controllerContext.HttpContext.Request.ContentType; 
     return contentType.Contains("application/json"); 
    } 
} 

、次のようにアクションにカスタムModelBinderを使用します:

ソリューションは、アクションのためにcreate a custom ModelBinderにした

public class TestController : Controller 
{ 
    [HttpPost] 
    public ActionResult TestAction([ModelBinder(typeof(JsonNetModelBinder))] JToken json) 
    { 
     return new HttpStatusCodeResult(HttpStatusCode.OK); 
    } 
} 
関連する問題