Git Product home page Git Product logo

autoqueryable's Introduction

AutoQueryable · NuGet PRs Welcome GitHub license Donate

AutoQueryable add auto querying functionality like OData on top of IQueryable with best url practices. It help you to make requests like http://baseurl/api/products?nameContains=frame&color=red,black with no effort.

Installing / Getting started

Package NuGet
Install-Package AutoQueryable NuGet Downloads Install without filters
AutoQueryable.AspNetCore.Filter Nuget Downloads Install for AspNet Core
AutoQueryable.AspNetCore.Swagger Nuget Downloads Install for AspNet Core
AutoQueryable.AspNet.Filter Nuget Downloads Install for Web api 2
AutoQueryable.Nancy.Filter Nuget Downloads Install for Nancy

Other web framework? You could made your own attribute, see Use AutoQueryable without attribute section.

Basic usage

[Route("api/[controller]")]
public class ProductsController : Controller
{
    [HttpGet]
    [AutoQueryable]
    public IQueryable<Product> Get([FromServices] myDbContext dbContext)
    {
        return dbContext.Product;
    }
}

With this url: /products?select=productId,name,color,productCategory.name,salesOrderDetail,salesOrderDetail.product

You will get result like:

[
    {
        "productId": 1,
        "name": "Product 0",
        "color": "red",
        "productCategory": {
            "name": "red"
        },
        "salesOrderDetail": [
            {
                "product": {
                    "productId": 1,
                    "name": "Product 0",
                    "productNumber": "24bb9446-d540-4513-a3c6-be4323984112",
                    "color": "red",
                    "standardCost": 1,
                    "listPrice": 0,
                    "size": "L",
                    "weight": 0,
                    "productCategoryId": 1,
                    "productModelId": 1,
                    "sellStartDate": "2017-07-14T00:00:00+02:00",
                    "rowguid": "f100e986-adeb-46b0-91de-9a1f8f3a4d11",
                    "modifiedDate": "0001-01-01T00:00:00",
                    "salesOrderDetail": []
                },
                "salesOrderId": 0,
                "salesOrderDetailId": 1,
                "orderQty": 5,
                "productId": 1,
                "unitPrice": 0,
                "unitPriceDiscount": 0,
                "lineTotal": 0,
                "rowguid": "00000000-0000-0000-0000-000000000000",
                "modifiedDate": "0001-01-01T00:00:00"
            },
            ...
        ]
    },
    ...
]

Api URL usage

Existing filters

By default filters are separated by AND (eg: color=red&color=black is translated by color == red AND color == black)

In a filter, comma separator is used for OR (eg: color=red,black is translated by color == red OR black)

String filters have a negate (NOT) variant:

String filters have the following modifiers:

Filter aliases are not case sensitive:

Note that filters works with primitive types, string, datetime & guid

Filter modifiers

AQ provide property modifiers to modify property before filter, modifiers are denoted with :

Selection

Projection

You can use projection in select & filters clauses with navigation properties (objects or collection of object)

Dto projection

You can still use dto projection and query over your dto with defined type:

[HttpGet]
[AutoQueryable]
public IQueryable Get([FromServices] AdventureWorksContext adventureWorksContext)
{
    return adventureWorksContext.Product.Select(p => new ProductProjection
    {
        Name = p.Name,
        ProductColor = p.Color,
        FinalPrice = p.price
    });
}

Or anonymous type:

[HttpGet]
[AutoQueryable]
public IQueryable Get([FromServices] AdventureWorksContext adventureWorksContext)
{
    return adventureWorksContext.Product.Select(p => new
    {
        p.Name,
        p.Color,
        FinalPrice = p.Price
    });
}

Unselectable properties

If you want some properties to be unselectable (eg: Id, Password, ...)

[Route("api/[controller]")]
public class UsersController : Controller
{
    [HttpGet]
    [AutoQueryable(UnselectableProperties = new []{ "Password", "Id" })]
    public IQueryable<User> Get([FromServices] myDbContext dbContext)
    {
        return dbContext.User;
    }
}

Note that Dto projection is the best way to limit selectable properties

Use base type instead of dynamic types

AQ uses dynamic types per default to ensure that the final flow will be as small as possible. In some cases you may not want to use dynamic types, there is a property for this:

[Route("api/[controller]")]
public class UsersController : Controller
{
    [HttpGet]
    [AutoQueryable(UseBaseType = true)]
    public IQueryable<User> Get([FromServices] myDbContext dbContext)
    {
        return dbContext.User;
    }
}

Note that final flow will include null and default values but you can escape them with serializer settings for exemple

Use AutoQueryable without attribute

If you don't want to use autoqueryable attribute you could use AQ directry in your code by passing it the querystring. First install the Autoqueryable package

Install-Package AutoQueryable
[Route("api/[controller]")]
public class UsersController
{
    [HttpGet]
    public IActionResult Get([FromServices] myDbContext dbContext)
    {
        var resultSet = dbContext.Product.Select(p => new { ... }).AutoQueryable(queryString);
        return new OkObjectResult(new {
            foo = "",
            ....,
            Values = resultSet;
        })
    }
}

Add Swagger parameters

If you want to add AQ parameters to your swagger docs, just add AutoQueryable to the swagger conf.

Install-Package AutoQueryable.AspNetCore.Swagger
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
    c.AddAutoQueryable(); // add this line
});

AutoMapper

ProjectTo()

If you are getting the error "Sequence contains no elements", you should use the package

Install-Package AutoMapper.Extensions.ExpressionMapping

and replace the

ProjectTo<T>()

with

.UseAsDataSource().For<T>()

Map relations

AutoQueryable and AutoMapper do not work together when it comes to mapping entity relations from an Entity to a Dto. To fix this, use the AutoQueryable profile setting

profile.ToListBeforeSelect = true

This performs a ToList() using the AutoMapper mapping before using the select query parameters and selecting only the properties asked by the Querystring

autoqueryable's People

Contributors

ngoov avatar nurhat avatar trenoncourt avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.