ASP.NET MVC - 控制器参数未从表单中收集?

时间:2009-05-18 20:24:19

标签: jquery asp.net-mvc

我们现在正在控制器遇到这个问题;控制器看起来像这样:

public class AccountsController:Controller {
    public ActionResult List(int? page, int? pageSize, string keywords) {...}
}

我们通过jquery发布到此页面:

$.post("/myapp/Accounts/List",
       {"page":0,"pageSize":10,"keywords":"asdf"}, 
       updategrid,
       "json");
...
function updategrid(result) {...}

在操作中:Request.Form [“keywords”] ==“asdf”,但关键字==“”,在这里我不知所措。为什么关键字没有我们想要的价值?

7 个答案:

答案 0 :(得分:1)

引用Mark Worth评论提供的答案......

  

你的控制器是怎样的   实例化?我遇到了这个问题   发现这是我的   SpringControllerFactory创建我的   控制器作为单身人士(因此   总是使用来自的值   第一次请求)。 - 马克沃思5月19日在   8:19

     

就是这样!我的控制器是   注册成为我的单身人士   温莎容器让我   WindsorControllerFactory返回了一个   单身。 - 比尔巴里5月19日   18:14

答案 1 :(得分:0)

你不想传递URL上的值,让MVC的路由负责传递值吗?不作为实际变量传递?

答案 2 :(得分:0)

如果要发布值,可以使用FormCollection ..

public class AccountsController:Controller {
public ActionResult List(int? page, FormCollection collection) {

  string keywords=collection["keywords"];
  ....
}

}

另外,对于帖子,你可以将id附加到url并将其他参数放在json中。我也认为没有必要在json中将你的属性名称放在引号中。

$.post("/myapp/Accounts/List/"+page,
   {pageSize:10,keywords:"asdf"}, 
   updategrid,
   "json");

... function updategrid(result){...}

......或者像其他人建议的那样,你可以创建一个包含所有可能参数的路线。

答案 3 :(得分:0)

使用此属性:

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
public class StringParamFilterAttribute:ActionFilterAttribute {
    public string Param { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext) {
        filterContext.ActionParameters[Param] = filterContext.HttpContext.Request[Param];
    }
}

我能够在动作上放置一个属性,以便将此参数提供给方法:

[StringParamFilter(Param="keywords")]
public ActionResult List(int? page, int? pageSize, string keywords) {...}

现在关键字具有所需的值

答案 4 :(得分:0)

由于上面指定的属性有效,您是否检查过将HttpContext.Request.Form集合的内容与MVC-Binder-Bound FormCollection对象进行比较。似乎两组之间存在差异。另外,尝试其他方式访问FormCollection - Get(),GetValue()...检查AllKeys是否有你感兴趣的密钥???

另外,关于路线注册的想法......

如果您没有注册myApp / Accounts / List / {page} / {pageSize}路由并且页面大小仍然存在,那么可以理所当然地说无需注册myApp / Accounts / List / {page} / {pageSize} / {keywords} route。

答案 5 :(得分:0)

这很奇怪,因为我机器上的代码有效。当您直接从浏览器请求URL(没有jQuery .post()调用)时会发生什么:

/myapp/Accounts/List?page=0&pageSize=10&keywords=asdf

生成一个GET请求(而不是jQuery .post()方法生成的POST请求 - 但是应该填充操作方法参数)。

出于调试目的,您可能希望将操作方法​​更改为:

public ActionResult List(int? page, int? pageSize, string keywords)
{
     return Content(String.Format("page = {0}, pageSize = {1}, keywords = {2}",
                    page, pageSize, keywords));
}

如果可以,那么下一步就是用类似的东西来测试你的jQuery调用(将返回的数据格式从JSON更改为文本):

 $.post('/myapp/Accounts/List',
        { 'page' : 0, 'pageSize' : 10, 'keywords' : 'asdf' },
        function(result) {
           alert(result);
        },
        'text');

以上所有内容对我来说都是正确的,所以除非我遗漏了什么......我很困惑为什么它对你不起作用?我哪里出错了?

答案 6 :(得分:0)

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public class JsonParametersFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            string contentType = filterContext.HttpContext.Request.ContentType;

            if (string.IsNullOrEmpty(contentType))
                return;

            if (!contentType.Contains("application/json"))
                return;

            string paramValue;

            using (var reader = new StreamReader(filterContext.HttpContext.Request.InputStream))
                paramValue = reader.ReadToEnd();

            var serializer = new JavaScriptSerializer();
            var rawResult = (IDictionary<string, object>)serializer.DeserializeObject(paramValue);

            var keys = new List<string>(filterContext.ActionParameters.Keys);

            foreach (var key in keys)
            {
                object value = null;

                if (rawResult.TryGetValue(key, out value))
                {
                    filterContext.ActionParameters[key] = value;
                }
            }
        }
    }

这将尝试填充输入流中的所有参数值。