Generally speaking, business logic shouldn't reside in any of the MVC players; it should only be consumed by your controller actions.
As many have mentioned, it's best to create a library to host business logic as a set of client agnostic, reusable components.
When done this way, we greatly increase reusability, compatibility, scalability, and testability with our software. We also reduce our dependence on certain framework features, which makes it easier to migrate to newer / different technologies.
Abstracting our business logic into a stand alone assembly (or assemblies) has served us well over the years. Our business logic can then be consumed by virtually any .NET technology (ASP.NET MVC/API/Core, WPF, Win Forms, WCF, UWP, WF, Console, etc.).
In addition, we like our middle tier to handle business rule and validation logic to reduce our dependencies on the .NET MVC Framework's. For example, we avoid using the .NET MVCs validation helpers and instead rely on our own. This is another factor that allows us to easily consume our business logic from any .NET technology.
Logically designing our middle tier this way has allowed us to easily achieve this physical architecture:
It was written with Peasy.NET, and has served us well over the years. So well in fact that we decided to open source it.
If anyone is curious as to what our middle tier looks like, here is a sample of a client agnostic, business layer. It also showcases the consumption of it by multiple .NET clients (ASP.NET MVC, Web Api, and WPF).
Hope this helps someone!