Search code examples
c#asp.net.net.net-coreminimal-apis

How to query on SQL Server in .NET 6 minimal API by anything other than Id


I have a small database that has been created by EF using a typical model class:

public class Metrics
{
    public int Id { get; set; }
    public string? MetricValue { get; set; }
    public string? MetricHost { get; set; }
    public string? MetricTime { get; set; }
}

The database is now populated with data and my Minimal API can return all the entries from:

app.MapGet("/metric", async (DataContext context) => await context.Metrics.ToListAsync());

And also, I can query by Id:

app.MapGet("/metric/{id}", async (DataContext context, int id) => 
    await context.Metrics.FindAsync(id) is Metric metric ? 
    Results.Ok(metric) :
    Results.NotFound("Metric not found"));

I've been searching the web for something that would show how to search by another property but have not found anything that works. e.g.,

app.MapGet("/hostnames/{MetricHost}"...

This article on CodeMaze is the closest I've found but none of the examples seem to work:

https://code-maze.com/aspnetcore-query-string-parameters-minimal-apis/

Any help is appreciated. Here's an example that did not work:

app.MapGet("/search", (SearchCriteria criteria) =>
{
    return $"Host: {criteria.MetricHost}, Id: {criteria.Id}";
});

With model changes:

public class Metric
{
    public int Id { get; set; }
    public string? MetricValue { get; set; }
    public string? MetricHost { get; set; }
    public string? MetricTime { get; set; }

    public static ValueTask<Metric?> BindAsync(HttpContext context, ParameterInfo parameter)
    {
        string hostname = context.Request.Query["MetricHost"];
        int.TryParse(context.Request.Query["Id"], out var id);

        var result = new Metric
        {
            MetricHost = hostname,
            Id = id
        };

        return ValueTask.FromResult<Metric?>(result);
    }
}

Solution

  • You are binding wrong type, BindAsync should be part of SearchCriteria:

    app.MapGet("/search", (SearchCriteria criteria, DataContext context) =>
    {
        IQueryable<Metric> query = context.Metrics;
        if(criteria.MetricHost is not null)
        {
            query = query.Where(m => m.MetricHost == criteria.MetricHost)
        }
        // ... rest of filters
        return await query.ToListAsync();
    });
    
    public class SearchCriteria
    {
        public string? MetricHost { get; set; }
        // ... rest of filters
    
        public static ValueTask<SearchCriteria?> BindAsync(HttpContext context, ParameterInfo parameter)
        {
            string hostname = context.Request.Query["MetricHost"];
            // ... rest of filters
            var result = new SearchCriteria
            {
                MetricHost = hostname,
            };
            return ValueTask.FromResult<SearchCriteria?>(result);
        }
    }
    

    Read more: