Good day, I am doing Web api rest project and want to include product search for products by size and color, but I want to be able search for example: 1 One size
[httpGet][Route("oneSize/{sizeID}")]
2 Two Sizes
[httpGet][Route("TwoSizes/{sizeID1}/{sizeID2}")]
3 One size/ One color
[httpGet][Route("OneSizeOneColor/{sizeID1}/{ColorID}")]
4 Two sizes/ One color
[httpGet][Route("TwoSizeOneColor/{sizeID1}/{sizeID2}/{ColorID}")]
etc. Do I need to create end point for every tipe of search or is there a smarter way of doing it?
CodePudding user response:
You should use the query params. You can add them via FromQuery
attribute:
[HttpGet]
public IActionResult SearchProducts([FromQuery] int[] sizeIds, [FromQuery] int[] colorIds) {
}
You can replace int
with string
if you have string Ids.
For example, if you want to make a request with sizes 1 and 2, and color 3 and 4, the request would look like this: https://localhost:5001/your-endpoint-name?sizeIds=1&sizeIds=2&colorIds=3&colorIds=4
So query is a list of key=value
url parameters after the ?
separated by &
sign
EDIT
You can easily query the database with the sql IN operator.
In EF Core, it would look something like this:
IQuaryable<Product> query = dbContext.Products;
if (sizeIds.Length > 0) {
query= query.Where(p => sizeIds.Contains(p.SizeId));
}
if (colorIds.Length > 0) {
query= query.Where(p => colorIds.Contains(p.ColorId));
}
List<Product> result = await query.ToListAsync();
It would be translated to the following SQL:
SELECT * FROM Products
WHERE Products.SizeId IN (1, 2) AND Products.ColorId IN (3, 4);
CodePudding user response:
The problem is that I have nested classess
public class ProductBase
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ICollection<ProductVariant> Variants { get; set; } = new List<ProductVariant>();
public int BaseImageId { get; set; } = 0;
public string BaseImagePath { get; set; } = string.Empty;
}
public class ProductVariant
{
public int Id { get; set; }
public int Quantity { get; set; }
public int ProductBaseId { get; set; }
public int ProductSizeId { get; set; }
public ProductSize ProductSize { get; set; }
public int ProductColorId { get; set; }
public ProductColor ProductColor { get; set; }
public IEnumerable<ImageVariant> imageVariants { get; set; } = new List<ImageVariant>();
}
public class ProductSize
{
public int Id { get; set; }
public string Size { get; set; }
}
public class ProductColor
{
public int Id { get; set; }
public string Color { get; set; }
}
I am trying something like this
public async Task<IQueryable<Models.ProductBase>> SearchProducts(int[] SizeIds, int[] ColorIds )
{
IQueryable<Models.ProductBase> query = _dataContext.ProductBases
.Include(pb => pb.Variants).ThenInclude(v => v.ProductSize)
.Include(pb => pb.Variants).ThenInclude(v => v.ProductColor)
.Include(pb => pb.Variants).ThenInclude(v => v.imageVariants);
if(SizeIds.Length > 0)
{
query = query.Where(pb => SizeIds.Contains(pb.Variants.Any(pb.Variants.doesnotWork));
}
if(ColorIds.Length > 0)
{
query = query.Where(pb => ColorIds.Contains(pb.Variants.Contains(pb.Variants.doesNotWork)));
}
List<ProductBase> result = await query.ToListAsync();
}
CodePudding user response:
Fixed , this is working now
public async Task<IEnumerable<Models.ProductBase>> SearchProducts(int[] SizeIds, int[] ColorIds )
{
IQueryable<Models.ProductBase> query = _dataContext.ProductBases
.Include(pb => pb.Variants).ThenInclude(v => v.ProductSize)
.Include(pb => pb.Variants).ThenInclude(v => v.ProductColor)
.Include(pb => pb.Variants).ThenInclude(v => v.imageVariants);
if(SizeIds.Length > 0)
{
query = query.Where(pb => pb.Variants.ToList().Any(v => SizeIds.Contains(v.ProductSizeId)));
}
if(ColorIds.Length > 0)
{
query = query.Where(pb => pb.Variants.ToList().Any(v => ColorIds.Contains(v.ProductColorId)));
}
List<Models.ProductBase> result = await query.ToListAsync();
return result;
}