【问题标题】:Accept a list (of unknown length) of query string parameters to MVC action接受 MVC 操作的查询字符串参数列表(长度未知)
【发布时间】:2016-08-31 13:30:54
【问题描述】:

我正在构建一个页面,该页面将发送一个包含任意数量的productId_{index}productQuantity_{index} 的查询字符串。

例如:

http://www.website.com/action?productId_1=65&productQuantity_1=1&productId_2=34&productQuantity_2=1

因此,此 URL 会将 65ProductId 映射到 1quantity 并将 34ProductId 映射到 1quantity

我无法更改将其发送到我为什么没有使用 a solution like this 的页面的方式。

我希望能够以某种方式将这种格式的查询映射到强类型的对象列表。

这个问题主要是询问 MVC 的方式来做到这一点,因为我已经有了一个使用 Request 对象的解决方案,但是能够做到这一点,MVC 方式会更好。

【问题讨论】:

  • 给个url例子
  • @StephenMuecke 完成,不确定是否格式化。
  • 使用自定义模型绑定器:stackoverflow.com/questions/32373662/…
  • @stephen.vakil 我会调查一下,谢谢。
  • MVC 方式 是使用您链接到的文章中描述的集合索引器正确生成 url。如果它确实是一个未知长度,那么您就有超过查询字符串限制并引发异常的风险。但是您始终可以创建一个自定义 ModelBinder 来读取 Request 值,然后将其转换为您的模型属性(但这正是您已经在做的事情)

标签: c# asp.net-mvc


【解决方案1】:

您需要将查询字符串的格式设置为更简单易读的格式,如下所示:p=id-quantity,然后您可以使用参数,

例如:http://www.website.com/action?p=65-1&p34-4&p=32-23&p=....

public ActionResult Products(params string[] p)
{
    foreach(var product in p)
    {
        var productId = product.Split('-')[0];
        var quantity = product.Split('-')[1];
    }
}

[通知] 我不建议通过url“GET”发送此类参数,如果使用“POST”表单方法会更好更安全。

【讨论】:

  • OP 已声明 我无法更改发送到页面的方式,如果可以更改,这肯定不是这样做的方法
【解决方案2】:

正如向我建议的那样,我最终使用 custom model binder 为我提供了我的 Action 中的对象列表。

自定义模型绑定器

public class ProductIdAndQuantityListModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var request = controllerContext.HttpContext.Request;

        var products = new List<ProductIdAndQuantity>();

        for (int i = 0; i < 25; i++)
        {
            string productIdKey = string.Format("productid_{0}", i);
            string quantityKey = string.Format("productqty_{0}", i);

            string productIdVal = request[productIdKey];
            string quantityVal = request[quantityKey];

            if (productIdVal == null || quantityVal == null)
                break;

            int productId = Convert.ToInt32(productIdVal);
            int quantity = Convert.ToInt32(quantityVal);

            var productIdAndQuantity = products.FirstOrDefault(x => productId == x.ProductId);

            if (productIdAndQuantity != null)
            {
                productIdAndQuantity.Quantity += quantity;
            }
            else
            {
                products.Add(new ProductIdAndQuantity()
                {
                    ProductId = productId,
                    Quantity = quantity
                });
            }
        }

        return products;
    }
}

Global.asax.cs

protected void Application_Start()
{
    ModelBinders.Binders.Add(typeof(ICollection<Models.Basket.ProductIdAndQuantity>), new ProductIdAndQuantityListModelBinder());
}

动作

public ActionResult Index(ICollection<ProductIdAndQuantity> products)
{
    foreach (var product in products)
    {
        // Do stuff...
    }
}

谢谢大家的帮助!如您所见,它可以采用的参数数量未知但并非无限,这取决于我认为的使用方式。

【讨论】:

  • 由于我基本上已经得到了链接问题的答案,我不确定这个问题是否对其他人有用。
猜你喜欢
  • 2015-04-27
  • 2011-06-12
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-19
  • 2022-01-23
  • 1970-01-01
相关资源
最近更新 更多