'Suggested architecture for a project with 2 Frontend applications (Blazor Server and Angular) with EFCore, Identity, Mediatr

I am currently working on a school project with a classmate. We've decided on making the classic setup of an Administration-client (Blazor Server) and a Member-client (Angular).

We have 7 Projects in the solution so far:

Solution
├───Project.MemberClient (Angular)
├───Project.AdminClient (Blazor Server)
├───Project.Api (REST API)
├───Project.Application (CQRS & Mediatr)
├───Project.Core (Entities, Enums, Interfaces)
├───Project.Infrastructure (Database Context & Migrations)
└───Project.Test

We're using EntityFramework for the database, which both the API and Blazor Server have access to, through Mediatr.

Unfortunately, we can't come to terms with how we should handle the use of the API.

  1. My classmate is convinced that both Blazor Server client and the Angular client should go through the REST API.
  2. I'm convinced that we don't need to go through the API with the Blazor Server-client, since it can access Mediatr through Dependency injection. I feel it's silly to go through the API to deserialize a C# object to JSON just to serialize it again straight after.

This is a request on the API:

[HttpPost("organizr-user")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<OrganizrUserResponse>> CreateOrganizrUser([FromBody] CreateOrganizrUserCommand command)
{
    var result = await _mediator.Send(command);
    return Ok(result);
}

This is a request on Blazor Server:

private async Task OnButtonSave_Clicked()
{
    _userCreated = false;
    _showErrors = false;
       
    var query = new RegisterUserRequest
    {
        FirstName = _firstName,
        LastName = _lastName,
        Gender = (Gender)_gender,
        Address = _address,
        PhoneNumber = _phoneNumber,
        Email = _email,
        Password = _password,
        ConfigRefreshPrivilege = _refreshConfiguration
    };

    var result = await Mediator.Send(query);

    if (!result.Succeeded)
    {
        _showErrors = true;
        _errors = result.Errors.ToList();
    }
    else
    {
        _userCreated = true;
    }
}

I feel (yeah, there are a lot of feelings involved) like we still uphold the principle of only one access point by the use of Mediatr. Blazor doesn't need the API, but Angular does.

What would be the right way to go about this?



Solution 1:[1]

I am glad you are taking this school project so seriously.

As is with all architectural decisions - "it depends". There is no such thing as a silver bullet approach, only the best for you situation.

I think you both have some points. You are correct in saying you are upholding a single point of access, and thus reducing the amount of code you need to write - but that is not the only thing to consider here. You need to ask yourself a few more questions.

You should treat this as an production application that has the potential to scale

Here are some questions you should ask yourself.

  1. Are the API and the Blazor web server going to be hosted on the same server as the database ?
  2. API's should be stateless, are you going to keep that consideration while writing your blazor web app, since they consume the same code ?
  3. Is your application scalable ? How will you implement things like load balancing on both the API and the blazor web server ?
  4. Can I easily replace/change some in the overall design if needed ?

If I had to choose for you, I would suggest filtering everything through a web API.

Here is why:

  • You have more options around hosting - you can host your blazor web application on one server and the database/webAPI on another.
  • It forces developers into "The pit of success". If you have 10 developer working on this product, it's easier for them to think of the application as "one API" rather than an "API and a server that uses the same code". This may not seem important now, but trust me, large scale application can get very hairy very quickly if you don't keep things as simple as possible.
  • Creating load balancers on Blazor web server can be tricky, since it uses SignalR to communicate with the client.
  • Testing becomes easier. What if your blazor application has functionality that your Angular client doesn't? That means it would never be built into the web api. Now you need to do things like load testing, stress testing, etc on two separate servers rather than just the web API. The testing required on the Blazor web server would be heavily scaled down if everything ran through the Web API.
  • And last but not least,the Blazor developers pride themselves on how easy it is to switch between Blazor client and Blazor web server. What if, in future, you decide that Blazor web server isn't the best solution, and you would prefer blazor client ? If everything was running through an Web API this would be a few lines of code. If not - you have a lot of refactoring to do.

I think its a better idea to write a few extra lines to "serialize and deserialize " through an API now, and save yourself potential hassle later.

This is my opinion based off my personal experiences - keep things simple, readable and scalable.

I hope this helped.

Let me know if you would like me to clarify anything.

Happy coding!!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Geoffrey Fook