【问题标题】:ASP.NET MVC - Controller parameter not being gathered from form?ASP.NET MVC - 没有从表单中收集控制器参数?
【发布时间】:2009-05-18 20:24:19
【问题描述】:

我们现在在控制器上遇到了这个问题;控制器如下所示:

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", but keywords=="" 在这里我不知所措。为什么关键字没有我们想要的价值?

【问题讨论】:

  • 使用我在下面提供的答案,但对结果语法不满意。只是感觉这不是正确的方法。
  • 你的控制器是如何被实例化的?我遇到了这个问题,我发现是我的 SpringControllerFactory 将我的控制器创建为单例(因此总是使用第一个请求中的值)。
  • 就是这样!我的控制器在我的 Windsor 容器中注册为单例,因此我的 WindsorControllerFactory 返回了一个单例。

标签: jquery asp.net-mvc


【解决方案1】:

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

你的控制器怎么样 实例化?我有这个问题,我 发现是我的 SpringControllerFactory 创建我的 控制器作为单例(因此 总是使用来自 第一个请求)。 – 马克沃思 5 月 19 日在 8:19

就是这样!我的控制器是 作为单身人士注册到我的 温莎集装箱所以我的 WindsorControllerFactory 返回了一个 单身人士。 ——比尔·巴里 5 月 19 日在 18:14

【讨论】:

    【解决方案2】:

    您不想传递 URL 上的值并让 MVC 的路由处理传递值吗?不作为实际变量传递?

    【讨论】:

    • 也许我应该更清楚一点:pageSize 肯定会被传入(在操作内部,它的预期值为 10)我将参数作为表单帖子的一部分发送。 MVC 确实负责将我的所有值从表单移动到方法参数中,除了这个字符串值。
    • 可能想要检查该特定操作的路由
    • 实际呈现的 url 是 ResolveUrl("~/API/Accounts/List") 唯一注册的路由是:routes.MapRoute("Default", "API/{Controller}/{Action} ");
    • 可以尝试专门为该路由注册一条路由,以查看它是否正确通过。
    【解决方案3】:

    如果您要发布值,则可以只使用 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");
    

    ... 函数更新网格(结果){...}

    ... 或者按照其他人的建议,您可以创建一个包含所有可能参数的路线..

    【讨论】:

    • 我可以,但如果可以的话,我想远离魔术弦。 jquery post 将由一个假装实际调用控制器的表达式生成。
    • 不确定你所说的“魔术字符串”是什么意思,假装打电话给控制器……你能解释一下吗?
    • 魔术字符串是实际代表代码的字符串,但不会被编译(而是在运行时评估)。相反,我可以“假装”在我的视图中调用操作,以便使用 (c=>c.List(0,10,"asdf"), " updategrid")%> 该方法采用表达式树并在我的视图中生成必要的 javascript。这样做,我避免了由于在操作中重命名参数(或为此添加新参数,因为我的视图无法编译)而导致的运行时错误。
    • 注意:我使用 spark 作为我的视图,以便我可以将它们编译为我的构建的一部分,它会发现类似的错误。
    • 有趣.. 我以前没见过火花。我会看看。谢谢。
    【解决方案4】:

    使用这个属性:

    [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) {...}
    

    现在关键字具有所需的值

    【讨论】:

    • 现在我已经让它工作了,我唯一剩下的问题是为什么会这样(似乎除了字符串之外的所有东西都会被检索)?
    • 我同意(如果感觉正确,我不会问这个问题)。
    • 您可以发布您注册的路线吗?
    • 实际渲染的url是ResolveUrl("~/API/Accounts/List"),唯一注册的路由是:routes.MapRoute("Default", "API/{Controller}/{Action} ");
    【解决方案5】:

    由于上面指定的属性有效,您是否检查过将 HttpContext.Request.Form 集合的内容与 MVC-Binder-Bound FormCollection 对象进行比较。好像两组有区别。另外,尝试访问 FormCollection 的其他方式 - Get()、GetValue() ...检查 AllKeys 以获取您感兴趣的键???

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

    如果您没有注册路由 myApp/Accounts/List/{page}/{pageSize} 并且页面大小仍在通过,则无需注册 myApp/Accounts /List/{page}/{pageSize}/{keywords} 路由。

    【讨论】:

      【解决方案6】:

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

      /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');
      

      上面的一切对我来说都是正确的,所以除非我错过了什么......我很困惑为什么它不适合你?我哪里做错了?

      【讨论】:

        【解决方案7】:
        [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;
                        }
                    }
                }
            }
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多