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

6
我有以下脚本正在向MVC控制器发送数据:
```html

我有以下脚本正在向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”],但由于它是通过application/json提交的,所以该值为null。
我希望能够从Action Filter中访问此值,这就是为什么我不想修改签名/模型的原因。
3个回答

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内部代码或其他东西读取过了。

虽然这样做是有效的,但我面临的问题是当我读取 onAuthorize 流时,流是空的,因此当控制器接收请求正文时,其中没有任何内容。 - PUG

1
我想要能够从一个Action Filter中访问这个值,这就是为什么我不想修改签名/模型的原因。
如果不改变方法的签名,从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
即使此“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)
{

}

在ActionFilter中,所有的方法都有一个名为“filterContext”的参数。 - Kuqd
没错,抱歉。请检查我的编辑,这次应该没问题了,是我犯了个小错误。 - Kuqd
除了告知他人答案不正确之外,downvote 的目的是什么? - Dismissile
HttpContext.Current.Request.Params 这个东西里面有什么?有没有什么有趣的值? - Kuqd
即使我按照你说的做,我也无法在filterContext.HttpContext.Current.Request.Params中找到“foo”。 - Sr.PEDRO
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接