简体   繁体   中英

C# MVC.Net Controller Simplification

I'm trying to avoid the "fat controller" scenario.

There are many examples of Controllers calling one API, but what if your controller needs to call two or more API's?

How do you simplify such a scenario? It seems like there should be a cleaner way:

private ServiceTwo serviceTwo = new ServiceTwo();
private MailService mailService = new MailService();

[HttpPost]
public async Task<ActionResult> Index(Customer formData) 
{
    if (!ModelState.IsValid) 
    {
        return View();
    }

    var apiOneService = new ApiOneService(formData);

    if (apiOneService.ExistingUserCheck()) 
    {
        ModelState.AddModelError("Email", "* Email address already exists.");
        return View(formData);
    }

    var apiTwoResult = serviceTwo.CreateTrial(formData);

    var emailResult = await mailService.SendMailAsync((formData));

    return RedirectToAction("Index", "TrialConfirmation");
}

For something this small, you can just extract the logic to some other method in the controller:

[HttpPost]
public async Task<ActionResult> Index(Customer formData) {
    if (!ModelState.IsValid) {
        return View();
    }

    var ok = await CreateTrial(formData);
    return ok 
        ? (ActionResult)RedirectToAction("Index", "TrialConfirmation")
        : View(formData);
    }
}

protected async Task<bool> CreateTrial(Customer formData) {
    var apiOneService = new ApiOneService(formData);
    if (apiOneService.ExistingUserCheck()) return false;

    var emailTask = mailService.SendMailAsync((formData));
    var apiTwoResult = serviceTwo.CreateTrial(formData);
    await emailTask;

    return true;
}

For a more complicated method, you could extract the logic into a separate class or layer as well.

You can simplify controller till that:

https://github.com/DashboardCode/Routines/blob/master/AdminkaV1/Injected.AspCore.MvcApp/Controllers/UsersController.cs

Here you could see only metadata definition: what is an id, which fields need load data as for one-to-many which as for many-to-many and so on.

Actually you are asking how to write Internal DSL that can define my controllers in "bigger bricks". Just write it.

It is possible but not brings full satisfaction. People stick to general purpose code because it is.. general. Even if verbose.

I tend to implement a service layer in some similar cases and exposing Interfaces with dependency injection. Logic is in the service layer and controller just expose this logic to the view.

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