6

我有以下脚本将数据发送到 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 提交的。

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

4

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

于 2013-09-27T12:27:34.500 回答
1

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

如果不更改方法的签名,则从 Action 过滤器访问值会很棘手。从这篇文章中可以更好地理解原因。

此代码将在授权过滤器或模型绑定之前运行的代码中运行。

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; 
    }
  }
于 2012-06-01T04:14:59.227 回答
-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)
{

}
于 2012-05-31T16:00:31.660 回答