aspnet / Mvc

[Archived] ASP.NET Core MVC is a model view controller framework for building dynamic web sites with clean separation of concerns, including the merged MVC, Web API, and Web Pages w/ Razor. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
5.62k stars 2.14k forks source link

[ModelBinding] Create a default instance for collection types when no suitable data is present in the request #912

Closed kichalla closed 10 years ago

kichalla commented 10 years ago

This enables easy programming model, like in my scenario i need not do null checks when writing a Linq query...even though we have a workaround, it would be nice to do this by default...

Scenario My request url is /products/search?searchterm=adidas, which indicates that the user doesn't care about a particular categorie and is searching for the term in all categories...

Workaround The user can instantiate the collection himself in the constructor

    public class Product
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public string Manufacturer { get; set; }

        public ProductCategoryType Category { get; set; }
    }

    public enum ProductCategoryType
    {
        Books,
        Movies,
        Sports,
        Clothing
    }

    public class SearchCriteria
    {
        public SearchCriteria()
        {
            // Workaround
            //this.Categories = new List<ProductCategoryType>();
        }

        public List<ProductCategoryType> Categories { get; set; }

        [Required]
        public string SearchTerm { get; set; }
    }

    public class ProductsController :Controller
    {
        private static List<Product> allProducts = null;

        static ProductsController()
        {
            // products
            allProducts = new List<Product>();
            allProducts.Add(new Product()
            {
                Id = 1,
                Name = "Adidas Brazuca 2014 Top Glider",
                Manufacturer = "Adidas",
                Category = ProductCategoryType.Sports
            });
            allProducts.Add(new Product()
            {
                Id = 2,
                Name = "CLR via C#",
                Manufacturer = "Microsoft Press",
                Category = ProductCategoryType.Books
            });
            allProducts.Add(new Product()
            {
                Id = 3,
                Name = "Adidas Mens Mirror Trefoil Logo Tee Shirt",
                Manufacturer = "Adidas",
                Category = ProductCategoryType.Clothing
            });
        }

        [HttpGet]
        public ActionResult Search(SearchCriteria criteria)
        {
            if (!ModelState.IsValid)
            {
                return new HttpStatusCodeResult(400);
            }

            var filteredProdcuts = from category in criteria.Categories
                                   join product in allProducts
                                   on category equals product.Category
                                   where product.Name.IndexOf(criteria.SearchTerm, StringComparison.OrdinalIgnoreCase) >= 0
                                   select product;

            return new ObjectResult(filteredProdcuts);
        }
    }
yishaigalatzer commented 10 years ago

This is the expected behavior, and the work around seems fine.