简体   繁体   中英

Business logic in the API controller

I have this method in my ClientsController:

//POST api/v1/clients
[HttpPost]
public async Task<ActionResult> CreateClient([FromBody] CreateClientDto createClientDto)
{
    await _createClientService.Create(createClientDto.MapToClient());
    return CreatedAtRoute("GetClient", new { clientId = createClientDto.ClientId });
}

As you can see, this method references a previously injected service. The service looks like this:

public class CreateClientServiceImpl : ICreateClientService
{
    private readonly ConfigurationDbContext configurationDbContext;

    public CreateClientServiceImpl(ConfigurationDbContext configurationDbContext)
    {
        this.configurationDbContext = configurationDbContext;
    }

    public async Task Create(Client client)
    {
        await configurationDbContext.Clients.AddAsync(client.ToEntity());
        await configurationDbContext.SaveChangesAsync();
    }
}

This is where the problem arises. Where will I check if the clientId exists? I think not in the ICreateClientService because it would violate the Single Responsibility Principle rule. I can create next service which will check if the user exists and use it in controller method, but I think it will be too many logic in controller method. What should I do then? To be sure, ClientId is not an incremental Id, but too is unique.

First answer this question: How do your application to react, if a client already exists?

Also, are you aware of the fact that SaveChangesAsync() can throw a DbUpdateException or DbUpdateConcurrencyException ? Currently, you are not handling these cases.

One possibility would be to introduce an exception, for example DuplicateClientException and throw this exception in your CreateClientServiceImpl.Create method, if this client already exists. Another option is that Create returns a bool, indicating whether the create statement was successful. It could return false if it failed (one reason could be, that the client already exists). You could also return a Result -object. There is a library by Ardelis, see Result , which offers a solution to the problem you have.

Your controller method can then handle the exception, translate the method return value as you see fit or (automatically) turn the Result object into the correct status code, for example a 400 Bad Request .

Right now, I believe your code would run into an exception, if you have your primary keys set up correctly, and your controller would return a 500 Internal Server Error . If this is the behavior you want, then you don't have to change anything.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM