2

I am currently building an MVC application and I am trying to display a list of cars based on the selected dropdown. I dont want the user to have to select multiple dropdown to search, I want the code to be able to search by any combination of the dropdowns. I started wrinting the code with If else statements but I didnt think this was the best practice so I did some research and found a different way to filter my results. The issue that I am having is that the I am getting a null value in a Model.

This is my model

    public partial class Car 
{

    private Ignition_Hub_DBEntities Context;

    public IQueryable<Car> GetProducts(Car searchModel)
    {
        var result = Context.Cars.AsQueryable();
        if (searchModel != null)
        {
            if (searchModel.CarLotID.HasValue)
                result = result.Where(x => x.CarLotID == searchModel.CarLotID);
            if (searchModel.Available.HasValue)
                result = result.Where(x => x.Available == searchModel.Available);
            if (searchModel.ModelID.HasValue)
                result = result.Where(x => x.ModelID == searchModel.ModelID);
             if (searchModel.Model.MakeID.HasValue)
                return result;
            result = result.Where(x => x.Model.MakeID == searchModel.Model.MakeID);
            return result;
        }
        return result;
    }
        public Car()
    {
        Context = new Ignition_Hub_DBEntities();

    }
    public int? CarID { get; set; }
    public string Year { get; set; }

    public string Notes { get; set; }
    public bool? Available { get; set; }
    public string VinNumber { get; set; }
    public int? CarLotID { get; set; }
    public int? ModelID { get; set; }

    public virtual Model Model { get; set; }
    public virtual CarLot CarLot { get; set; }
}

This is my controller

        public ActionResult DisplaySearchResults(Car searchModel)
    {

        var business = new Car();
        var model = business.GetProducts(searchModel);
        return PartialView("_Index", model);
}

Right now I get an error on if (searchModel.Model.MakeID.HasValue) the error is 'Object reference not set to an instance of an object.' Thanks in advance for the help! If there is a better way to achieve this, please advise. Thank you!

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
Smiley Rod
  • 53
  • 6

1 Answers1

1

You need to make sure the Model property of the search model is not null and has been passed to the action, then when searching you need to make sure Model property of the element in linq query is not null, then compare MakeID property of the search model with MakeID property of the element in linq query. For example if you are going to search based on MakeID of the Model, if it's been specified, then you need to change the code to the following:

if (searchModel.Model !=null && searchModel.Model.MakeID.HasValue)
    result = result.Where(x => x.Model !=null && 
        x.Model.MakeID == searchModel.Model.MakeID);

However if you are following this post, in general it's better to follow these advises:

  • Do not use your Entity model as your POCO search model.
  • Do not put business logic in your POCO class.
  • If you are going to search based on MakeID, include it directly in the POCO search model.

Example

I'll extend the example from linked post, so the Product have a Category property as well and we are interested to search based on CategoryName as well as some other properties:

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Product
{
    public int Id { get; set; }
    public int Price { get; set; }
    public string Name { get; set; }
    public int CategoryId { get; set; }
    public Category Category { get; set; }
}

You can create a ProductSearchModel class and put some fields you want to search based on them:

public class ProductSearchModel
{
    public int? Id { get; set; }
    public int? PriceFrom { get; set; }
    public int? PriceTo { get; set; }
    public string Name { get; set; }
    public string CategoryName { get; set; }
}

Then you can put your search logic in ProductBusinessLogic class this way:

public class ProductBusinessLogic
{
    private YourDbContext Context;
    public ProductBusinessLogic()
    {
        Context = new YourDbContext();
    }

    public IQueryable<Product> GetProducts(ProductSearchModel searchModel)
    {
        var result = Context.Products.AsQueryable();
        if (searchModel != null)
        {
            if (searchModel.Id.HasValue)
                result = result.Where(x => x.Id == searchModel.Id);
            if (!string.IsNullOrEmpty(searchModel.Name))
                result = result.Where(x => x.Name.Contains(searchModel.Name));
            if (searchModel.PriceFrom.HasValue)
                result = result.Where(x => x.Price >= searchModel.PriceFrom);
            if (searchModel.PriceTo.HasValue)
                result = result.Where(x => x.Price <= searchModel.PriceTo);
            if (!string.IsNullOrEmpty(searchModel.CategoryName))
                result = result.Where(x => x.Category !=null && 
                    x.Category.Name.Contains(searchModel.Name));
        }
        return result;     
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • Thank you so much ! Your initial if statement in this answer fixed my issue. I will take your advise in using the POCOs for better practice. However, I had a checkbox in my table that was checked if car is available and unchecked if car was unavailable. After adding this code, the checkbox turned into a select dropdown. Any reason for that? – Smiley Rod Apr 27 '20 at 22:07
  • No problem :) *After adding this code, the checkbox turned into a select dropdown* → no idea at the moment :\ – Reza Aghaei Apr 27 '20 at 22:14