Grid - UrlAdaptor / DataManagerRequest / operation.PerformFiltering error : 'Object reference not set to an instance of an object.'

I get the following error : System.NullReferenceException : 'Object reference not set to an instance of an object.'
 when doing an operation.PerformFiltering in a DataManagerRequest on my Grid UrlAdaptor

Here is my ContactController :

        [HttpPost]
        public IActionResult UrlDatasource([FromBody] DataManagerRequest dm)
        {

            IEnumerable<Contact> contacts = _context.Contact.Include(c => c.CreateBy).Include(c => c.Customer).AsEnumerable();
            DataOperations operation = new DataOperations();

            if (dm.Search != null && dm.Search.Count > 0)
            {
                contacts = operation.PerformSearching(contacts, dm.Search);  //Search
            }
            if (dm.Sorted != null && dm.Sorted.Count > 0) //Sorting
            {
                if (!dm.Sorted.Any(item => item.Name.Contains(".")))
                {
                    contacts = operation.PerformSorting(contacts, dm.Sorted);
                }
            }
            if (dm.Where != null && dm.Where.Count > 0)
            {
                //dm.Where[0].IgnoreCase = false;
                contacts = operation.PerformFiltering(contacts, dm.Where, dm.Where[0].Operator);     //Filtering
            }

            if (dm.Skip != 0)
            {
                contacts = operation.PerformSkip(contacts, dm.Skip);   //Paging
            }
            if (dm.Take != 0)
            {
                contacts = operation.PerformTake(contacts, dm.Take);
            }
            return Ok(new { result = contacts, count = contacts.Count() });

        }

The where condition seems OK to me (I tried with IgnoreCase = false also but doesn't seem to be a PascalCase problem...


What should be done to get this filter working ?

Best regards,
Romain

9 Replies 1 reply marked as answer

MS Manivel Sellamuthu Syncfusion Team September 9, 2020 03:44 PM UTC

Hi Romain, 

Greetings from Syncfusion support. 

We have checked the reported issue at our end with menu filter, but we are not facing the reported issue. Please refer the tried code example and screenshot for more information. 

    <ejs-grid id="Grid" allowPaging="true" allowFiltering="true"> 
        <e-data-manager url="/Home/UrlDataSource" adaptor="UrlAdaptor"></e-data-manager> 
        <e-grid-filterSettings type="Menu"></e-grid-filterSettings> 
        <e-grid-columns> 
            <e-grid-column field="OrderID" headerText="Order ID" isPrimaryKey="true" textAlign="Right" width="100"></e-grid-column> 
            <e-grid-column field="ShipCountry" headerText="Ship Country" width="150" ></e-grid-column> 
            <e-grid-column field="CustomerID" headerText="Customer ID" type="string" width="120"></e-grid-column> 
            <e-grid-column field="Freight" width="150" ></e-grid-column> 
        </e-grid-columns> 
    </ejs-grid> 
public IActionResult UrlDatasource([FromBody]DataManagerRequest dm) 
       
            IEnumerable DataSource = order; 
            DataOperations operation = new DataOperations(); 
            if (dm.Search != null && dm.Search.Count > 0) 
           
                DataSource = operation.PerformSearching(DataSource, dm.Search);  //Search 
           
            if (dm.Sorted != null && dm.Sorted.Count > 0) //Sorting 
           
                DataSource = operation.PerformSorting(DataSource, dm.Sorted); 
           
            if (dm.Where != null && dm.Where.Count > 0) //Filtering 
           
                DataSource = operation.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator); 
           
            int count = DataSource.Cast<Orders>().Count(); 
            if (dm.Skip != 0) 
           
                DataSource = operation.PerformSkip(DataSource, dm.Skip);   //Paging 
           
            if (dm.Take != 0) 
           
                DataSource = operation.PerformTake(DataSource, dm.Take); 
           
            return dm.RequiresCounts ? Json(new { result = DataSource, count = count }) : Json(DataSource); 
       



Could you please share the below details, which will be helpful for us to validate further about issue. 

  1. Share the complete Grid code
  2. Share the Syncfusion packages version
 
Regards, 
Manivel 



RF Romain Fabbri September 14, 2020 01:11 PM UTC

Please run attached solution (run both WebApi & WebManager)

Update-Database
Register a user & login
https://localhost:44386/Customer/Contact

You shall get the reported error.

Attachment: _AlienErp_syncf_ticket_f2e1b9fe.zip


MS Manivel Sellamuthu Syncfusion Team September 16, 2020 12:13 PM UTC

Hi Romain, 

Thanks for your update. 

We checked the attached sample and we found that you have implemented URL service in the WebAPI controller. By default the URL adaptor is not compatible with WebAPI controller. So, we suggest you to use webApi adaptor for the Grid to resolve the reported issue.  

For WebApiAdaptor we need to handle the Grid actions such as filtering, paging, sorting in server side by manually. By default grid sends request to the server for all the grid actions like Paging, Sorting, Filtering, Searching etc., in the controller side you can perform these operation with the correspond queries and return the data with Items & Count value pair which will be bound to the grid. 

Please refer the below documentation and code example for more information. 


OrderController.cs 

public class OrderController : Controller 
    { 
        // GET: api/Orders 
        [HttpGet] 
 
        public object Get() 
        { 
            var queryString = Request.Query; 
// perform the operation using the concern querystring 
            int skip = Convert.ToInt32(queryString["$skip"]); //paging 
            int take = Convert.ToInt32(queryString["$top"]); 
            string filter = queryString["$filter"]; // filtering  
            string sort = queryString["$orderby"]; // sorting  
            var data = OrdersDetails.GetAllRecords(); 
            List<OrdersDetails> Datae = new List<OrdersDetails>(); 
            List<OrdersDetails> Datase = new List<OrdersDetails>(); 
            if (sort != null) //Sorting 
            { 
                switch (sort) 
                { 
// here you can perform sorting action 
                    case "OrderID": 
                        if (sort.Substring(sort.IndexOf(' ') + 1) != null) 
                            data = data.OrderByDescending(x => x.OrderID).ToList(); 
                        else 
                            data = data.OrderBy(x => x.OrderID).ToList(); 
                        break; 
                    case "CustomerID": 
                        if (sort.Substring(sort.IndexOf(' ') + 1) != null) 
                            data = data.OrderByDescending(x => x.CustomerID).ToList(); 
                        else 
                            data = data.OrderBy(x => x.CustomerID).ToList(); 
                        break; 
                    case "ShipCity": 
                        if (sort.Substring(sort.IndexOf(' ') + 1) != null) 
                            data = data.OrderByDescending(x => x.ShipCity).ToList(); 
                        else 
                            data = data.OrderBy(x => x.ShipCity).ToList(); 
                        break; 
                    case "ShipCountry": 
                        if (sort.Substring(sort.IndexOf(' ') + 1) != null) 
                            data = data.OrderByDescending(x => x.ShipCountry).ToList(); 
                        else 
                            data = data.OrderBy(x => x.ShipCountry).ToList(); 
                        break; 
                } 
            } 
            if (filter != null) 
            { 
// here you can perform filtering action 
                var newfiltersplits = filter; 
                var filtersplits = newfiltersplits.Split('(', ')', ' '); 
                var filterfield = filtersplits[1]; 
                var filtervalue = filtersplits[3]; 
                if (filtersplits.Length != 5) 
                { 
                    filterfield = filter.Split('(', ')', '\'')[3]; 
                    filtervalue = filter.Split('(', ')', '\'')[5]; 
                } 
                switch (filterfield) 
                { 
                    case "OrderID": 
 
                        Datae = (from cust in data 
                                 where cust.OrderID.ToString() == filtervalue.ToString() 
                                 select cust).ToList(); 
                        break; 
                    case "EmployeeID": 
 
                        Datae = (from cust in data 
                                 where cust.EmployeeID.ToString() == filtervalue.ToString() 
                                 select cust).ToList(); 
                        break; 
                    case "Freight": 
 
                        Datae = (from cust in data 
                                 where cust.Freight.ToString() == filtervalue.ToString() 
                                 select cust).ToList(); 
                        break; 
                    case "CustomerID": 
                        Datae = (from cust in data 
                                 where cust.CustomerID.ToLower().StartsWith(filtervalue.ToString()) 
                                 select cust).ToList(); 
                        break; 
                    case "ShipCity": 
                        Datae = (from cust in data 
                                 where cust.ShipCity.ToLower().StartsWith(filtervalue.ToString()) 
                                 select cust).ToList(); 
                        break; 
                    case "ShipCountry": 
                        Datae = (from cust in data 
                                 where cust.ShipCountry.ToLower().StartsWith(filtervalue.ToString()) 
                                 select cust).ToList(); 
                        break; 
                } 
                Datase.AddRange(Datae); 
               // count = Datase.Count; 
                data = Datase; 
            } 
// return the data with Items and Count pair 
            return new 
            { 
                Items = data.Skip(skip).Take(take), 
                Count = data.Count() 
               //  return order; 
            }; 
 
        } 
 
        // GET: api/Orders/5 
        [HttpGet("{id}", Name = "Get")] 
        public string Get(int id) 
        { 
            return "value"; 
        } 
 
        // POST: api/Orders 
        [HttpPost] 
        public object Post([FromBody]OrdersDetails value) 
        { 
            OrdersDetails.GetAllRecords().Insert(0, value); 
            return value; 
        } 
 
 
 
        // PUT: api/Orders/5 
        [HttpPut] 
        public object Put(int id, [FromBody]OrdersDetails value) 
        { 
            var ord = value; 
            OrdersDetails val = OrdersDetails.GetAllRecords().Where(or => or.OrderID == ord.OrderID).FirstOrDefault(); 
            val.OrderID = ord.OrderID; 
            val.EmployeeID = ord.EmployeeID; 
            val.CustomerID = ord.CustomerID; 
            val.Freight = ord.Freight; 
            val.OrderDate = ord.OrderDate; 
            val.ShipCity = ord.ShipCity; 
            return value; 
        } 
 
        // DELETE: api/ApiWithActions/5 
        [HttpDelete("{id:int}")] 
        [Route("Orders/{id:int}")] 
        public object Delete(int id) 
        { 
            OrdersDetails.GetAllRecords().Remove(OrdersDetails.GetAllRecords().Where(or => or.OrderID == id).FirstOrDefault()); 
            return Json(id); 
        } 
 
        public class Data 
        { 
 
            public bool requiresCounts { get; set; } 
            public int skip { get; set; } 
            public int take { get; set; } 
        } 
    } 
<ejs-grid id="Grid"> 
    <e-data-manager url="/api/Orders" adaptor="WebApiAdaptor" crossdomain="true"></e-data-manager> 
    <e-grid-columns> 
        <e-grid-column field="OrderID" headerText="Order ID" type="number" textAlign="Right" width="120"></e-grid-column> 
        <e-grid-column field="CustomerID" headerText="Customer ID" type="string" width="140"></e-grid-column> 
        <e-grid-column field="Freight" headerText="Freight" textAlign="Right" format="C2" width="120"></e-grid-column> 
        <e-grid-column field="OrderDate" headerText="Order Date" format='yMd' textAlign="Right" width="140"></e-grid-column> 
    </e-grid-columns> 
</ejs-grid> 
 

Please let us know, if you need further assistance. 

Regards, 
Manivel 


Marked as answer

JS Jason Smith February 3, 2023 01:04 PM UTC

I have personally googled this issue extensively, (using this grid in a .NET 7 project) and i can say as from Feb 2023, the URLadapter works perfectly fine, the issue is the Nullreference occurs because the column names are serialised as camelCase, so you class might have a property called "EmployeeName", but the DataManagerRequest and associated DataOperations object is trying to filter on "employeeName", which is how you get the nullreference,

if you change your ActionResult method to return something like this then filtering works fine:


return Json(new { result = DataSource, count = TotalRecords }, new System.Text.Json.JsonSerializerOptions() { PropertyNamingPolicy = null });



PS Pavithra Subramaniyam Syncfusion Team February 6, 2023 10:08 AM UTC

Hi Jason Smith,


Thanks for updating with the solution you have tried. Please get back to us for further assistance.


Regards,

Pavithra S



VP Virang Patel replied to Jason Smith April 7, 2023 02:44 PM UTC

Could oyu explain further where to do this at? when you return at the end, doesn't the filtering exception happen before you return the result anyways?



PS Pavithra Subramaniyam Syncfusion Team April 10, 2023 02:08 PM UTC

Hi Virang Patel,


You can resolve the casing problem serializing and returning them in the PascelCase format using the below code in the startup.cs file of the application,


If the ASP.NET CORE version is 2.X then add the below code in startup.cs file


 

public void ConfigureServices(IServiceCollection services)

{

    services.AddMvc().AddJsonOptions(options =>

    {

        options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();

    });

}

 


If the ASP.NET CORE version is 3.X and more, then add the below code in startup.cs file


 

 

public void ConfigureServices(IServiceCollection services)

          {

                      services.AddMvc().AddNewtonsoftJson(options =>

          {

                 options.SerializerSettings.ContractResolver =

                    new DefaultContractResolver();
          });

           

        }

 


To use AddNewtonsoftJson in your project we need include the Microsoft.AspNetCore.Mvc.NewtonsoftJson assembly


Note : We need to install NewtonSoft.JSON as dependency since Syncfusion.EJ2.AspNet.Core dependent to NewtonSoft.JSON package.


Refer to the below documentation for more information.


UG: https://ej2.syncfusion.com/aspnetcore/documentation/grid/data-binding/data-binding#troubleshoot-grid-render-rows-without-data


Regards,

Pavithra S



AH Ahmed May 13, 2024 07:53 AM UTC

Good day folks, 

I had the same issue and tried for hours to fix it even with what  Jason Smith comment I wasn't able to fixed.

Finally I noticed that the filter works when at list one sort is done. Otherwise the filter doesn't work. 

So I added this peace of code to my javascript file :

  $(document).ready(function () {

    document.getElementById("myGrid").ej2_instances[0].sortSettings.properties.columns.push({ field: 'myDefaultSortingColumn', direction: 'Descending' });

  })


Now, filtering is working properly when page is loaded.



AR Aishwarya Rameshbabu Syncfusion Team May 16, 2024 11:43 AM UTC

Hi Ahmed,


We understand that you have resolved your issue on your own.


Please get back to us if you have further queries or if you are still facing the reported issue.


Regards

Aishwarya R


Loader.
Up arrow icon