Clean Architecture with MediatR, how does one handle SelectListItem

Viewed 264

Background:

I am building an "admin application" (GitHub) to manage another community-driven lyrics web application. Users that sign up can submit new artists and lyrics and the admin application I'm building will allow an admin or a moderator to approve new submissions ...etc.

I built the admin application based on Jason's Clean Architecture solution template. The template uses a SPA built in Angular as the front-end and I wanted regular MVC with Razor views, so I had to get rid of the Client app and change my controllers so that they would return Views instead of JSON.

All went well.

Problem:

I now want to create the ability to add a new artist, so I have an initial GET request action to load the form, and a POST request action to handle the submission.

On the GET request, the view model that I need to return has a SelectListItem to create a drop down (for gender selection) on the Razor view.

ArtistsController.cs

[HttpGet]
public async Task<ActionResult> Create()
{
    CreateArtistGenderDto viewModel = await Mediator.Send(new CreateArtistQuery());
    
    return View(viewModel);
}

[HttpPost]
public async Task<ActionResult<int>> Create(CreateArtistCommand command)
{
    return await Mediator.Send(command);
}

CreateArtistQuery.cs

public class CreateArtistQuery : IRequest<CreateArtistGenderDto>
{
}

public class CreateArtistQueryHandler : IRequestHandler<CreateArtistQuery, CreateArtistGenderDto>
{
    public async Task<CreateArtistGenderDto> Handle(
        CreateArtistQuery request,
        CancellationToken cancellationToken)
    {
        CreateArtistGenderDto model = new CreateArtistGenderDto();

        return model;
    }
}

CreateArtistGenderDto.cs

namespace bejebeje.admin.Application.Artists.Queries.CreateArtist;

public class CreateArtistGenderDto
{
    public Gender SelectedGender { get; set; }
    
    public List<SelectListItem> GenderOptions = new List<SelectListItem>
    {
        new SelectList(Enum.GetValues(typeof(Gender))
    };
}

public enum Gender
{
    Female,
    Male,
    NotApplicable
}

The issue is, if I follow the MediatR pattern and place my Query class in the Application project, that project does not know what a SelectListItem is and if I add a reference to the package, I'll be breaking the nice dependency chain that I currently have.

clean architecture

In other words, the dependencies will no longer flow inward, but they'll go outward too and we've been told that is "bad" and creates a mess.

selectlistitem issue

What is the right way of going about this without breaking the dependency chain/flow?

0 Answers
Related