从内容类型为application / json的请求中检索值

时间:2012-05-31 15:55:52

标签: c# asp.net-mvc json

我有以下脚本将数据发送到MVC中的控制器:

$.ajax({
    url: '/products/create',
    type: 'post',
    contentType: 'application/json; charset=utf-8',
    data: JSON.stringify({
        'name':'widget',
        'foo':'bar'
    })
});

我的控制器看起来像这样:

[HttpPost]
public ActionResult Create(Product product)
{
    return Json(new {success = true});
}

public class Product 
{ 
    public string name { get; set; }
}

有没有办法在没有

的控制器动作中获得“foo”变量
  • 修改模型
  • 修改操作的签名

如果是常规表单提交,我可以访问Request.Form [“foo”],但是这个值为null,因为它是通过application / json提交的。

我希望能够从动作过滤器访问此值,这就是我不想修改签名/模型的原因。

3 个答案:

答案 0 :(得分:4)

我想今天几乎完全一样,发现这个问题没有答案。我也用与Mark相似的解决方案解决了它。

这对我来说非常适合我在asp.net MVC 4.也许可以帮助其他人阅读这个问题,即使它是旧问题。

        [HttpPost]
        public ActionResult Create()
        {
            string jsonPostData;
            using (var stream = Request.InputStream)
            {
                stream.Position = 0;
                using (var reader = new System.IO.StreamReader(stream))
                {
                    jsonPostData = reader.ReadToEnd();
                }
            }
            var foo = Newtonsoft.Json.JsonConvert.DeserializeObject<IDictionary<string, object>>(jsonPostData)["foo"];

            return Json(new { success = true });
        }

重要的部分是重置流的位置,因为它已被某些MVC内部代码或其他内容读取。

答案 1 :(得分:1)

  

我希望能够从动作过滤器中访问此值   这就是为什么我不想修改签名/模型。

在不更改方法签名的情况下访问Action过滤器中的值会很棘手。从post开始,可以更好地理解原因。

此代码适用于授权过滤器或模型绑定之前运行的代码。

public class CustomFilter : FilterAttribute, IAuthorizationFilter
  {
    public void OnAuthorization(AuthorizationContext filterContext)
    {
      var request = filterContext.RequestContext.HttpContext.Request;

      var body = request.InputStream;
      var encoding = request.ContentEncoding;
      var reader = new StreamReader(body, encoding);
      var json = reader.ReadToEnd();

      var ser = new JavaScriptSerializer();

      // you can read the json data from here
      var jsonDictionary = ser.Deserialize<Dictionary<string, string>>(json); 

      // i'm resetting the position back to 0, else the value of product in the action  
      // method will  be null.
      request.InputStream.Position = 0; 
    }
  }

答案 2 :(得分:-2)

即使这个'foo'没有绑定,它也会在你的动作过滤器中通过:

filterContext.HttpContext.Current.Request.Params

如果看到参数,请查看这些集合。

所以是的,只需创建您的动作过滤器,不要更改它将起作用的签名。

以防万一调试过滤器以确定值的位置。

最后,您需要在global.asax中注册json的值提供程序:

protected void Application_Start() 
{
  RegisterRoutes(RouteTable.Routes);
  ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
}

您的参数也是错误的,它需要更像:

$.ajax({
    url: '/products/create',
    type: 'post',
    contentType: 'application/json; charset=utf-8',
    data: JSON.stringify({
        name:'widget',
        foo:'bar'
    })
});

没有引用。

编辑(更准确地说):

您的过滤器将包含这些方法

public void OnActionExecuting(ActionExecutingContext filterContext)
{

}
public void OnActionExecuted(ActionExecutedContext filterContext)
{

}