3

Currently implementing Clean Architure using MediatR with

     IRequestHandler<IRequest<ResponseMessage>, ResponseMessage>
     IRequest<ResponseMessage>

The implementation now separates between business logic layer, infrastructure and controller and they rely on dependency injection and decoupled.

Currently the implementation is in Asp.Net Core and this framework supports response code generation done in controller as example below.

    [HttpGet]
    [ProducesResponseType(200)]
    [ProducesResponseType(404)]
    public async Task<IActionResult> GetObject([FromQuery] int Id)
    {
      ...
      return Ok(some_result_to_show);   // This generates code 200
    }

I wonder where in Clean Architecture layer should translate business rule decisions made into correct response codes and what would be good practice or set methodology doing this adaption. Seems quick implementation would be still doing it in controller however wonder if this decision belongs to business rules or application business rules and should be handled in different layer before translating into response code in presentation layer. If then Asp.Net core or MediatR (or any other library) has in-built framework or features to support such design.

swcraft
  • 2,014
  • 3
  • 22
  • 43
  • Some of the business rules could impact the reasons on why it is a bad request (400). How would you transfer such message to controller so that controller send it to presentation layer? Is there any good design around it so that explanation come from the business rules then delivered to the outer layer in well designed structure? – swcraft Jul 28 '18 at 18:12
  • Thought I had removed my ramble before you saw it.wanted to give it some more thought. – Nkosi Jul 28 '18 at 18:14
  • I still think you are mixing concerns though between HTTP Status codes and your application's status codes – Nkosi Jul 28 '18 at 18:16
  • My intention is not to make decision of which response code in business layer. Rather, the question goes to is there any sophisticated in-built support of existing framework (whether it be MediatR, ASP.NET Core, etc.) in terms of correct implementation (design) in translating business rule decisions made into correct response codes and which layer in Clean Architecture should be responsible in each stage in the flow. – swcraft Jul 28 '18 at 23:08

2 Answers2

1

One way I found is as below

In the business layer,

  RequestMessageValidator : AbstractValidator<RequestMessage>
  {
     RuleFor(r => r).{ConditionSyntax}().WithErrorCode(ResponseCodeString);
  }

Then in the controller,

  return StatusCode(
                Convert.ToInt32(ValidationResult.Errors[0].ErrorCode),
                ValidationResult.Errors[0].ErrorMessage);
swcraft
  • 2,014
  • 3
  • 22
  • 43
  • yeah but I don't think `return StatusCode` is needed if using fluent validation middleware. (`AddFluentValidation`) this should be handled for you then. – Konrad Sep 04 '18 at 12:10
0

It is definitely the application / presentation layer which is MVC or your controllers. I would suggest you to throw specific exceptions that serve only one purpose.

For instance when you query data you will have a request-handler that looks for the data that should be found using a given id (a guid, or whatever). Now that identifier is valid but it is none existence on your database. You don't want to access the httpcontext (even though you could) in your handler because than your businesslogic would be coupled to asp.net. Throw an exception that tells you, that a resource was not found to produce a 404 error response (let's call it ResourceNotFoundException i.e.). For that exception you can then use an exception-filter instead of data-annotation above your controller-endpoints. You can have many exception-filter. Each serves its own purpose.

If you do it like that, your businesslogic will be decoupled from any application / presentation layer and can easily be reused where ever you want.

If you want to see an example of how an exception-filter works, I've created a simple solution for that a while ago. You can find it here.

Not directly related to your question but instead of returning an IActionResult, you could also return a data-transfer-object when you want to send data to the client. It will also produce a Http.OK statuscode.

alsami
  • 8,996
  • 3
  • 25
  • 36
  • Thanks for the response.. But what I am asking could be slightly different than the point you made in your answer. You are right that you don't want to call HTTP Context response code at business logic. However the actual contents explaining further on bad request, as one example, could be done on the business logic after reasoning done. Controller could be simply delivering the decision already made using httpcontext. – swcraft Jul 28 '18 at 17:03
  • What you mean bad request could be produced directly within the controller? When validating modelstate for instance? – alsami Jul 28 '18 at 17:05
  • In Clean Architecture, decision made if it is bad request then with what reason is done using FluentValidation. – swcraft Jul 28 '18 at 17:10
  • Reread your comment and finally understood what you mean. Yes, business-logic will make decision, will validate a new entity and what not. You can still have multiple exceptions that you just throw and create an exception-filter for each, that handle and set the response accordingly. Cleanarchitecture also means single-responsiblity and DRY, which you will not have if you handle the very same businesslogic each time in your controller endpoints. By the way, I am also using fluent-validation for the same matter. An exception is thrown when validation has failed and a filter handles that. – alsami Jul 28 '18 at 17:11
  • I haven't dug whole lot, however this link below could answer your DRY question on validator. https://stackoverflow.com/questions/30730937/c-sharp-fluentvalidation-for-a-hierarchy-of-classes – swcraft Jul 28 '18 at 18:14
  • It wasn't meant for the validation and it was not a question. I know it can be made reusable easily. I am taking more about the fact that you have to repeat the controller endpoints "logic" to have specific response-codes, that are returned. Anyway you should look into my suggestion bc it is definitely what you need ;) – alsami Jul 28 '18 at 18:16
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/176950/discussion-between-jp-medevice-and-alsami). – swcraft Jul 28 '18 at 20:45