Skip to content

Commit

Permalink
docs: organize readme following drf documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
willianantunes committed Sep 17, 2024
1 parent 437bb41 commit 8728dee
Showing 1 changed file with 83 additions and 85 deletions.
168 changes: 83 additions & 85 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,84 +4,6 @@ AspNetCore REST Framework makes you focus on business, not on boilerplate code.

This is a copy of the convention established by [Django REST framework](https://github.com/encode/django-rest-framework), though translated to C# and adapted to the .NET Core framework.

## Sorting

In the `ListPaged` method, we use the query parameters `sort` or `sortDesc` to sort by a field. If not specified, we will always use the entity's `Id` field for ascending sorting.

## Filters

Filters are mechanisms applied whenever we try to retrieve entity data in the `GetSingle` and `ListPaged` methods.

### QueryStringFilter

The `QueryStringFilter`, perhaps the most relevant, is a filter that matches the fields passed in the query parameters with the fields of the entity whose filter is allowed. All filters are created using the equals (`==`) operator.

### QueryStringIdRangeFilter

The `QueryStringIdRangeFilter` goal is to filter the entities by `Id` based on all the `ids` provided in the query parameters.

### QueryStringSearchFilter

The `QueryStringSearchFilter` is a filter that allows a `search` parameter to be provided in the query parameters to search, through a single input, in several fields of the entity, even performing `LIKE` on strings.

### Implementing a filter

Given an `IQueryable<T>` and an `HttpRequest`, you can implement the filter as you prefer. Just inherit from the base class and add it to your controller:

```csharp
public class MyFilter : AspNetCore.RestFramework.Core.Filters.Filter<Seller>
{
private readonly string _forbiddenName;

public MyFilter(string forbiddenName)
{
_forbiddenName = forbiddenName;
}

public IQueryable<TEntity> AddFilter(IQueryable<TEntity> query, HttpRequest request)
{
return query.Where(m => m.Name != forbiddenName);
}
}
```

```csharp
public class SellerController
{
public SellerController(...)
: base(...)
{
Filters.Add(new MyFilter("Example"));
}
}
```

## Errors

The `ValidationErrors` and `UnexpectedError` might be returned in the `BaseController` in case of validation errors or other exceptions.

## Validation

Implement validators for the DTOs and configure your application with the extension `ModelStateValidationExtensions.ConfigureValidationResponseFormat` to ensure that in case of the `ModelState` being invalid, a `ValidationErrors` is returned. It might be necessary to add the `HttpContext` accessor to the services. Check the example below:

```csharp
services.AddControllers()
// ...
// At the end of AddControllers, add the following:
.AddModelValidationAsyncActionFilter(options =>
{
options.OnlyApiController = true;
})
// ModelStateValidationExtensions
.ConfigureValidationResponseFormat();
// ...
services.AddHttpContextAccessor();
```

## Serializer

`Serializer` is a mechanism used by the `BaseController`. Each controller has its own serializer. The serializer's methods can be overridden to add additional or different logic for specific entities. It works more or less similar to the [Django REST framework's serializers](https://www.django-rest-framework.org/api-guide/serializers/).

## Quickstart with an example

Let's create a CRUD API for a `Customer` entity with a `CustomerDocument` child entity.
Expand All @@ -91,9 +13,9 @@ Let's create a CRUD API for a `Customer` entity with a `CustomerDocument` child
Some characteristics of the entities:

- We should inherit from `BaseModel<TPrimaryKey>`.
- The `TPrimaryKey` is the type of the primary key. In this case, we are using `Guid`.
- The `TPrimaryKey` is the type of the primary key. In this case, we are using `Guid`.
- The `GetFields` method is mandatory. It informs which fields of the entity will be serialized in the API response.
- For fields of child or parent entities, we can use `:` to indicate them to be serialized as well. In this case, it is necessary to perform the `Include` with a filter.
- For fields of child or parent entities, we can use `:` to indicate them to be serialized as well. In this case, it is necessary to perform the `Include` with a filter.

```csharp
public class Customer : BaseModel<Guid>
Expand Down Expand Up @@ -206,7 +128,87 @@ public class CustomersController : BaseController<CustomerDto, Customer, Guid, A
}
```

## Glossary
## API Guide

### Sorting

In the `ListPaged` method, we use the query parameters `sort` or `sortDesc` to sort by a field. If not specified, we will always use the entity's `Id` field for ascending sorting.

### Filters

Filters are mechanisms applied whenever we try to retrieve entity data in the `GetSingle` and `ListPaged` methods.

#### QueryStringFilter

The `QueryStringFilter`, perhaps the most relevant, is a filter that matches the fields passed in the query parameters with the fields of the entity whose filter is allowed. All filters are created using the equals (`==`) operator.

#### QueryStringIdRangeFilter

The `QueryStringIdRangeFilter` goal is to filter the entities by `Id` based on all the `ids` provided in the query parameters.

#### QueryStringSearchFilter

The `QueryStringSearchFilter` is a filter that allows a `search` parameter to be provided in the query parameters to search, through a single input, in several fields of the entity, even performing `LIKE` on strings.

#### Implementing a filter

Given an `IQueryable<T>` and an `HttpRequest`, you can implement the filter as you prefer. Just inherit from the base class and add it to your controller:

```csharp
public class MyFilter : AspNetCore.RestFramework.Core.Filters.Filter<Seller>
{
private readonly string _forbiddenName;

public MyFilter(string forbiddenName)
{
_forbiddenName = forbiddenName;
}

public IQueryable<TEntity> AddFilter(IQueryable<TEntity> query, HttpRequest request)
{
return query.Where(m => m.Name != forbiddenName);
}
}
```

```csharp
public class SellerController
{
public SellerController(...)
: base(...)
{
Filters.Add(new MyFilter("Example"));
}
}
```

### Errors

The `ValidationErrors` and `UnexpectedError` might be returned in the `BaseController` in case of validation errors or other exceptions.

### Validation

Implement validators for the DTOs and configure your application with the extension `ModelStateValidationExtensions.ConfigureValidationResponseFormat` to ensure that in case of the `ModelState` being invalid, a `ValidationErrors` is returned. It might be necessary to add the `HttpContext` accessor to the services. Check the example below:

```csharp
services.AddControllers()
// ...
// At the end of AddControllers, add the following:
.AddModelValidationAsyncActionFilter(options =>
{
options.OnlyApiController = true;
})
// ModelStateValidationExtensions
.ConfigureValidationResponseFormat();
// ...
services.AddHttpContextAccessor();
```

### Serializer

`Serializer` is a mechanism used by the `BaseController`. Each controller has its own serializer. The serializer's methods can be overridden to add additional or different logic for specific entities. It works more or less similar to the [Django REST framework's serializers](https://www.django-rest-framework.org/api-guide/serializers/).

### Glossary

| Term | Description |
|----------------|-------------------------------------------------------------|
Expand All @@ -216,10 +218,6 @@ public class CustomersController : BaseController<CustomerDto, Customer, Guid, A
| `TDestination` | Type of the DTO. |
| `TContext` | Type of the Entity Framework context. |





## Notice

This project is still in the early stages of development. We recommend that you do not use it in production environments and check the written tests to understand the current functionality.

0 comments on commit 8728dee

Please sign in to comment.