design consideration for asp.net webapi controller - asp.net-web-api

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).

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.

single responsibility principle webapi

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.

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?

MVC paradigm: exposing model and controller from view

I find myself needing to have a View expose its Model and Controller references. Is this the smell of bad design? Or is this considered "safe" practice?
For example: I have a list (composed of a ListView, ListController, and ListModel) and many list items (composed of a ItemView, ItemController, and ItemModel).
When I create the ItemModel, ItemView, and ItemController for each list item, I pass the ItemView instance off to the ListView. But, at some later point, my ListController needs a reference to the corresponding ItemController instance.
So, would it be more proper to pass both the ItemView and the ItemController in to ListView::addItem(), or just pass in ItemView and expose an instance method such as ItemView::getController()?
Or doesn't it matter? Is each approach equally viable? If followed to their logical conclusion, does either tactic result in an anti-pattern?
But, at some later point, my ListController needs a reference to the corresponding ItemController instance
Why? If you're decoupling your classes properly, you shouldn't need this.
Controllers almost always address a functional domain. An example of such a domain might be "Sales" or "Admin." In addition, MVC also supports the use of "Areas," which provides an additional hierarchical level of organization.
Adding references to controllers from other controllers is at cross-purposes with this organizational structure. If you need to combine functionality to make your code more DRY, ordinary refactoring will accomplish that. You can also inherit controllers from a base class containing common functionality.
In the mvc pattern the users request shall be routed to a controller, say invoicecontroller, that has actions.
Lets say the default action, Index, returns a list of invoices; the controller then creates a model with a list of invoice objects, instantiates the correct view and injects the model into the view.
Now it is the views turn to do its magic. It renders the best view it can with the data it has, which may include routes to one or more controllers.
In NO instance should the view (or model) do business logic themselves.
That said, I totally agree with Jakub. Hope that helps.
Considering you are not actually showing any code at all.
In my opinion, you should change your design. A controller is not supposed to communicate with another controller (directly), MVC dictates it: reference.
If you need to invoke a controller action from another controller, consider using delegates or composition. Instead of directly invoking the controller action.

How to implement polymorphism in sproutcore?

I am developing an application that involves a type hierarchy and started by defining the models for each type via inheritance. When it comes to writing the corresponding controllers I am not sure how to approach the whole thing in a clean way. Should I write only one controller for the base type that is able to handle derived models or should there be one controller for each subtype? How should the view-controller bindings be set up to work with the different controllers?
You might want to check out SproutCore's new experimental polymorphism support: http://groups.google.com/group/sproutcore-dev/browse_thread/thread/b63483ab66333d15
Here's some information on defining sub-classes and overriding properties and methods:
http://wiki.sproutcore.com/w/page/12412971/Runtime-Objects.
From my (limited) use of Sproutcore, I've only been able to bind 1 view to 1 controller.
As such, if you are planning to use a single view (e.g. ListView) to display your data, then I think you will only be able to bind that view to 1 controller. This means the 1 base type that is able to handle derived models seems to be the way to go.
Typically you populate the content of ArrayController instances with the results of App.store.find calls. SC.Store#find can take an SC.Query instance, which typically looks like:
MyApp.myController.set('content') = MyApp.store.find(SC.Query.local(MyApp.MyModel));
This should return all instances of MyApp.MyModel, including any instances of MyApp.MyModel's subclasses.
The first argument to SC.Query.local can either be an SC.Record subclass or a string referring to the subclass. So if you've got some intermediary SC.Record subclasses, you might want to try using them there.
Controllers should just be proxies for objects, when dealing with single instances of your model. In other words, ObjectController can proxy anything. Here is what I mean in code:
You have two objects, Person and Student.
App.Person = SC.Object.extend({
// person stuff here
})
App.Student = App.Person.extend({
// student stuff here, you have have all Person things because you are extending person.
})
You then want to define controllers:
App.personController = SC.ObjectController.create({
contentBinding: 'App.path.to.person'
})
App.studentController = SC.ObjectController.create({
contentBinding: 'App.path.to.student'
})
note that you would only bind the controller's content to something if the person/student is a result of a selection, or some other flow where bindings fire. In other words, if you set the person manually (say from a statechart, as the result of an interaction), you would still define the controller but would do
App.personController.set('content', person);
You set up the controller differently depending on whether the Person is a 'top level' object in your app, or some intermediate object that gets selected. Also, you might only need one controller, you would only have a studentController and a personController if you were acting on a person and a student at the same time. Both are just ObjectControllers, and those can proxy anything.
Finally, in your view you would bind the relevant view element to the controller:
...
nameView: SC.LabelView.design({
layout: {/* props */},
valueBinding: SC.Binding.oneWay('App.personController.name')
})
...
note that the oneway binding is if the name is not going to be changed on the view, if the view can change the name, then just do a normal binding. Also note the path here. I am not binding to
'App.personController.content.name'
Since the personController proxies the object, you bind to the
'namespace.controller.property-on-object-controller-proxies'
If you are putting a lot of business logic in your controller, you are doing it wrong. Controllers should just be for proxying objects (at least ObjectControllers should be). Business logic should be on the models themselves, and decision making logic should be in statecharts.

Resources