0

I use CQRS for most of my applications. My request objects contain the data needed by the Handler to perform the Request.

However, I've started to realize that some data points we have are required on every single request and are more contextual to the request. For example, the ID of the specific Division the request is for is added to the header of every http request.

Originally, this contextual data was added to the request before it was sent to the CQRS dispatcher. Something like this (This is in ASP.NET with Mediatr) -

[FromHeader]
public int DivisonId { get; set; }

public async IActionRequest CreateOrder([FromBody] CreateOrderRequest request) { request.DivisionId = this.DivisionId; await _mediator.Send(request); }

However, I'm considering moving to using a Scoped Service that can provide this contextual data within the Handler itself.

public class CreateOrderHandler
{
   private readonly ICurrentDivisionService _currentDivision;

public CreateOrderHandler(ICurrentDivisionService currentDivision) {...}

public async Task Handle(CreateOrderRequest request) { // Code uses _currentDivision.DivisionId instead of request.DivisionId } }

My question is this - Should all data be on the request? Or does providing contextual data that is needed for every request through a service make sense?

mccow002
  • 121

1 Answers1

2

Should all data be on the request? Or does providing contextual data that is needed for every request through a service make sense?

This isn't a universally answerable question, context applies.

Proponents of pure functions will inherently favor passing everything via the request and not routing some of the information via another external dependency.

However, there are justifiable cases where external routing can make sense, e.g. if you're implementing multi-tenancy and you're trying to apply a globalized tenant ID that is applied every step of the way. Passing it via the request could potentially open you up to bad actors overriding the tenant ID, whereas routing it via a pathway that the requestor does not have access to makes that much harder (if not impossible) to accomplish.

Rather than ask for an objective universally applicable answer, this is something you need to weigh for your specific use case. Rather than pick between two things based on what they look like or what you prefer; what would be the pros and cons of either approach, and which pros/cons are more important for your specific use case?


Here are some musings from my end. These aren't answers, these are just things that I would consider during the analysis:

  • Can the same request (with the same values) make sense for a different division?
    • For example, if your request contains globally unique identifiers (e.g. a product GUID) that does not occur in other divisions, then the request is already inherently division-specific.
    • Compared to the previous, if the identifiers are reused in different divisions (e.g. an auto-incrementing product integer ID, i.e. it starts from 1 for every division and therefore their uniqueness is only scoped to the division itself), then a request without a division identifier would not be identifiable to a specific division.
  • Is this part of an overarching security measure whereby a division ID is used as a form of authorization control?
  • Is there ever a possibility that within one request, more than one division is referenced? (also consider admin endpoints, not just end-user endpoints)
  • Are you trying to protect against bad actors? Can a bad actor "unlock" something that they most definitely should not be able to? Or is this more a matter of "if you send the wrong data your request just won't work"?
    • Subsequently, what is the blast radius of such a circumvention, whether through a bad actor or an honest mistake?
Flater
  • 49,580