single responsibility principle webapi - asp.net-web-api

I am building a WebAPI service for an application and i am stuck at a cross roads, i understand the SOLID principles and wanting to implement my WebAPI services following these principles, however i have spent the last couple of days struggling with an implementation and would like some advice from the community.
The Single Responsibility principle states that every class should have responsibility over a single part of the functionality provided by the software (see Solid Principles)
I have a two ApiControllers at the moment but there will be many more, and the two currently have Get, Post and Put functionality, but each controller will also require a Search function and my question is should the search methods be moved into a separate ApiController, called SearchController for example.
For example:
I have a user controller
public class UserController : ApiController {
Get - returns a User
Post and Put - Add and update a User
}
and i have a patient controller along the same lines as above, should i have my search methods in each controller of should i have a SearchController, eg.
public class SearchController : ApiController {
SearchUsers() - returns ICollection<User>
SearchPatients() - returns ICollection<Patient>
}
I realise there is no definitive answer and would just like some advice on the best practice

If you go insane with SRP and don't find the proper level of responsibility you end up with a zillion classes doing nothing.
I view the User controller as being responsible for mediating between the User resource api and how that concept is implemented inside of the application. In that case it makes sense to have all api operations in a single controller.
That said we follow Command/Query separation so our controllers delegate to commands or queries to do the actual work. That way the only reason our controller should change is if we want to change the API we provide.

I would introduce search as an action on the respective controller and if you want to track all controllers that have a search action, put an interface on it.
public interface ISearchable
{
IHttpActionResult Search(string q);
}
public class UsersController : ApiController, ISearchable
{
[Route("api/Users/Search")]
[HttpGet]
public IHttpActionResult Search([FromUri] string q)
{
var userRepo = new UserRepo();
//this search method can be as complex as needed
//search initials, middle names, phone numbers, whatever you need.
var results = userRepo.Search(q);
return this.Ok(results);
}
}
Usage:
https://domain.com/api/Users/Search?q=smith
This keeps it very clear to your clients since they don't have to know about a specific SearchController that would basically be a bunch of RPC's. If you think about what search is, it's basically a verb that isn't a standard http verb, so we attach it to the route as an action. We are still acting upon the Users collection similar to a GET or POST against the collection. Since we don't have SEARCH as a valid HTTP method, an action is the next best thing.
In reference to SOLID. This keeps your controller as simple a controller. It's job (IMO) is to control the request and route that to logic. In this case, it took the route, mapped it to a UserRepo and executed the Search method. Searching is not the job of the controller, you have another class doing that heavy lifting. The controller simply handles what logic should be executed given the request. Even the data returned is deferred until later in the pipeline via serializers so SOLID should hold true on the controller.

Related

MVC - Should be there a master View, Model and Controller or should they be implementation-specific?

I'm interested in the concept, not the implementation. Consider a CarBookingRequest scenario where user through an interface requests for booking a car. Let's discuss it under the following constraint and taking only View in perspective by keeping Controller and Model simple:
There is one controller class/code which contains all the functions representing relevant actions
There is one model class/code that deals only with single database with few tables (no other data models)
There can be many interfaces through which a request can be made:
1. Desktop Application
A user clicks a Button that fires the Click event which in turn is pre-programmed to make a call to BookingController with request NewBooking. Something like:
Event OnClick() {
C = New BookingController
C.Request('NewBooking')
}
2. Mobile Application
A user taps a Button that fires the Touch event which in turn is pre-programmed to make a call to the same BookingController with request NewBooking. Something like:
EventListener OnTouch() {
C = New BookingController
C.Request('NewBooking')
}
3. Vending Machine
A user presses a PushButton on the machine that fires the event which is pre-programmed to make a call to the same BookingController with request NewBooking. Something like:
Event OnPress() {
C = New BookingController
C.Request('NewBooking')
}
Assume similar implementation for a Web Interface and Service Interface where the request is made by another system or a scheduled task. Obviously all these implementation are different versions of BookingViews written in very different languages and platform. Now if I knew these implementations beforehand and I am making a Booking MVC, what should be my View, Controller and Model Class like? or how many? and why?
Should I have a "Main" BookingView class that has a function such as:
Function CallController(Command) {
If Command = 'NewBooking' {
Return New BookingController
}
or some good implementation of controller/action registry to fetch appropriate controller
}
and every specific View should in-turn call this function which then will call the BookingController as:
Event OnClick {
C = MainView.CallConroller('NewBooking')
}
Or should each View call the controller separately in its own way?
May be too many questions but I am of the view that my View, Controller and Model should be reusable and every new Interface (Mobile, Machine or Web) should require only their specific handling of the View (events or displays) while the connecting and fetch data code remains untouched.
The core idea of MVC patterns is to separate the three aspects of the application - model, view and controller - from each other.
The way you describe your solution, doesn't seem to adhere to this principle. Let me suggest a method that helps you to achieve good MVC, following these rules. I am describing the generic rules, you can then modify according to the specifics of your application, frameworks etc:
Your controller should not know about the views. This rule helps to separate "view" from control. If you follow this rule, your controller, instead of worrying about types of client, can just return one type of resource (e.g. a JSON resource, in this case a Booking). Then, each client (Web, mobile, machine) has to handle presentation of this resource, whichever way they want. But the important point is that, it is not the concern of controller.
Your Model should not know about the controller. The concern of Model is to implement a car booking. It does not know what is being done with it (like whether a controller wants to access it to then pass it to someone else or so). For example, it may have an interface such as
CarBooking:
constructor();
book();
unbook();
...
It performs the business logic of constructing a request, booking a request or removing a booking. Period.
How do you achieve this, proper separation of Model, View and Controller? Well, one method is to start from within, and then move outward. That is, start from Model, then controller, then view. In reality, you may not do it in this order as you has to consider all of these aspects. But, what I am saying is more in the logical sense.

Input validation in MVC

I need a little help regarding design of MVC .
Most of the tutorials of MVC and CODEIGNITER are doing input validation in controller. Is it a good practice ?Suppose we implement REST or SOAP API then we are going to have different controllers, and for all those controllers I need to replicate my code. Later if any of the validation rule is changed, it will get rippled into all controllers. Shouldn't all the validation should be inside Model instead of Controller ?
One more thing I would like to ask. As I am trying to keep my functions as cohesive as possible, I am getting one to one relation between functions of model and controller. Is it ok or I am doing things wrong ?
Regarding doing input validation in Controller
Ans. Yes, that is the generally accepted practice in most MVCs. However, during the past few years, due to the advent of AJAX frameworks and more adoption of JavaScript, many UI validations get done in UI itself(called client-side validations). These are generally displayed as javascript alert boxes and do not allow user to go ahead unless he fixes these errors. So, I would say Controllers/View helpers are de-facto places where validations are done but you should consider client-side validations wherever feasible. It also saves you trips to the server.
If you expose the same as functionality as SOAP/REST
Ans. Now-a-days you can annotate the same controller methods to make them work as web service endpoints. So, your controllers can service both web-based requests and also SOAP/REST requests.
But one note of caution - your form-beans/backing beans should be very well designed. I have seen code where hibernate model objects are used as form-backing objects. This makes it tricky when you generate a WSDL out of the form-backing objects as hibernate model objects may have many linked entities and one ends up with very complex xml structures in the request/response.
But still, if you design your backing-beans as fine-grained, i.e. not having complex objects, then you should be comfortably placed in using your existing controller/controller methods as web service endpoints for both SOAP/REST.
Regarding the validations being inside Model layer
Ans. You can use this thumb rule to determine where to place which validations -
Business validations should happen in models/services
complex client validations, which are not feasible in client-side, should happen in controllers/view helpers
UI validations (formatting/empty checks) should happen via client-side/javascript validations
Regarding one to one relation between functions of controller and model/service
Ans. Its fine. Just remember to have one controller method talk to its respective model method. And if multiple models are needed to service a request, then that model method should act as an aggregator of information from multiple models i.e. the controller should contact its main model and the main model should contact other models.
Is it a good practice? In my experience yes.
One thing to keep in mind is that any given controller can display an number of different pages. For example, consider a "Dashboard" which could have multiple tasks each of which requires its own page.
A rough pseudo-codeish "Dashboard" controller might look like this:
class Dashboard extends CI_Controller {
public function __construct(){
parent :: __construct();
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->load->model('somemodel_model');
}
public function index(){
//displays a task selection page with links to various tasks
}
public function admins(){
//some kind of interface to display and edit admin level users
}
public function users(){
//CRUD for dashboard users
}
}
With this controller the task selection page is opened with baseurl/dashboard, adminstrator's page with baseurl/dashboard/admins and user CRUD with baseurl/dashboard/users. Because each of these share the same Class, code needed by all/many of these pages (like validation) can be implemented in the constructor and/or with private methods. You probably already know all this. Keep in mind that AJAX responders can also reside in a controller using the same technique.
In regards to keeping the validation rules DRY and easing the work required for changes to rules CI can store sets of rules in a config file for easy reuse in multiple situations. Read about it.

ASP.NET WEB API 2: Role or Claim dependent model validation

I have a unique requirement that I'm not sure how to handle. We are working with an underlying repository that allows for a quite a bit of flexibility with regards to parameters. The Controller services are injected as "service" objects into a "Service" Property for our controller classes and they wrap the calls to entity framework.
eg.
public UserController:ApiController{
public IUserSvc Service {get;set}
public UserController(IUserSvc service){
this.Service=service;
}
}
This part is handled by Autofac and all is well here.
Next, we have the standard GET,POST,PUT,DELETE,PATCH methods in the controller that accept a SINGLE user model. In other words, there is only ONE user model that is ever used, and therein lies the problem.
While the underlying service class just handles the passing of data back and forth, it pushes the requirement of the granular control of validation up the pipe. This isn't abnormal to me.
Given that we have a single API that uses models with validation attributes, we've run into an issue where different apps that call into the api require different types of validation. The model structure is fine. It's just that some properties, depending on "who you are" and what HTTPMethod is sent, either are or are not validated.
ex:
public class User{
public int UserID {get;set}
public string Name {get;set;}
}
Let's take 2 scenarios:
1. Basic User
2. System User
As a basic user, UserID is required for: GET, PUT,PATCH ( and technically delete too but it's not used). It is not required for POST because that would be creating their own user.
As a system user, UserID is NOT required in GET but is required in PUT, PATCH, DELETE.
So I am having a hard time trying to figure out how to do this without making one api for Basic User with their own models and one for System User.
I wanted to keep this high in the pipe so I wasn't doing this in the controller api methods, i.e. Check roles/claims, create/cast/or otherwise map bound model to specific concrete model per role/claim and then run validation and THEN return model binding errors if any. That's a lot of gunk in the method and I would prefer this to be on an attribute of the method or api controller.
Is there any way to do a type of model binding and or model validation based on "who you are"? That could be by role or claim?

design consideration for asp.net webapi controller

I am new to MVC WebAPI with EF4. I am wondering if it's better to split a large controller with multiple GET and/or PUT methods into multiple controllers in order to avoid "Multiple actions were found that match the request" error. I prefer to only use VERB-based route pattern "api/controller/id" as follows.
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
"Api",
"api/{controller}/{id}",
new { id = RouteParameter.Optional }
);
For example, I have two domain objects, Doctor and Patient. A ClinicController has the following actions:
getDoctors()
getPatientCohort(int doctorId)
getPatientPrimaryDr(int patientId)
getPatientDoctors(int patientId, int clinicId)
getPatients()
getPatient(int patientId)
putDoctor(Doctor doctor)
putPatient(Patient patient)
createDoctor(Doctor doctor)
createPatient(Patient patient)
Should I split this controller into DoctorController and PatientController so that each controller only deals with one domain object. Since the Patient Cohort is an association class, should getPatientCohort(int doctorId) be a method of PatientController or DoctorController? Thanks.
In my opinion (and I'm explicitly stating this), you should create separate controllers for each model. It really depends on the purpose of the actions themselves, but I can probably guess the intentions and roughly split it up.
The Put and Create methods should reside in their own controller, because this (again, I assume) has nothing to do with the Clinic. Patients and Doctors just get created or updated (replaced), which is perfectly fine in their own controller. Should a patient or doctor be assigned to a clinic, there should be a separate action inside the Clinic controller which does this.
Any actions which has the Patient model as a basis, and retrieves associated models should also reside in the PatientController; analogous for the Doctor model.
So in essence it boils down to this:
Any model specific actions should be in the controller of that model.
Any model specific actions which retrieve associated models should reside in the controller of the main model.
Any binding actions can reside in either of the controllers which bind the two together.
This is similar to the way the OData framework handles actions and associations, and thus I'm more accustomed to implementing it that way. Hopefully this clears some things up for you (or at least provides some guidelines).

Command Pattern in .NET MVC 3 (removing junk from the controller)

I am trying to implement this Command Pattern on my .NET MVC 3 application, specifically for saving edits to a Thing. I am undecided on how to proceed. Before I get to the actual question, here is the simplified code:
public class ThingController
{
private readonly ICommandHandler<EditThingCommand> handler;
public ThingController(ICommandHandler<EditThingCommand> handler)
{
this.handler = handler;
}
public ActionMethod EditThing(int id)
{
...build EditThingViewModel and return with View...
}
[HttpPost]
public ActionMethod EditThing(int id, EditThingViewModel vm)
{
var command = new EditThingCommand
{
...not sure yet...
};
this.handler.Handle(command);
...redirect somewhere...
}
}
My EditThingViewModel is wholly disconnected from my domain, which consists of POCO classes. It seems like my EditThingCommand should look like this:
public class EditThingCommand
{
Thing ModifiedThing;
}
However, building ModifiedThing would then still be happening in my controller. That's the majority of the work in this case. By the time ModifiedThing is built (and the "old" timestamp applied to it for optimistic concurrency checking), all that's left is for command to call Update on my data context.
Clearly there is value in being able to easily decorate it with other commands, but I'd also like to be able to move the construction of ModifiedThing outside of my controller. (Perhaps this question is really just about that.) EditThingCommand is in my domain and doesn't have a reference to EditThingViewModel, so it can't go there. Does it make sense to have another command in my presentation layer for mapping my viewmodel to my poco entity?
I created an EditThingPostCommand outside of my domain, which takes the EditThingViewModel as a parameter. The EditThingPostCommandHandler is responsible for creating the EditThingCommand and calling its handler.
It works, but I'm not going to assume that's the best answer to my question. Arguably most of what the EditThingPostCommandHandler is doing could be done in a custom AutoMapper configuration, which would still serve the purpose of cleaning up the controller action method.
After several months of using this pattern on other projects, it is apparent to me that the commands on this particular project were simply too general and therefore too complex, requiring too much setup. It would have been better to create, for example, an EditThingTitleCommand and a MoveThingPiecesCommand and so on, and call them from their own ActionMethods.
In other words, when using the command pattern, don't just use the commands as replacements for typical CRUD operations. With more specificity comes more benefit.

Resources