Breakpoint not hit

13 posts, 0 answers
  1. Alberto
    Alberto avatar
    20 posts
    Member since:
    May 2019

    Posted 21 Aug 2019 Link to this post

    Hi There,

    I'm studying grid samples and don't understand why deleting a record in the ForeignKey grid sample a breakpoint on the method below is not hid during Delete operation. I ask because I replicated the same approach in my application (with Customers and Countries tables) and I get a NullReferenceException in this method every time because the last parameter is null. What am I missing?

    Thanks.

            [AcceptVerbs(HttpVerbs.Post)]
          public ActionResult ForeignKeyColumn_Destroy([DataSourceRequest] DataSourceRequest request,
              [Bind(Prefix = "models")]IEnumerable<ProductViewModel> products)
          {
              foreach (var product in products)
              {
                  productService.Destroy(product);
              }
     
              return Json(products.ToDataSourceResult(request, ModelState));
          }
  2. Nikolay
    Admin
    Nikolay  avatar
    297 posts

    Posted 22 Aug 2019 Link to this post

    Hello Alberto,

    In order to hit a breakpoint in the method you need to save after the deletion is made. Only deleting a record does not execute the request.

    From your explanation I am not sure if you are getting a reference error or the breakpoint is not hit? 

    If the above does not help you resolve the situation, please provide more details to showcase the issue so I can have a better look at it and offer a more concrete answer.

    Regards,
    Nikolay
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  3. Alberto
    Alberto avatar
    20 posts
    Member since:
    May 2019

    Posted 22 Aug 2019 Link to this post

    Thanks for answering so quickly Nikolay,

    Here is my code. I'm trying to use the Grid for the first time in my own application.

    public class CustomerViewModel
    {
        [ScaffoldColumn(false)]
        public int CustomerID { get; set; }
     
        [DisplayName("First name")]
        public string FirstName { get; set; }
     
        [DisplayName("Last name")]
        public string LastName { get; set; }
     
        public string Phone { get; set; }
     
        public string Company { get; set; }
     
        public string Address1 { get; set; }
     
        public string Address2 { get; set; }
     
        public string City { get; set; }
     
        [DisplayName("State/Province")]
        public string StateProvince { get; set; }
     
        [DisplayName("Zip/Postal code")]
        public string ZipPostalCode { get; set; }
     
        [UIHint("ClientCountry")]
        public CountryViewModel Country { get; set; }
     
        [DisplayName("Country")]
        public string CountryID { get; set; }
     
        [DisplayName("VAT number")]
        public string VatNumber { get; set; }
     
        [DisplayName("Codice destinatario SDI")]
        public string DestCode { get; set; }
         
        public string Notes { get; set; }
     
        [ScaffoldColumn(false)]
        public int OrderCount { get; set; }
    }
     
    public class CountryViewModel
    {
        public string CountryID { get; set; }
     
        public string CountryName { get; set; }
    }
     
    public class CustomerService : IDisposable
    {
        private static bool UpdateDatabase = false;
     
        private devDeptMvcContext entities;
     
        public CustomerService(devDeptMvcContext entities)
        {
            this.entities = entities;
        }
     
        public IList<CustomerViewModel> GetAll()
        {
            var result = HttpContext.Current.Session["Customers"] as IList<CustomerViewModel>;
     
            if (result == null || UpdateDatabase)
            {
                result = entities.Customers.Select(customer => new CustomerViewModel
                {
                    CustomerID = customer.customerID,
                    FirstName = customer.firstName,
                    LastName = customer.lastName,
                    Phone = customer.phone,
                    Company = customer.company,
                    Address1 = customer.address1,
                    Address2 = customer.address2,
                    City = customer.city,
                    StateProvince = customer.stateProvince,
                    ZipPostalCode = customer.zipPostalCode,
                    CountryID = customer.countryID,
                    Country = new CountryViewModel()
                    {
                        CountryID = customer.Country.countryID,
                        CountryName = customer.Country.countryName
                    },
                    VatNumber = customer.vatNumber,
                    DestCode = customer.destCode,
                    Notes = customer.notes,
                    OrderCount = customer.Orders.Count
                }).ToList();
     
                HttpContext.Current.Session["Customers"] = result;
            }
     
            return result;
        }
     
        public IEnumerable<CustomerViewModel> Read()
        {
            return GetAll();
        }
         
        public void Create(CustomerViewModel customer)
        {
            if (!UpdateDatabase)
            {
                /*var first = GetAll().OrderByDescending(e => e.CustomerID).FirstOrDefault();
                var id = (first != null) ? first.CustomerID : 0;
     
                customer.CustomerID = id + 1;
     
                if (customer.CustomerID == null)
                {
                    customer.CustomerID = 1;
                }*/
     
                if (customer.Country == null)
                {
                    customer.Country = new CountryViewModel() {CountryID = "ITA", CountryName = "Italy"};
                }
     
                GetAll().Insert(0, customer);
            }
            else
            {
                var entity = new Customer();
     
                entity.firstName = customer.FirstName;
                entity.lastName = customer.LastName;
                entity.company = customer.Company;
                entity.address1 = customer.Address1;
                entity.address2 = customer.Address2;
                entity.city = customer.City;
                entity.stateProvince = customer.StateProvince;
                entity.zipPostalCode = customer.ZipPostalCode;
                entity.vatNumber = customer.VatNumber;
                entity.destCode = customer.DestCode;
                entity.notes = customer.Notes;
     
                entity.countryID = customer.CountryID;
     
                /*if (entity.countryID == null)
                {
                    entity.countryID = "ITA";
                }*/
     
                if (customer.Country != null)
                {
                    entity.countryID = customer.Country.CountryID;
                }
     
                entities.Customers.Add(entity);
                entities.SaveChanges();
     
                customer.CustomerID = entity.customerID;
            }
        }
         
        public void Update(CustomerViewModel customer)
        {
            if (!UpdateDatabase)
            {
                var target = One(e => e.CustomerID == customer.CustomerID);
     
                if (target != null)
                {
                    target.FirstName = customer.FirstName;
                    target.LastName = customer.LastName;
                    target.Phone = customer.Phone;
                    target.Company = customer.Company;
                    target.Address1 = customer.Address1;
                    target.Address2 = customer.Address2;
                    target.City = customer.City;
                    target.StateProvince = customer.StateProvince;
                    target.ZipPostalCode = customer.ZipPostalCode;
                    target.VatNumber = customer.VatNumber;
                    target.DestCode = customer.DestCode;
                    target.Notes = customer.Notes;
                     
                    /*if (customer.Country != null)
                    {*/
                        customer.CountryID = customer.Country.CountryID;
                    /*}
                    else
                    {
                        customer.Country = new CountryViewModel()
                        {
                            CountryID = customer.CountryID,
                            CountryName = entities.Countries.Where(s => s.countryID == customer.CountryID)
                                .Select(s => s.countryName).First()
                        };
                    }*/
     
                    target.CountryID = customer.CountryID;
                    target.Country = customer.Country;
                }
            }
            else
            {
                var entity = new Customer();
                 
                entity.customerID = customer.CustomerID;
                entity.firstName = customer.FirstName;
                entity.lastName = customer.LastName;
                entity.company = customer.Company;
                entity.address1 = customer.Address1;
                entity.address2 = customer.Address2;
                entity.city = customer.Address2;
                entity.countryID = customer.CountryID;
     
                /*if (customer.Country != null)
                {*/
                    entity.countryID = customer.Country.CountryID;
                /*}*/
     
                entities.Customers.Attach(entity);
                entities.Entry(entity).State = EntityState.Modified;
                entities.SaveChanges();
            }
        }
     
        public void Destroy(CustomerViewModel customer)
        {
            if (!UpdateDatabase)
            {
                var target = GetAll().FirstOrDefault(p => p.CustomerID == customer.CustomerID);
                if (target != null)
                {
                    GetAll().Remove(target);
                }
            }
            /*else
            {
                var entity = new Customer();
     
                entity.customerID = customer.CustomerID;
     
                entities.Customers.Attach(entity);
     
                entities.Customers.Remove(entity);
                /*
                var orderDetails = entities.Order_Details.Where(pd => pd.ProductID == entity.ProductID);
     
                foreach (var orderDetail in orderDetails)
                {
                    entities.Order_Details.Remove(orderDetail);
                }
                #1#
                entities.SaveChanges();
            }*/
        }
     
        public CustomerViewModel One(Func<CustomerViewModel, bool> predicate)
        {
            return GetAll().FirstOrDefault(predicate);
        }
     
        public void Dispose()
        {
            entities.Dispose();
        }
    }

     

    This is my controller:

    public class GridController : Controller
    {
        private CustomerService customerService;
     
        public GridController()
        {
            customerService = new CustomerService(new devDeptMvcContext());
        }
     
        protected override void Dispose(bool disposing)
        {
            customerService.Dispose();
     
            base.Dispose(disposing);
        }
         
        public ActionResult Index()
        {
            PopulateCountries();
            return View();
        }
     
        private void PopulateCountries()
        {
            var dataContext = new devDeptMvcContext();
            var countries = dataContext.Countries
                .Select(c => new CountryViewModel {
                    CountryID = c.countryID,
                    CountryName = c.countryName
                })
                .OrderBy(e => e.CountryName);
             
            ViewData["countries"] = countries;
            ViewData["defaultCountry"] = countries.First();           
        }
         
        public ActionResult ForeignKeyColumn_Read([DataSourceRequest] DataSourceRequest request)
        {
            return Json(customerService.Read().ToDataSourceResult(request));
        }
     
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ForeignKeyColumn_Update([DataSourceRequest] DataSourceRequest request,
            [Bind(Prefix = "models")]IEnumerable<CustomerViewModel> customers)
        {
            if (customers != null && ModelState.IsValid)
            {
                foreach (var customer in customers)
                {
                    customerService.Update(customer);                   
                }
            }
     
            return Json(customers.ToDataSourceResult(request,ModelState));
        }
     
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ForeignKeyColumn_Create([DataSourceRequest] DataSourceRequest request,
            [Bind(Prefix = "models")]IEnumerable<CustomerViewModel> customers)
        {
            var results = new List<CustomerViewModel>();
            if (customers != null && ModelState.IsValid)
            {
                foreach (var customer in customers)
                {
                    customerService.Create(customer);
                    results.Add(customer);
                }
            }
     
            return Json(results.ToDataSourceResult(request, ModelState));
        }
     
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ForeignKeyColumn_Destroy([DataSourceRequest] DataSourceRequest request,
            [Bind(Prefix = "models")]IEnumerable<CustomerViewModel> customers)
        {
            foreach (var customer in customers)
            {
                customerService.Destroy(customer);
            }
     
            return Json(customers.ToDataSourceResult(request, ModelState));
        }      
    }

     

    And this is my view:

    @using Corporate.Models
     
    @(Html.Kendo().Grid<CustomerViewModel>()
        .Name("grid")
        .Columns(columns =>
        {
            columns.Bound(c => c.FirstName).Width(100);
            columns.Bound(c => c.LastName).Width(100);
            columns.Bound(c => c.Company);
            columns.Bound(c => c.City).Width(100);
            columns.Bound(c => c.OrderCount).Width(100).Title("Orders");
            columns.ForeignKey(c => c.CountryID, (System.Collections.IEnumerable)ViewData["countries"], "CountryID", "CountryName")
                .Title("Country").Width(100);
            columns.Command(command => command.Edit());
            columns.Command(command => command.Destroy());
        })
        .ToolBar(toolBar =>
        {
            toolBar.Create();
        })
        .Editable(editable => editable.Mode(GridEditMode.PopUp))
        .Filterable()
        .Groupable()
        .Pageable()
        .Sortable()
        //.Scrollable()
        .HtmlAttributes(new { style = "height:540px;" })
        .DataSource(dataSource => dataSource
            .Ajax()
            .PageSize(10)
            .ServerOperation(false)
            .Events(events => events.Error("errorHandler"))
            .Model(model =>
            {
                model.Id(c => c.CustomerID);
                model.Field(c => c.CustomerID).Editable(false);
               // model.Field(c => c.CountryID).DefaultValue("ITA");
            })
            .Read(read => read.Action("ForeignKeyColumn_Read", "Grid"))
            .Update(update => update.Action("ForeignKeyColumn_Update", "Grid"))
            .Create(create => create.Action("ForeignKeyColumn_Create", "Grid"))
            .Destroy(destroy => destroy.Action("ForeignKeyColumn_Destroy", "Grid"))
        )
        )
     
    <script type="text/javascript">
        function errorHandler(e) {   
            if (e.errors) {
                var message = "Errors:\n";
                $.each(e.errors, function (key, value) {
                    if ('errors' in value) {
                        $.each(value.errors, function() {
                            message += this + "\n";
                        });
                    }
                });       
                alert(message);
            }
        }
    </script>

     

    I've also added this ClientCountry.cshtml without understanding how it's used:

    @model Corporate.Models.CountryViewModel
     
    @(Html.Kendo().DropDownListFor(m => m)
        .DataValueField("CountryID")
        .DataTextField("CountryName")
        .BindTo((System.Collections.IEnumerable)ViewData["countries"])
        )

     

    The result is a NullReferenceException inside the public ActionResult ForeignKeyColumn_Destroy() method (customer collection is null).

    I managed to make it work using:

    .Destroy(destroy => destroy.Action("Destroy", "Grid"))

    in the view and renaming the ForeignKeyColumn_Destroy() method as Destroy() but they are all blind attempts.

    What am I doing wrong?

    Thanks,

    Alberto

  4. Alberto
    Alberto avatar
    20 posts
    Member since:
    May 2019

    Posted 22 Aug 2019 in reply to Alberto Link to this post

    Actually to make it work, I use this controller action:

             [AcceptVerbs(HttpVerbs.Post)]
           public ActionResult Destroy(CustomerViewModel product)
           {
               RouteValueDictionary routeValues;
     
               //Delete the record
               customerService.Destroy(product);
     
               routeValues = this.GridRouteValues();
     
               //Redisplay the grid
               return RedirectToAction("Index", routeValues);
           }
  5. Nikolay
    Admin
    Nikolay  avatar
    297 posts

    Posted 26 Aug 2019 Link to this post

    Hello Alberto,

    Thank you for the provided configuration.

    What I understand is that your issue is more of an MVC architectural nature and not so related to using the Kendo UI components.  I confirm that your Grid implementation is correct but how you will handle the back-end actions is up to you. 

    If the Grid receives the expected response from the Destroy action, the record should be successfully deleted and disappear from the Grid after the request. This would not happen if the Destroy controller does not return a proper response, which in turn will prevent the DataSource from updating item. Please check the following article on the Grid CRUD operations specifics:

    Another thing that comes to my mind are MVC filters. Do you have such in your application? ASP.NET MVC Filters are custom classes where you can write custom logic to execute before or after an action method executes and a such one may prevent the request from reaching the action method.

    Hope the above helps and if you have any further questions, please contact us back.


    Regards,
    Nikolay
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  6. Alberto
    Alberto avatar
    20 posts
    Member since:
    May 2019

    Posted 26 Aug 2019 in reply to Nikolay Link to this post

    Hi Nikolay,

    Thanks for the explanation but I am still unsure on the direction to take. My web app uses a MS SQL database on localhost, I thought it was easy to replace the WebGrid below with the Telerik one. Now it seem something beyond my reach. What we were after was simply to improve sorting/grouping etc. Maybe I am looking to the wrong sample? The article you linked is not easy to understand for me. Is it possible to open a ticket with our entire project+db to get the exact code we need to use?

    Thanks.

    Alberto

    @{
         var grid = new WebGrid(source: Model,
                                defaultSort: "LastName",
                                canSort: true,
                                canPage: true,
                                rowsPerPage: 25);
     }
     
     @*Normally is loaded at the end of the page, WebGrid needs it first.*@
     @Scripts.Render("~/bundles/jquery")
     <div id="grid">
         @{
             var gridColumns = new List<WebGridColumn>();
     
             if (User.IsInRole("admin"))
             {
                 gridColumns.Add(grid.Column(format: (item) => Html.ActionLink("DELETE", "Delete", new {id = item.customerID}, null)));
                 gridColumns.Add(grid.Column(format: (item) => Html.ActionLink("EDIT", "Edit", new {id = item.customerID}, null)));
             }
     
             gridColumns.Add(grid.Column("firstName", "First name"));
             gridColumns.Add(grid.Column("lastName", "Last name"));
             gridColumns.Add(grid.Column("company", "Company"));
             gridColumns.Add(grid.Column("countryID", "Country", (item => item.Country.countryName), canSort: false)); // derived from Country
             gridColumns.Add(grid.Column(null, "Orders", (item => item.Orders.Count), canSort: false)); // derived
             gridColumns.Add(grid.Column(null, format: (item) => Html.ActionLink("Details", "Details", new {id = item.customerID})));
     
         }
     
         @grid.Pager(WebGridPagerModes.All)
         @grid.GetHtml(
             tableStyle: "table table-striped",
             columns: grid.Columns(gridColumns.ToArray()))
     </div>

     

     

  7. Nikolay
    Admin
    Nikolay  avatar
    297 posts

    Posted 28 Aug 2019 Link to this post

    Hi Alberto,

    I believe the demo you were examining is for Grid Batch Editing. The scenario here is s to switch grid cells in edit mode by simply clicking them, update the data on the client and then process all changes on the server in a single batch update. A single click on "Delete" button only updates the data on the client side and does not fire the ActionResult Editing_Destroy. It will be fired upon clicking on "Save changes" and at that point your breakpoint will hit the method.

    If you wish to have your action method fired upon clicking on delete then you can choose to implement the editing to be completed on the Server directly. Please check the Grid Server editing demo, which actually contains the controller action method that you pointed as working for you.

    You can also examine the other demos we have provided in the Data Editing section and choose the one that best fit your project needs.
    If you need further assistance, please do not hesitate to contact us back. You can also send your working project in a support ticket. If it is within our scope of acknowledgment and is Kendo UI related, we will do our best to help.

    Kind regards,
    Nikolay
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  8. Alberto
    Alberto avatar
    20 posts
    Member since:
    May 2019

    Posted 28 Aug 2019 in reply to Nikolay Link to this post

    No Nikolay, I was examining the `ForeignKey column` demo because I need to deal with the Country foreign key (I'm trying to populate a simple Customers grid).

    What I understand is that your issue is more of an MVC architectural nature and not so related to using the Kendo UI components

    Is there any MVC architectural difference between the 'Grid Server editing' demo and the 'ForeignKey column' demo?

    Thanks,

    Alberto

     

  9. Nikolay
    Admin
    Nikolay  avatar
    297 posts

    Posted 30 Aug 2019 Link to this post

    Hello Alberto,

    Thank you for providing additional clarifications on the case.

    The ForeignKey column demo illustrates how to implement foreign key column in the Grid and generates a DropDownList editor for the Category column. The action method ForeignKeyColumn_Destroy in this demo does not fire on a single click the "Delete" button. A single click here only updates the data on the client side. Therefore, the action method ForeignKeyColumn_Destroy is, indeed, not hit in this demo. But again the purpose of it is to show you how you can implement foreign key column in the Grid.

    If you wish to have your data rendered on the server right after you click on "Delete", you could follow the approach in the Grid Server editing demo and more specifically  the ActionResult Destroy used in the Controller.

    Please keep in mind that the server part of our demos are only illustrative examples of how to handle your back-end when using Kendo UI components. Their logic might be different, depending on your project needs and implementing it depends on you.

    Hope the above answers your question and please contact us back in case of further ones.

    Regards,
    Nikolay
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  10. Alberto
    Alberto avatar
    20 posts
    Member since:
    May 2019

    Posted 02 Sep 2019 in reply to Nikolay Link to this post

    Ok Nikolay, I've tried to mix ServerEditing demo and ForeignKeyColumn demo code and still it doesn't work.

    public class CustomerViewModel
    {
        [ScaffoldColumn(false)]
        public int CustomerID { get; set; }
     
        [DisplayName("First name")]
        public string FirstName { get; set; }
     
        [DisplayName("Last name")]
        public string LastName { get; set; }
     
        public string Phone { get; set; }
     
        public string Company { get; set; }
     
        public string Address1 { get; set; }
     
        public string Address2 { get; set; }
     
        public string City { get; set; }
     
        [DisplayName("State/Province")]
        public string StateProvince { get; set; }
     
        [DisplayName("Zip/Postal code")]
        public string ZipPostalCode { get; set; }
     
        public CountryViewModel Country { get; set; }
     
        [DisplayName("Country")]
        [UIHint("ClientCountry")]
        public string CountryID { get; set; }
     
        [DisplayName("VAT number")]
        public string VatNumber { get; set; }
     
        [DisplayName("Codice destinatario SDI")]
        public string DestCode { get; set; }
         
        public string Notes { get; set; }
     
        [ScaffoldColumn(false)]
        public int OrderCount { get; set; }
    }
     
    public class CountryViewModel
    {
        public string CountryID { get; set; }
     
        public string CountryName { get; set; }
    }
     
    public class CustomerService : IDisposable
    {
        private static bool UpdateDatabase = false;
     
        private devDeptMvcContext _entities;
     
        public CustomerService(devDeptMvcContext entities)
        {
            this._entities = entities;
        }
     
        public IList<CustomerViewModel> GetAll()
        {
            var result = HttpContext.Current.Session["Customers"] as IList<CustomerViewModel>;
     
            if (result == null || UpdateDatabase)
            {
                result = _entities.Customers.Select(customer => new CustomerViewModel
                {
                    CustomerID = customer.customerID,
                    FirstName = customer.firstName,
                    LastName = customer.lastName,
                    Phone = customer.phone,
                    Company = customer.company,
                    Address1 = customer.address1,
                    Address2 = customer.address2,
                    City = customer.city,
                    StateProvince = customer.stateProvince,
                    ZipPostalCode = customer.zipPostalCode,
                    CountryID = customer.countryID,
                    Country = new CountryViewModel()
                    {
                        CountryID = customer.Country.countryID,
                        CountryName = customer.Country.countryName
                    },
                    VatNumber = customer.vatNumber,
                    DestCode = customer.destCode,
                    Notes = customer.notes,
                    OrderCount = customer.Orders.Count
                }).ToList();
     
                HttpContext.Current.Session["Customers"] = result;
            }
     
            return result;
        }
     
        public IEnumerable<CustomerViewModel> Read()
        {
            return GetAll();
        }
         
        public void Create(CustomerViewModel customer)
        {
            if (!UpdateDatabase)
            {
                if (customer.Country == null)
                {
                    customer.Country = new CountryViewModel() {CountryID = "ITA", CountryName = "Italy"};
                }
     
                GetAll().Insert(0, customer);
            }
            else
            {
                var entity = new Customer();
     
                entity.firstName = customer.FirstName;
                entity.lastName = customer.LastName;
                entity.company = customer.Company;
                entity.address1 = customer.Address1;
                entity.address2 = customer.Address2;
                entity.city = customer.City;
                entity.stateProvince = customer.StateProvince;
                entity.zipPostalCode = customer.ZipPostalCode;
                entity.vatNumber = customer.VatNumber;
                entity.destCode = customer.DestCode;
                entity.notes = customer.Notes;
     
                entity.countryID = customer.CountryID;
     
                if (customer.Country != null)
                {
                    entity.countryID = customer.Country.CountryID;
                }
     
                _entities.Customers.Add(entity);
                _entities.SaveChanges();
     
                customer.CustomerID = entity.customerID;
            }
        }
         
        public void Update(CustomerViewModel customer)
        {
            if (!UpdateDatabase)
            {
                var target = One(e => e.CustomerID == customer.CustomerID);
     
                if (target != null)
                {
                    target.FirstName = customer.FirstName;
                    target.LastName = customer.LastName;
                    target.Phone = customer.Phone;
                    target.Company = customer.Company;
                    target.Address1 = customer.Address1;
                    target.Address2 = customer.Address2;
                    target.City = customer.City;
                    target.StateProvince = customer.StateProvince;
                    target.ZipPostalCode = customer.ZipPostalCode;
                    target.VatNumber = customer.VatNumber;
                    target.DestCode = customer.DestCode;
                    target.Notes = customer.Notes;
                     
                    customer.CountryID = customer.Country.CountryID;
     
                    target.CountryID = customer.CountryID;
                    target.Country = customer.Country;
                }
            }
            else
            {
                var entity = new Customer();
                 
                entity.customerID = customer.CustomerID;
                entity.firstName = customer.FirstName;
                entity.lastName = customer.LastName;
                entity.company = customer.Company;
                entity.address1 = customer.Address1;
                entity.address2 = customer.Address2;
                entity.city = customer.Address2;
                entity.countryID = customer.CountryID;
     
                entity.countryID = customer.Country.CountryID;
     
                _entities.Customers.Attach(entity);
                _entities.Entry(entity).State = EntityState.Modified;
                _entities.SaveChanges();
            }
        }
     
        public void Destroy(CustomerViewModel customer)
        {
            if (!UpdateDatabase)
            {
                var target = GetAll().FirstOrDefault(p => p.CustomerID == customer.CustomerID);
                if (target != null)
                {
                    GetAll().Remove(target);
                }
            }           
        }
     
        public CustomerViewModel One(Func<CustomerViewModel, bool> predicate)
        {
            return GetAll().FirstOrDefault(predicate);
        }
     
        public void Dispose()
        {
            _entities.Dispose();
        }
    }

     

    This is the controller:

    public class GridController : Controller
    {
        private CustomerService _customerService;
     
        public GridController()
        {
            _customerService = new CustomerService(new devDeptMvcContext());
        }
     
        protected override void Dispose(bool disposing)
        {
            _customerService.Dispose();
     
            base.Dispose(disposing);
        }
         
        public ActionResult Index()
        {
            PopulateCountries();
            return View(_customerService.Read());
        }
     
        private void PopulateCountries()
        {
            var dataContext = new devDeptMvcContext();
            var countries = dataContext.Countries
                .Select(c => new CountryViewModel {
                    CountryID = c.countryID,
                    CountryName = c.countryName
                })
                .OrderBy(e => e.CountryName);
             
            ViewData["countries"] = countries;
            ViewData["defaultCountry"] = countries.First();           
        }
        
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Update(CustomerViewModel customer)
        {  
            if (ModelState.IsValid)
            {
                //The model is valid - update the product and redisplay the grid.
                _customerService.Update(customer);
     
                //GridRouteValues() is an extension method which returns the
                //route values defining the grid state - current page, sort expression, filter etc.
                RouteValueDictionary routeValues = this.GridRouteValues();
     
                return RedirectToAction("Index", routeValues);
            }
     
            //The model is invalid - render the current view to show any validation errors
            return View("Index", _customerService.Read());
        }
     
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Destroy(CustomerViewModel product)
        {
            RouteValueDictionary routeValues;
     
            //Delete the record
            _customerService.Destroy(product);
     
            routeValues = this.GridRouteValues();
     
            //Redisplay the grid
            return RedirectToAction("Index", routeValues);
        }
    }

     

    This is the view:

    @using Corporate.Models
    @model IEnumerable<CustomerViewModel>
     
    @(Html.Kendo().Grid(Model)
        .Name("Grid")
        .Columns(columns =>
        {
            columns.Bound(c => c.FirstName).Width(100);
            columns.Bound(c => c.LastName).Width(100);
            columns.Bound(c => c.Company);
            columns.Bound(c => c.City).Width(100);
            columns.Bound(c => c.OrderCount).Width(100).Title("Orders");
            columns.ForeignKey(c => c.CountryID, (System.Collections.IEnumerable)ViewData["countries"], "CountryID", "CountryName")
                .Title("Country").Width(100);
            columns.Command(command => command.Edit());
            columns.Command(command => command.Destroy());
        })
        .Editable(editable => editable.Mode(GridEditMode.PopUp))
        .Filterable()
        .Groupable()
        .Pageable()
        .Sortable()
        .HtmlAttributes(new { style = "height:540px;" })
        .DataSource(dataSource => dataSource
            .Server()
            .Model(model =>
            {
                model.Id(c => c.CustomerID);
                model.Field(c => c.CustomerID).Editable(false);
                model.Field(c => c.OrderCount).Editable(false);
            })
            .Read("Index", "Grid")
            .Update("Update", "Grid")
            .Destroy("Destroy", "Grid"))
        )
        )
     
    <script type="text/javascript">
        $(document).ready(function () {
            $("form.k-edit-form").kendoValidator();
        });
    </script>

     

    And this is the ClientCountry editor:

    @model Corporate.Models.CountryViewModel
     
    @(Html.Kendo().DropDownListFor(m => m)
        .DataValueField("CountryID")
        .DataTextField("CountryName")
        .BindTo((System.Collections.IEnumerable)ViewData["countries"])
        )

     

    I still get the following error:

    System.InvalidOperationException: 'The model item passed into the dictionary is of type 'System.String', but this dictionary requires a model item of type 'Corporate.Models.CountryViewModel'.'

    In my opinion this error is related to the UIHint on CustomerViewModel.CountryViewModel or on CustomerViewModel.CountryID field. In one case I can run the app and get no dropDown in the Popup editor, in the other I get the InvalidOperationException above.

    Thanks,

    Alberto

  11. Nikolay
    Admin
    Nikolay  avatar
    297 posts

    Posted 04 Sep 2019 Link to this post

    Hi Alberto,

    Thank you for the provided project configuration and error messages you receive.

    What I noticed is that your ClientCountry model is of type String, but the ClientCountry Editor expects a model item of type "CountryViewModel". These two should be consistent and the model should be of the same type the editor expects to receive. You can either set the ClientCountry to be of type CountryViewModel or specify the ClientCountry Editor to require a model of type String.

    Please try the above and let me know if you need further assistance.

    Kind regards,
    Nikolay
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  12. Alberto
    Alberto avatar
    20 posts
    Member since:
    May 2019

    Posted 04 Sep 2019 in reply to Nikolay Link to this post

    You were right Nikolay,

    I've moved the UIHint on this CustomerViewModel member:

    [UIHint("ClientCountry")]
    public CountryViewModel Country { get; set; }

     

    And now I got rid of the error. However, the popup editor still does not show the DropDownCombo for Country column. Why? see attached picture.

    Thanks,

    Alberto

     

     

     

     

     

     

     

  13. Nikolay
    Admin
    Nikolay  avatar
    297 posts

    Posted 05 Sep 2019 Link to this post

    Hi Alberto,

    When a column is defined as a ForeignKey colum the ASP.NET MVC Grid will look for the editor template in ~Views\Shared\EditorTemplates named GridForeignKey.cshtml and populate it with the passed collection through the column declaration. Thus, you must name your DropDownList editor with GridForeignKey.cshtml.

    Below is the definition of the editor template from the demo:

    @model object
    @(Html.Kendo().DropDownListFor(m => m)
        .BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
    )

    Hope the above helps and let me know if you need further help.

    Regards,
    Nikolay
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Back to Top