Asp.net 在MVC控制器中将JSON绑定到JToken

Asp.net 在MVC控制器中将JSON绑定到JToken,asp.net,asp.net-mvc,asp.net-web-api,asp.net-mvc-5,json.net,Asp.net,Asp.net Mvc,Asp.net Web Api,Asp.net Mvc 5,Json.net,有没有办法让MVC控制器将传入的动态JSON绑定到JToken对象 如果我使用API控制器,我可以做到: public class TestController : ApiController { public void Post(JToken json) { } } 发布的json被转换成JToken对象。 但是,如果使用MVC控制器,则会导致服务器错误 public class TestController : Controller { [HttpPost]

有没有办法让MVC控制器将传入的动态JSON绑定到
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接收数据

我曾尝试使用自定义的
ValueProviderFactory
,但我的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')
});
更新:

注意-如上所述,我已将默认的
JsonValueProviderFactory
替换为基于
Json.NET
的工厂


经过进一步调查,问题似乎出现在
DefaultModelBinder.CreateModel
方法中。当
DefaultModelBinder
尝试创建
JToken
实例时,它会失败,因为
JToken
是一个抽象类。即使我将
TestAction
参数更改为
JObject
,它仍然会失败,这可能是因为在对象继承权的更深处有
JToken
属性。

在这种特殊情况下,通过更改传入JSON的默认序列化程序不起作用。这似乎是因为
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
,如下所示:

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

你的JToken类有foo和wibble属性吗?@Karthik这是确定的。该类是否包含foo和wibble属性?ASP.Net MVC使用的是
JavaScriptSerializer
而不是Json.Net。要切换,请参阅和。@dbc谢谢,Jason Butera在第二个链接中的回答提供了解决方案,我还需要创建一个基于Json.NET的自定义ModelBinder。你想提供一个答案,我会接受它,还是我应该展示解决方案?