0

I am building a page which will have a query string sent to it containing any number of productId_{index} and productQuantity_{index}.

E.g:

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

So this URL would map a ProductId of 65 to a quantity of 1 and a ProductId of 34 to a quantity of 1.

I cannot change how this is sent to the page which I why I have not used a solution like this.

I would like to be able to somehow map the query in this format to a strongly typed list of objects.

This question is meant to be mainly asking about the MVC way to do this, as I already have a solution using the Request object, but being able to do this the MVC way would be preferable.

Manfred Radlwimmer
  • 13,257
  • 13
  • 53
  • 62
Djorge
  • 103
  • 8
  • Give an example of the url –  Aug 31 '16 at 13:32
  • @StephenMuecke Done, not sure about formatting it. – Djorge Aug 31 '16 at 13:35
  • 2
    Use a custom model binder: http://stackoverflow.com/questions/32373662/custom-model-binder-for-asp-net-mvc-on-get-request – stephen.vakil Aug 31 '16 at 13:38
  • @stephen.vakil I will look into this, thanks. – Djorge Aug 31 '16 at 13:39
  • 1
    The _MVC way_ is to generate the url correctly using collection indexers as described in the article you linked to. And if it really is an unknown length, then you at risk of exceeding the query string limit and throwing an exception. But you can always create a custom `ModelBinder` to read the `Request` values and convert then to you model properties (but its just what your already doing anyway) –  Aug 31 '16 at 13:39

2 Answers2

0

you need to format the query string to something simpler and easy to read like this: p=id-quantity, then you can use params,

e.g.: 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];
    }
}

[Notice] I don't recommend sending such parameters via url "GET", it is better and safer if you use "POST" form method.

LazZiya
  • 5,286
  • 2
  • 24
  • 37
  • OP has stated _I cannot change how this is sent to the page_, and if it could be changed, this is certainly not the way to do it –  Aug 31 '16 at 14:00
0

As was suggested to me, I ended up using a custom model binder to give me a list of objects in my Action.

Custom Model Binder

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());
}

Action

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

Thank you you all for your help! As you can see it's an unknown but not unlimited number of parameters it could take which is just down to how I'm using it I think.

Community
  • 1
  • 1
Djorge
  • 103
  • 8
  • Since I've basically ended up with what the answer on the linked question was, I'm not sure this question is going to be useful to anyone else. – Djorge Aug 31 '16 at 15:14