Bolt.RequestBus : How to use Filters – Part 4

This is fourth part of the series. In our previous post we discuss about how to publish and handle events for a request. If you don’t know what Bolt.RequestBus is please read the first part of this series. In this part I am trying to show how you can use filter in application and reduce the complexity of request handler. You can add more than one filter for any request. Filter may not always necessary but in some cases you might find this technique very helpful. This will help to reduce the complexity of Handler as you can divide the responsibility to filters. Generally filters more appropriate for Query when you reading data from system, but you need to read from different sources or do complex calculation on result.

Lets say you are displaying book details to user. Each book might have some discount and you need to display discount price also. Suppose you load book details from a database and another api is responsible for deciding the discount. That means you need to call the database to get book details and then call the api to get discount of the book if applicable. Rather than doing both request in requesthandler you can load books from database in request handler and add a filter that load discount price for the book from discount Api. Lets see the code.

Define the request and the record dto that we will return for the request.

public class GetBookByIdRequest : IRequest
{
    public Guid Id { get; set; }
}

public class BookDto
{
    public Guid Id { get; set; }
    public string Title { get; set; }
    public decimal Price { get; set; }
    public string Author { get; set; }
    public decimal Discount { get; set; }

    public decimal DisplayPrice => Discount > 0 ? Price - (Price*(Discount/100)) : Price;
}

[RoutePrefix("v1/books")]
public class GetBooksController : ApiController
{
    private readonly IRequestBus bus;

    public GetBooksController(IRequestBus bus)
    {
        this.bus = bus;
    }

    [Route("{id}", Name = RouteNames.BookById)]
    [HttpGet]
    public IHttpActionResult Get([FromUri]GetBookByIdRequest request)
    {
        var response = bus.Send<GetBookByIdRequest, BookDto>(request);

        return this.ResponseResult(response);
    }
}

Now define the handler that load books from bookrepository.

public class GetBooksByIdRequestHandler : RequestHandlerBase<GetBookByIdRequest, BookDto>
{
    private readonly IBookRepository repository;
    private readonly IMapper mapper;

    public GetBooksByIdRequestHandler(IBookRepository repository, IMapper mapper)
    {
        this.repository = repository;
        this.mapper = mapper;
    }

    protected override BookDto Process(GetBookByIdRequest msg)
    {
        return repository.GetById(msg.Id).NullSafeGet(bookRecord => mapper.Map<BookDto>(bookRecord));
    }
}

As you see we just load books from repository which does not has discount information. We need to call and api to get discount for all books if applicable. Lets write a filter for this.

public class LoadDiscountFilter : RequestFilterBase<GetBookByIdRequest, BookDto>
{
    private readonly IDiscountApiProxy proxy;

    public LoadDiscountFilter(IDiscountApiProxy proxy)
    {
        this.proxy = proxy;
    }

    public override void OnCompleted(GetBookByIdRequest request, BookDto value)
    {
        if(value == null) return;

        var discounts = proxy.Get(new[] {value.Id});
        value.Discount = discounts.FirstOrDefault(x => x.BookId == value.Id)?.Discount ?? 0;
    }
}

Now all you need is to tell your Ioc container to register any class against the implemented interface when the name ends with “Filter”.

builder.RegisterAssemblyTypes(assemblies)
            .Where(a => a.IsClass && 
                    (a.Name.EndsWith("Handler")                
                    || a.Name.EndsWith("Validator"))           
                    || a.Name.EndsWith("Filter"))
            )
            .AsImplementedInterfaces();

That’s it. You should now get the book details with discount price.

Happy coding 🙂

Advertisements

3 thoughts on “Bolt.RequestBus : How to use Filters – Part 4

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s