在 ASP.NET MVC 中,我可以从 POST 主体自动绑定到 JObject 模型吗?
In ASP.NET MVC, can I automatically model bind to a JObject from the POST body?
我有一个控制器操作,它将 JSON 文档作为 POST 请求的主体。我很想通过模型绑定从中自动创建一个 JObject
,如下所示:
[HttpPost]
public ActionResult Index([FromBody] JObject data)
{
// "data" is now a populated JObject object
}
但是我收到有关未创建摘要的错误 class。我试图从 JObject
扩展一些东西,但它也不会那样做。
我知道我可以只读取请求的正文并对其调用 JObject.Parse
(我正在这样做,所以它确实有效),但我从上面的想法看起来更加优雅。
这可能吗?
编辑:实际错误为:
System.MissingMethodException: Cannot create an abstract class.
[MissingMethodException: Cannot create an abstract class.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
[Stack trace continues...]
请求永远不会进入控制器操作。
根据我的研究 JObject
并不抽象,但为了确定,我这样做了:
public class Entry : JObject
然后
public ActionResult Index([FromBody] Entry data)
没用。同样的错误。
你还应该把 JSON 的结构放在你的问题中。完整的请求会更好。在那之前,请尝试以下操作:
将[FromBody] JObject data
替换为[FromBody] dynamic data
或[FromBody] object data
看看它是否遇到了放在操作第一行的断点。
如果是,请查看您的动态实际是什么(类型)。
如果没有,可能是 POST 请求没有 Content-Type: application/json
问题是在反序列化为 JObject
类型时,它会调用创建“JToken”,这就是引发异常的地方。这是确切的例外:
Cannot create an abstract class. Object type
Newtonsoft.Json.Linq.JToken
可能有两个问题。我更改了两处,现在可以使用了,但我不能 100% 确定哪一个修复了它。
这是我更改的两件事 --
首先,我继承自 ApiController
而不仅仅是 Controller
。我不确定这是否与它有关。
其次,其他答案之一指出我需要 application/json
的正确 Content-Type
header。好吧,事实并非如此。 Content-Type
header 被设置为特定于我们正在集成的软件的一些疯狂值。
所以,在 Application_Start
中,我添加了这个:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("[crazy ass content-type header value]"));
然后成功了。
我怀疑是第二件事修复了它。由于 header 没有告诉模型活页夹它正在传入 JSON,活页夹试图从头开始创建 JObject
object 并通过反射分配属性 运行 变成 JToken
抽象的问题。一旦它知道它正在处理 JSON,它就知道只需调用 JObject.Parse
。
我已经为 JToken 编写了一个 ASP.NET Core ModelBinder,您可以安装它 - https://github.com/mcintyre321/AspNetCoreJTokenModelBinder
绑定到 JToken,然后在你的控制器中使用 .ToObject<T>()
我有一个控制器操作,它将 JSON 文档作为 POST 请求的主体。我很想通过模型绑定从中自动创建一个 JObject
,如下所示:
[HttpPost]
public ActionResult Index([FromBody] JObject data)
{
// "data" is now a populated JObject object
}
但是我收到有关未创建摘要的错误 class。我试图从 JObject
扩展一些东西,但它也不会那样做。
我知道我可以只读取请求的正文并对其调用 JObject.Parse
(我正在这样做,所以它确实有效),但我从上面的想法看起来更加优雅。
这可能吗?
编辑:实际错误为:
System.MissingMethodException: Cannot create an abstract class.
[MissingMethodException: Cannot create an abstract class.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
[Stack trace continues...]
请求永远不会进入控制器操作。
根据我的研究 JObject
并不抽象,但为了确定,我这样做了:
public class Entry : JObject
然后
public ActionResult Index([FromBody] Entry data)
没用。同样的错误。
你还应该把 JSON 的结构放在你的问题中。完整的请求会更好。在那之前,请尝试以下操作:
将[FromBody] JObject data
替换为[FromBody] dynamic data
或[FromBody] object data
看看它是否遇到了放在操作第一行的断点。
如果是,请查看您的动态实际是什么(类型)。
如果没有,可能是 POST 请求没有 Content-Type: application/json
问题是在反序列化为 JObject
类型时,它会调用创建“JToken”,这就是引发异常的地方。这是确切的例外:
Cannot create an abstract class. Object type Newtonsoft.Json.Linq.JToken
可能有两个问题。我更改了两处,现在可以使用了,但我不能 100% 确定哪一个修复了它。
这是我更改的两件事 --
首先,我继承自 ApiController
而不仅仅是 Controller
。我不确定这是否与它有关。
其次,其他答案之一指出我需要 application/json
的正确 Content-Type
header。好吧,事实并非如此。 Content-Type
header 被设置为特定于我们正在集成的软件的一些疯狂值。
所以,在 Application_Start
中,我添加了这个:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("[crazy ass content-type header value]"));
然后成功了。
我怀疑是第二件事修复了它。由于 header 没有告诉模型活页夹它正在传入 JSON,活页夹试图从头开始创建 JObject
object 并通过反射分配属性 运行 变成 JToken
抽象的问题。一旦它知道它正在处理 JSON,它就知道只需调用 JObject.Parse
。
我已经为 JToken 编写了一个 ASP.NET Core ModelBinder,您可以安装它 - https://github.com/mcintyre321/AspNetCoreJTokenModelBinder
绑定到 JToken,然后在你的控制器中使用 .ToObject<T>()