Problem with pre-select values on PostBack

3 posts, 0 answers
  1. Sebastien Veilleux
    Sebastien Veilleux avatar
    2 posts
    Member since:
    Mar 2016

    Posted 03 Mar Link to this post

    We are using the multiselect control with values pre-selection and ToDataSourceResult instance as describe in documentation.

    Unfortunately, when we post our model and its ModelState is invalid, we return to the view and the control fails to display the pre-selection and the search also stop working.

    Here is some sample snippet.

    Model

    public class CreateModel
    {
        [Required]
        public string Name { get; set; }
     
        public List<int> ProductIds { get; set; }
        public List<Product> InitialProducts { get; set; }
    }
     
    public class Product
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
    }

    Controller

    public class HomeController : Controller
    {
        [HttpGet]
        public ActionResult Create()
        {
            var initialProduct = GetProductList().First();
     
            var model = new CreateModel
            {
                InitialProducts = new List<Product>(new[] { initialProduct }),
                ProductIds = new List<int>(new[] { initialProduct.ProductId })
            };
     
            return View(model);
        }
     
        [HttpPost]
        public ActionResult Create(CreateModel model)
        {
            if (ModelState.IsValid)
                return RedirectToAction("Success");
     
            model.InitialProducts = GetProductList().Where(p => model.ProductIds.Contains(p.ProductId)).ToList();
     
            return View(model);
        }
     
        [HttpGet]
        public ActionResult Success()
        {
            return View();
        }
     
        private static IEnumerable<Product> GetProductList()
        {
            return new[]
            {
                new Product { ProductId = 1, ProductName = "Chai" },
                new Product { ProductId = 2, ProductName = "Chang" },
                new Product { ProductId = 3, ProductName = "Book" },
                new Product { ProductId = 4, ProductName = "Fork" },
                new Product { ProductId = 5, ProductName = "Knife" },
                new Product { ProductId = 6, ProductName = "Spoon" },
                new Product { ProductId = 7, ProductName = "Dish" },
                new Product { ProductId = 8, ProductName = "Glass" },
                new Product { ProductId = 9, ProductName = "Cup" }
            };
        }
         
        [HttpPost]
        public JsonResult GetDataSourceProducts([DataSourceRequest] DataSourceRequest request)
        {
            var products = GetProductList();
     
            if (request.Filters != null && request.Filters.Count > 0)
            {
                var filter = (FilterDescriptor)request.Filters[0];
                products = products.Where(p => p.ProductName.ToLower().Contains((string)filter.Value)).AsEnumerable();
            }
     
            return Json(products.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
        }
    }

    View

    @using (Html.BeginForm("Create", "Home"))
    {
        <div>
            @Html.Kendo().TextBoxFor(m => m.Name)
            @Html.ValidationMessageFor(m => m.Name)
        </div>
     
        <div>
            @(Html.Kendo().MultiSelectFor(m => m.ProductIds)
                  .DataTextField("ProductName")
                  .DataValueField("ProductId")
                  .Placeholder("Select products...")
                  .AutoBind(false)
                  .DataSource(source => source
                      .Custom()
                      .ServerFiltering(true)
                      .Type("aspnetmvc-ajax")
                      .Transport(transport => transport.Read(read => read.Action("GetDataSourceProducts", "Home")))
                      .Schema(schema => schema.Data("Data").Total("Total"))
                  )
                  .Filter(FilterType.Contains)
                  .Value(Model.InitialProducts)
                  )
        </div>
     
        <div>
            <button id="Save" type="submit">Save</button>
        </div>
    }

     

    Is there any kind of work around for this?

  2. Georgi Krustev
    Admin
    Georgi Krustev avatar
    3707 posts

    Posted 07 Mar Link to this post

    Hello Sebastien Veilleux,

    When same view is returned, the MVC wrapper will retrieve the values from the ModelState, because it needs to display the erroneous form state. In this case, the Value of the widget will not be equal to the Model.InitialProducts, but equal to the posted ProductIds. 

    This is an expected behavior, and the only workaround is to remove the values from the ModelState (as it is shown in the aforementioned forum thread).

    Regards,
    Georgi Krustev
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. Sebastien Veilleux
    Sebastien Veilleux avatar
    2 posts
    Member since:
    Mar 2016

    Posted 07 Mar in reply to Georgi Krustev Link to this post

    Thanks it is good to know.

    I use ModelState.Remove("ProductIds") and it works now as I expected.

Back to Top