Single responsibility principle in MVC - c#

I have a MVC project with following pattern
View <-> Controller <-> Service <-> Repository/Entities <-> Database
For example, if I have 2 tables (Customer and Order) in my Database, then I have 2 classes in my Repository layer (this class map 1:1 with my database table because I'm using EF Code First) :
public class Customer
{
[Key]
public int CustomerID { get; set; }
public int Name { get; set; }
//rest of columns here
}
public class Order
{
[Key]
public int OrderId { get; set; }
//rest of columns here
}
Then I have services :
public class CustomerService : ICustomerService
{
void AddNewCustomer(Customer obj);
void GetCustomerOrders(Customer obj);
//rest of methods here
}
public class OrderService : IOrderService
{
void GetOrderById(int id);
void GetCustomerOrders(Customer obj);
//rest of methods here
}
you probably notice that I have GetCustomerOrders.
My question :
Without breaking Single responsibility principle rule, where do I put GetCustomerOrders? In CustomerService, OrderService, or both?
Did I break the Single responsibility principle rule by having more than one service in my controller? For example :
public class TransactionController : Controller
{
//more than 1 service inside this class
private ICustomerService _customerService;
private IOrderService _orderService;
public ProjectController()
{
this._customerService = new CustomerService();
this._orderService = new OrderService();
}
public ProjectController(CustomerService customerService, OrderService orderService)
{
this._customerService = customerService;
this._orderService = orderService;
}
public ActionResult Index()
{
Return View();
}
public ActionResult CreateCustomer()
{
//rest of code here
}
public ActionResult CreateOrder()
{
//rest of code here
}
}
I have bunch of controller with bloated Action method, for example my ProductController have :
Index
Add
Edit
Delete
Priority
AddPriority
EditPriority
DeletePriority
If the controller were split
ProductController
Index
Add
Edit
Delete
ProductPriorityController
Index
Add
Edit
Delete
I see that the template project from Microsoft doesn't have more than one CRUD operation inside their Controller (towards bottom example). Is it a bad design if I have more than one CRUD operation inside my controller (top example)? I was thinking of splitting my Controller but I don't want it to bite my ass later for having to maintain 50 controllers.
Any help will be appreciated and apologize for bad english.

I will put it in customerService because it depends on the customer you pass to the function.
I think that the maximum services for controller is about ~3/4 services in one controller. So in your case i think this is good.
The controller doesn't need to implement your business logic. They only should take data and post them to the right place. I think you should create a manager / service / class that will handle the business logic. About your CRUD operations, It should be all in one controller (get/post and etc).

1- You don't always need to go through a service to access the repository in the controller.
You can embrace an onion architecture for example where instead a 3 layers architecture. Personally I think important the concept of accessing layers in the right way, but adding a indirection level just to call a repository with no logic inside the service, makes me question the value of the service, because in that case, what is the service that the service is providing?
Since your repository knows the domain, you can return domain objects.
What about commands and queries?
You can read a little bit more and make your one of all this your preference or maybe adapt an idea. Just keep the idea of separation of concerns always in mind, you are on the good way.
About questions 2 and 3 I agree with #Rik, but I will paste his answer just to make my answer complete (credit on him)
2- No, that's fine. In fact, you're are dividing the different responsibilities over separate services, which is very "single responsibility"
3- I'd say keep them separate if they do separate things. Maintaining a number of controllers is easy if you know which controller is responsible for what.

I suggest making a CustomerOrdersController.
No, that's fine. In fact, you are dividing the different responsibilities over separate services, which is very "single responsibility".
I'd say keep them separate if they do separate things. Maintaining a number of controllers is easy if you know which controller is responsible for what.

Related

Mapping and querying the web api in service layer

I am making a web api and have created several classes, the class controller and the service as well as the dto and the model.
In the controller I have the methods for post and get and the business logic is in the service
My question is how can I make the queries from the model class and map the queries to the dto
Service Layer:
public class GermanyService : IGermanyService
{
public Task<IEnumerable<GermanyDto>> All()
{
throw new NotImplementedException();
}
public Task Create(GermanyDto germany)
{
throw new NotImplementedException();
}
}
Controller:
public class GermanyController
{
private readonly IGermanyService _germanyService;
public GermanyController(IGermanyService service)
{
_germanyService = service;
}
[HttpGet]
public async Task<IEnumerable<GermanyDto>> Get(int id)
{
return await _germanyService.All();
}
[HttpPost]
public async Task Post([FromBody]GermanyDto dto)
{
await _germanyService.Create(dto);
}
Okay :)
Use an interface implementation ->
seggregate your business logic's interfaces, so you have many of them, split into their single responsibilities and then join them in one:
Example
public interface IStreetName {
string StreetName{get;set;}
}
public interface IPostCode {
string PostCode {get;set;}
}
... other implementations for an Address DTO f.x.
then
public interface IAddress : IPostCode, IStreetName, ...
{
//should be empty
}
now you can Implement Iaddress on your DAL object, and not need an actual DTO -> because you ONLY reference the interface in your business logic.
etc.
Obviously, you would have to rename the intefaces for the properties on your "GermanyDTO", which I don't know what looks like.
EDIT:
Using mappers like "auto-mappers" or the like is usually a sign of 2 things.
1: You don't understand how to write effective mapping yourself.
2: Using a framework to accomplish something, doesn't absolve you from testing. And frameworks are notoriously difficult to test.
(Because, following proper procedure, you would have to test the interface between your code and the framework, and by extension the code between framework and 3rd part component, failing to do so, will setup you up for risks, between what you THINK the framwork does, and what it ACTUALLY does)
So Yes, using something like "Automapper" is at best a supression of a symptom rather than a cure.
Because the root cause is failing to understand how interfaces solve mappings.
And using a tool, to do something you can do cleaner yourself, and improve the structure of your entire system as a result? Is a no-brainer.
Just notice your own statement:
"Do you think it is effective? Automapper solves some of my issues"
You are seriously going to implement a direct dependency in your system, because of a framework?
You are admitting to writing bad code, because a framework can take away ... what? A little bit of boiler plate?

Best practice ASP.NET Controller for Common Actions

I have a quick question,
In so many examples I saw controller Actions which does not return any View or Partialview are also added in the same controller - Now in my situation i have multiple controllers which i need to run same ACTIONS such as
Controller A will Run Action A
Controller B will run Action A
Adding Action A in both Controller A and B does not look right.
As I am making [HttpPost] calls for Action A using AJAX, therefore, i want this to be in a Controller for easy POST access, although I don't want to add the same Action in both Controllers
I can add action A in Controller A and let Controller B access the same action requesting from Controller A instead but what I was thinking
**How about if I create a new Controller called
commonActionContoller
and put "ACTION A" in it and let everything use commonActionContoller when Action A is required?**
Cheers
EDIT: Example added as following
An example application which has Person and Countries, So Person model is the same for all Countries but we have different Controller for each country so If an Admin wants to update Person's model with field IsEmpoyed from true to false then they go to for example {USA}/Index controller and switch true to false. Now, this is same for {AUS}/Index and {China}/Index so Action which changes IsEmpyed to true/false is the same across all controllers. To make this work i don't want to add Action IsEmplyed to all country controllers - (Couldn't think of a better example) –
You should write Action A in both Controller. Otherwise it will violate Single responsibility principle. Best practice is to move the implementation codes from Controller to a Service layer. For example, if you want to load Product Category for Products and Sub-Categories, then code will be like this:
public interface ICategoryService
{
List<Category> LoadCategory();
}
public class CategoryService : ICategoryService
{
public List<Category> LoadCategory()
{
//code here
}
}
public class ProductController : Controller
{
private readonly ICategoryService _categoryService;
public ProductController()
{
_categoryService = <inject dependency here>;
}
public ActionResult GetCategory()
{
var category = _categoryService.LoadCategory();
}
}
public class SubCategoryController : Controller
{
private readonly ICategoryService _categoryService;
public SubCategoryController()
{
_categoryService = <inject dependency here>;
}
public ActionResult GetCategory()
{
var category = _categoryService.LoadCategory();
}
}
The guiding principle here should be Separation Of Concerns.
If ControllerA and ControllerB have specific business logic, and adding a CommonActions controller give shared data a good isolated home this is a good practice.
Without a better illustration of your needs though it's difficult to answer.
A slightly better example might be the order application:
InventoryController
EmployeeController
You probably don't want a CommomController with methods like:
GetStoreClosingHours(int storeNumber);
GetTotalSales(int employeeId);
GetEmployeeComps(int employeeId);
IoC and dependency injection might pay off as well depending on the actions. Where any controller could call methods like:
GetLastLogonTime(thisEmployee);
It's really a set of principles designing your application after all, and best practices aren't always super neatly packaged. I'd say most importantly choose something flexible, scalable and then stick with it.

MVC4 Ideal controller coding

I recieved an mvc4 application from my friend in which I will add some functions. but I found that he use controllers with more Than 6000 line of code.
I want to know what's the ideal way to develop MVC4 application.
means to have many controllers with little number of line code in each one. or to have little number of controllers with big number of line code.
I don't think there's a 'right' answer to this, especially without any concrete examples.
Just think about maintainability going forward. A monolithic controller with multiple thousands of lines of code is likely to be much more difficult to understand (and therefore maintain) than a smaller, more targeted controller.
Also I would look carefully at the kind code that goes into your controller. The controller is there to link your models to your views and is not the best place for business logic code; I would personally put any significant business logic into some kind of repository that the controller references.
There definitely isn't a generic solution to this problem, however you can reduce the number of “lines” within a controller by using repositories which will also enable you to make use of the dependency injection pattern.
Dependency injection will also help with unit testing. The repository separates the logic into a separate (replaceable) class.
Searching these terms will provide lots of information (unfortunately far too much to put all the information in a SO question) – but here is some code that will help you in the right direction:
Create an interface to define the repository
public interface IGenericControllerRepository
{
MyModel[] ComplexMethod();
}
Controller class:
public class GenericController : Controller
{
private IGenericControllerRepository repository;
public GenericController() : this(new GenericRepository()) { }
public GenericController(IGenericControllerRepository genericRepository)
{
this.repository = genericRepository;
}
// GET: /controller
public ActionResult Index()
{
MyModel[] m = repository.ComplexMethod();
return View("Index", m);
}
}
Repository Class
public class GenericRepository : IGenericControllerRepository
{
public MyModel[] ComplexMethod()
{
// do work here
}
}
It is hard to judge if you should split your controller into smaller ones as that really depends on the number of methods rather than the number of lines ( for example you could have a few methods with hundreds of lines ) in which case separating them into another controller won’t achieve a desired outcome. Your controllers should be split into “application logical” containers.
I think your friend maybe put the business logic into the controllers. You should put the business logic to other class, folder or projects.

Global Variables in ASP.NET MVC 4

I'm currently building an ASP.Net MVC 4 SAAS application (C#) and am stuck on designing the plans. I mean if a customer picks Plan A they should have access to some things and if they pick Plan B they get access to others and so on.
The Part that I'm stuck on is be best practice of sharing the account's plan with all of the actions. I realize having global variables are bad practice and all but I really don't want to take round trips to the DB to get the plan on every action.
What I'm thinking of doing is something like This SO answer where they just declare a static model and set it at some point and access it later on. In your opinion, is this the best way of doing this? is there a better way?
I think best practice is you should include an IoC in your project and inject a configuration object to your controller.
Example code of a controller:
public class YourController : Controller
{
private IConfigService _configService;
//inject your configuration object here.
public YourController(IConfigService configService){
// A guard clause to ensure we have a config object or there is something wrong
if (configService == null){
throw new ArgumentNullException("configService");
}
_configService = configService;
}
}
You could configure your IoC to specify singleton scope for this configuration object. In case you need to apply this pattern to all your controllers, you could create a base controller class to reuse code.
Your IConfigService
public interface IConfigService
{
string ConfiguredPlan{ get; }
}
Your ConfigService:
public class ConfigService : IConfigService
{
private string _ConfiguredPlan = null;
public string ConfiguredPlan
{
get
{
if (_ConfiguredPlan == null){
//load configured plan from DB
}
return _ConfiguredPlan;
}
}
}
This class is easily extended to include more configurations like connection String, Default timeout,...
We're passing in an interface to our controller class, it's easy for us to mock this object during unit testing.

MVC3 Exposing repository functionality through service

I've been playing around with asp.net MVC3 a bit and have been struggling to decide where to place my business logic. I've settled on using a service layer for now:
public class AnimalsService : IAnimalsService
{
private readonly IAnimalsRepository _animalsRepository;
public AnimalsService(IAnimalsRepository animalsRepository)
{
_animalsRepository = animalsRepository;
}
public IQueryable<Animal> GetFiveLeggedAnimals()
{
...
}
}
The controller would look something like this:
public class AnimalsController : Controller
{
private readonly IAnimalsService _animalsService;
public AnimalsController(IAnimalsService animalsService)
{
_animalsService = animalsService;
}
public ViewResult ListFiveLeggedAnimals()
{
var animals = _animalsService.GetFiveLeggedAnimals();
return View(animals);
}
}
I have basic CRUD logic in the repository (All, Find, UpdateOrInsert, Delete). If I want to use these CRUD methods in my controller:
1) Do I have to create wrapper methods in the service for these respository calls?
2) Would it not make more sense for me to just include the GetFiveLeggedAnimals method and other business logic in the repository?
3) Could I implement the IAnimalsRepository interface in the AnimalsService and then call the base methods (I realise this is possible but I assume its bad practice)?
1) Do I have to create wrapper methods in the service for these respository calls?
Mostly, yes. Typically, you want to offer CRUD for your domain models in the service layer. This way, the controller does not need to work with the repository directly (in fact, it never should). You can add more more sophisticated logic later without having to change external code. For example, consider you wanted to implement a newsfeed. Now every time a five-legged animal is inserted, you want to create a news item and push it to five-legged-animal-fans. Another common example is email notifications.
2) Would it not make more sense for me to just include the GetFiveLeggedAnimals method and other business logic in the repository?
Business logic should be in the Service Layer or in the Domain Model objects themselves, and only there. In fact (see 3), I wouldn't specifically offer an IAnimalRepository at all, if possible.
For instance, in a NoSQL-Environment, the database driver pretty much is a repository. On the other hand, when using a complex ORM mapping and stored procedures (where part of the biz logic is in the DB), you don't really have a choice but offer explicit interfaces that know the stored procedures.
I'd go for a IRepository<T> and use the Query Object pattern, if possible. I think LINQ can also be considered a Query Object / Repository based pattern.
3) Could I implement the IAnimalsRepository interface in the AnimalsService and then call the base methods (I realise this is possible but I assume its bad practice)?
To call the base methods, you'd have to inherit from a concrete implementation, e.g. from ConcreteAnimalsRepository.
Also, if your service implements the IAnimalsRepository interface directly or indirectly, it makes the (unfiltered) CRUD operations available to everyone.
My take: Don't inherit, aggregate. A service layer has a repository, but it isn't a repository itself: The service layer handles all the additional application logic (permissions, notifications) and the repository is a very thin wrapper around the db layer.
As an extreme example, what if deleting something directly was forbidden, and only the service would be allowed to make use of it when inserting a newer revision of sth.? This can be easily built when aggregating.
Repository by definition should be a generic collection-like class that abstracts DB interactions. It would contain typical methods for persistence like Get(object id), Add(T), Remove(T) and possibly implement IQueryable<T>.
The service would look like the following code.
public class AnimalsService : IAnimalsService
{
private readonly IRepository<Animal> _repository;
public AnimalsService(IRepository<Animal> repository)
{
_repository = repository;
}
public IEnumerable<Animal> GetFiveLeggedAnimals()
{
// animal specific business logic
}
}
I think is not good to use simple CRUD operation in the Controller and have a wrapper in the Service class, you should keep all business logic in the service layer, not in controller
for example you want to create a new Animal
in the controller you will have method
look at the example
// not good design
public ActionResult Create(AnimalInput input)
{
Animal animal = new Animal { Name = input.Name}; // set the other propreties
// if you have a CRUD operations in service class you will call
animalService.UpdateOrInsert(animal);
}
// better disign
public ActionResult Create(AnimalInput input)
{
animalService.Create(input.Name);
}
in the service class implementation you should have
follow
public void Create(string name)
{
Animal animal = new Animal { Name = input.Name};
animalRepository.UpdateOrInsert(animal);
}
for the methods like GetAll or GetFiveLeggedAnimals(); you can have wrapper in the service classes I think it's ok . And I want to give you adives allways when you write some code in controller or in Service class keep in mind how you will test this code
and don't forget about SOLID

Categories