将动态JSON发布到MVC4操作

时间:2013-08-26 20:50:45

标签: c# asp.net-mvc asp.net-mvc-4 dynamic asp.net-web-api

使用webapi,可以使用JObjectdynamic作为参数类型将动态JSON发布到操作:

Passing Dynamic JSON Object to Web API - Newtonsoft Example

如果我在MVC4中的非api动作上尝试这个,这似乎不起作用。我的行动签名是:

public async Task<ActionResult> Post(JObject requestObj)

当我使用动态时,我只是得到一个看似非动态的对象。如果我尝试JObject,我会收到以下错误:

[MissingMethodException]: Cannot create an abstract class.

在MVC4中的非api动作中是否可能出现类似的情况?

3 个答案:

答案 0 :(得分:3)

在之前的项目中,我们需要将动态JSON发布到Web Api控制器。我们最终做的是在客户端使用JSON并对其进行Base64编码。然后我们可以简单地将Base64编码的JSON发布到我们的后端。我们的后端然后解码了Base64输入并使用Newtonsoft JSON将其转换为动态对象(实际上它被转换为强类型类,并且后备是动态的)。我同意,这很糟糕,但它确实有用。

答案 1 :(得分:3)

我不确定它是否会有所帮助,但我在上面的评论中提到我最终使用自定义模型绑定器来执行此操作。我挖出了我认为是提出这个问题的原始代码,这就是我最终得到的结果:

    public async Task<ActionResult> Post(dynamic request)
    {
        return await ExecuteRequest(request, "application/json");
    }

和一个自定义模型绑定器如下(它适用于名为&#34; post&#34;或&#34; public&#34;但您可以选择自己的约定 - 并且在所有其他操作上回退到默认值的操作)

public class MyModelBinder : DefaultModelBinder
{        
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var actionName = controllerContext.RouteData.Values["Action"];
        if (controllerContext.Controller.GetType() == typeof(MyController) && actionName != null && 
            (string.Compare(actionName.ToString(), "post", StringComparison.OrdinalIgnoreCase) == 0 ||
            string.Compare(actionName.ToString(), "public", StringComparison.OrdinalIgnoreCase) == 0))
        {
            string contentText;

            using (var stream = controllerContext.HttpContext.Request.InputStream)
            {
                stream.Seek(0, SeekOrigin.Begin);
                using (var reader = new StreamReader(stream))
                    contentText = reader.ReadToEnd();
            }

            if (string.IsNullOrEmpty(contentText)) return (null);

            return JObject.Parse(contentText);
        }

        return base.BindModel(controllerContext, bindingContext);
    }
}

然后在Application_Start的开头注册自定义模型绑定器:

System.Web.Mvc.ModelBinders.Binders.DefaultBinder = new MyModelBinder();

答案 2 :(得分:0)

似乎不可能。阅读MSDN文档https://msdn.microsoft.com/en-us/library/system.web.mvc.controller.aspx

  

动作方法不能具有无界泛型类型参数。一个   unbounded泛型类型参数有一个空参数列表。一个   无界泛型类型也称为开放泛型类型。对于   有关无界泛型类型参数的信息,请参阅本节   类型参数约束中的“无界类型参数”。

你应该从APIController派生,或者创建一个CustomModelBinder(我不确定这个)

看一下以下链接:

posting a JObject to an action

.NET MVC Action parameter of type object

Can abstract class be a parameter in a controller's action?

希望它有所帮助!