9

I am working on a proof of concept project using Blazor WebAssembly. The project already has a React front end that I am hoping to replicate in Blazor.

I have the following projects in my solution:

  • Domain - contains entities and does not reference any other layers
  • Application - references the domain and contains DTOs, commands/queries (using MediatR/Dapper), validators (using FluidValidation) and interfaces for subsequent layers to implement
  • Persistence – references application and uses EF Core to store the domain models in the database
  • API - a Web API that registers everything using DI and exposes the commands/queries from the application layer via controllers
  • React Front End - uses AJAX to talk to the API

I would like to reference the Application layer in a Blazor WebAssembly project so that I can reuse the validation rules that exist against the DTOs. Would it be possible for somebody to step though the code in the browser and extract sensitive information, such as connection strings, from the commands/queries?

For example, a simple query may look like this and stepping through the code would allow the IDbConnection to be inspected:

public class PayCategoryListQueryHandler
    : IRequestHandler<PayCategoryListQuery, PayCategoryListQueryVm>
  {
    private readonly IDbConnection _connection;

    public PayCategoryListQueryHandler(IDbConnection connection)
    {
      _connection = connection;
    }

    public async Task<PayCategoryListQueryVm> Handle(PayCategoryListQuery query, CancellationToken cancellationToken)
    {
      {
        var viewModel = new PayCategoryListQueryVm();

        viewModel.AddRange(
          await _connection.QueryAsync<PayCategoryListItemDto>(
            "SELECT Id, Description, MakeAttendedTimeZero, IsOffSite, IsVisibleToClient FROM PayCategory ORDER BY Description"));

        return viewModel;
      }
    }
  }

Do I need to extract the DTOs and their validation a separate layer that does not contain any database access code to prevent the connection string being leaked?

Clarification

To try and clarify the issue I would like to try and explain my situation a bit better.

My current application uses a React front end with Formik and Yup providing the validation. This means that each time a change is made to a validation rule I need to reflect it in two places – the Application layer and the React application. I was hoping that moving to Blazor would alleviate the duplication by only having to maintain validation rules in the Application layer.

The architecture I am currently using is based upon the NorthwindTraders sample application.

Using that example, CreateCustomerCommand makes use of CreateCustomerCommandValidator which will respond to POST requests via CustomersController. In order to use this for client-side validation in Blazor WebAssembly I would currently need to reference the Application layer.

Given this scenario should all the commands (not command handlers) and validators be moved to a separate project which could then be referenced by Blazor. The command handlers could remain in the Application layer therefore removing any database access code.

Jesse
  • 3,243
  • 1
  • 22
  • 29
Newm
  • 1,313
  • 3
  • 16
  • 29
  • I don't want that on the client. The PayCategoryListQueryHandler is in the Application layer which is also where the DTOs and validation live. When using React it goes AJAX->API->Application so there is no issue. Using Blazor (so that I can reuse the validation) I reference the Application layer which is where the problem arrises. – Newm Feb 04 '20 at 12:50
  • Actualy you sould not reference your application layer in the Blazor wasm app, as you don't do it with your React front. But call your APIs. You can (and I encourage you) reference your Domain layer – agua from mars Feb 04 '20 at 13:06
  • Regarding validation, if you use Fluent take a look at this https://blog.stevensanderson.com/2019/09/04/blazor-fluentvalidation/ – agua from mars Feb 04 '20 at 13:08
  • 1
    Split your DTOs out of your Application layer, put them in the Shared - or whatever you choose to call it - project of the Blazor setup and reference that from the client and the app layer. Better yet, reference the Domain and don't have DTOs. – Rich Bryant Feb 04 '20 at 13:50
  • 1
    @Rich Bryant - sorry I was updating the post and did not see your comment. The DTOs are largely used to remove the EF nativation properties etc. I think your suggestion to move them to another project may be the way to go. – Newm Feb 04 '20 at 14:16
  • 1
    @Newm, what solution did you end up using for this? I feel it should be a quite common issue to have, but your question seems to basically the only one on the internet. – Michel Jansson Nov 04 '20 at 22:42
  • You should use DTOs but they do not belong in the Application Layer. And should not have a dependency on the Model. – H H May 24 '21 at 04:29

2 Answers2

4

Create a new dotnet.standard-project called something like, MyProject.Domain.Shared. There you put all communication (poco-)classes.

The Shared-Project is consumed by your Domain-Project, Application-Layer and Client-Layer. The Domain-Project is consumed by the Application-Layer and Persistence-Layer.

In the Shared-Project you put:

  • DTOs
  • Requests
  • Responses
  • Validators

In the Application-Project you put:

  • Request Handlers
  • Response Handlers

In the Domain-Project you put:

  • Domain-Objects
  • Repository-Interfaces
  • Handlers which consumes the requests and produce responses)
boop
  • 7,413
  • 13
  • 50
  • 94
Alois
  • 361
  • 2
  • 18
  • Would it not violate the clean/onion architecture to have the request handlers in the domain project, as it then would require dependency on infrastructure etc.? – Michel Jansson Nov 04 '20 at 22:48
  • 1
    Yes you are right. If you implement the clean architecture in a strict way the Requests, DTOs, etc. should always be mapped into Domain-Project and not be referenced. In real world I think it saves time to share that class. But of course, each pro comes with a contra. So you must decide it per project. – Alois Nov 06 '20 at 07:26
1

to keep the presentation layer separated from the application layer, even if you're using Blazor, you should not reference directly some application layer's code from any point of the presentation layer. Instead, call an API endpoint the same way you're doing it with the React front-end.

Also, as stated by others in comments, you should extract your dto-poco class to another project, and reference this one.

Matt
  • 133
  • 1
  • 7