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?
Related
I am currently trying to implement my first MVC pet-project. I understand the theory of Model View Controller pattern but when it comes to implementing a real application I am facing several logic issues.
My program is a basic Payment service system (i.e. PayPal).
Here is a typical flow of the program which demonstrates an issue:
Client clicks sign in button in View
A sign in method of Controller is called
This method returns an instance of a current signed in client BACK TO VIEW! (It constructs a client window passing current client as a constructor parameter)
Now when View needs to display some data of that client in client form it just uses that member instance directly.
It seems wrong to me, I think the solution here may be keeping an instance of current logged in user an exclusive private property of controller. But then it may be difficult to display all the data related to that user in View. I think I'll have to crete many 'getter' methods in controller which are going to return strings/strings arrays to populate the UI. It also sounds wrong to me cause I think it's still best to populate the UI with the model data, not some strings received from some controller functions.
What may be the best solution here?
Also, you might be interested in how I implemented MVC pattern in my program in detail.
The model includes Client and Staff entities which inherit the base properties from their superclass BaseUser and the two possible accounts: DebitAccount and CreditAccount which are subclasses of BaseAccount. Then I have a singleton PaymentService which stores all the instances of actors and accounts.
Here is a UML of my model
Then I have a view which is represented by:
EntryForm class — You can register a new client; log in a client or a staff member.
ClientForm
StaffForm — Admin panel
I have sketched/commented what looks like severe design fuckups to me(Sorry for the handwritting).
Here is a UML of my view
And controller
Your help and guidance will be much appreciated!
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.
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).
I have a question related to entity validation. As an example, there is a User which can be registered into a system given email and password. The business rule says that:
email must be valid (must conform to email format) and unique;
password should be between 6 and 20 characters.
My initial thought is to place the validation inside the User.Register(email, password). The main advantage of this approach is that User controls how it is registered by verifying itself the correctness of registration data. The disadvantage is that email uniqueness verification requires calls to UserRepository, so the User might have dependency on its Repository. To solve this issue, email and password validation might be factored out to some kind of BusinessRule objects. So the validation in User.Register() method might look like this:
var emailValidationErrors = _emailRule.Validate(email);
var passwordValidationErrors = _passwordRule.Validate(password);
where _emailRule and _passwordRule might be passed as constructor arguments: User(EmailRule emailRule, PasswordRule passwordRule).
In this casse User is not directly coupled to UserRepository. In this way the rules are explicitly shown in the domain, which make it more expressive.
So the question is: what do you think about this approach? Are there any other solutions?
You could implement a Domain Service that encapsulates this. Typically in DDD you would use a Domain Service when the business logic falls outside of the scope of one individual aggregate; in this case it is the uniqueness check. So, what I'd do is:
public class UserRegistrationService : IUserRegistrationService
{
private readonly IUserRespository _userRepository;
public void Register(string email, string password)
{
if (!_userRepository.DoesEmailExist(email))
throw new Exception("Email already registered");
User user = User.Create(email, password);
_userRepository.Save(user);
}
}
Also, if you are worried about User.Create being called outside of the registration service and therefore escaping the uniqueness check, you could possibly set the User.Create method to internal, meaning the only way to create a user is via the RegistrationService.
There are three validations that you're trying to do in this example:
Email address must be a valid format;
Email address must be unique (i.e., there isn't an existing user who has that email address);
Password must conform to certain length constraints.
1 and 3 above are simple validations that should be able to be done declaratively on the entity properties (using custom attributes and a suitable validation library in .NET for example).
2 above is the tricky bit, and that's where the intrinsic dependency on the User repository exists in my opinion.
The question is: "Does the responsibility of preventing the creation of a User with the same email address as an existing User lie with the User entity?". I believe the answer to that question is "No" ... it "feels" like this responsibility should lie with a higher-level service or entity for which it is natural to have knowledge of the whole set of users.
So, my take is:
Place those validations that sit with the user inside the User entity (strong cohesion);
Place the uniqueness constraint in a DDD service that is specifically responsible for maintaining the invariants of the set of users--it would do this by wrapping the uniqueness check and the persistence of the new User in a transaction.
You can kind of think there are 2 kinds of validation: internal state validation, and context validation. You can perform internal validation from within that entity, and then perform context validation using some service.
Markus,
His approach was not bad, but I just do differently.
In my opinion you respect the OCP, putting validation rules out of the Entity, which was wisely decided. Using these validation rules in the class constructor you are suggesting that the rules are immutable, right?
I would not do this way, just create a method dyad setting the rules as this constructor. For me it was not clear what would happen if the validation rules were violated. I like to throw exceptions to the user interface that handles as more ubiquitous warnings.
Another thing that was not clear to me is the event that triggers this validation. it would be when the entity User was added to the repository or have a method of the entity that would do this? I'll take the second option calling the method isValidAuthentication() throwing that exceptions.
Regarding the dependence of the Entity to the Repository, I venture to say that is wrong. You could even make the entity dependent on him, because the repository is a collection of objects, what's wrong with this? However, at this point seems clear that validation is a Service. So if we put these validations in a Service would eliminate this coupling and apply the OCP again. Do you agree?
A big hug and success!
I'm getting some trouble understanding the MVC concepts.
I'm building a User model, you know? Application_Model_Users. They say that the models should only contain the structure... and the business logic should be put in the controller.
So, consider a function called authenticate($user, $password). This function will return true if the username and password entered is valid or false otherwise. Where should I put this function? In the controller Authentication or in the model Users?
Thank you!
Related to the Model, whenever you need to retrieve data(from DB, Web service, filesystem) or save data, you need a model to do the job. In MVC, a model is not understood as a mapped table, maybe more like a mapper. Zend has some info about this at their site, it could help you understanding mvc a bit more.
When it comes to user authentication, you should certainly implement the authenticate function inside the Users model, I would think you will do a database check against a table or similar.
Just in case you are not already using it, Zend comes with a package for auhtentication: Zend_Auth (http://framework.zend.com/manual/en/zend.auth.html) , it could speed up implementing the security at your application.
Although Model operations often include storage operations (DB, servicer, etc), it is not limited to that. Model, as far as I know, should countain Business logic entities, this is, classes that represent your business entities, like User, Person, Customer, etc. Each class should define its own operation methods, in example, a Person model class should allow you to get a person's name, calculate his/her age according to his/her birth date, etc.
Also, there should be specialized classes for Model storage and retrieval. With these classes you could fetch all your Customers, or only one, using certain conditions, etc, or save a modified Customer class instance (in example, a customer changed his/her address or phone number).
This separates the storage/retrieval operations from Business login operations.
So, according to your question, your model could have a class that allows you to find one user by its user name and password. If the user is found, you could return a Model_User class instance (in example). Then, using the standard Zend_Auth class, or extending it to create your own authentication class, you can use some Login form parameters to perform the user authentication.
Follow the Zend Framework quick start guide, there are the basics about MVC in Zend Framework. Also, there you will find some resources about Zend_Db and related classes, to allow DB interaction. There are also Zend_Db_Table, Zend_Db_Table_Rowset and Zend_Db_Table_Row classes, that you could extend to fit your model storage needs.
I have a personal solution where I extend Zend_Db_Table for my (in example) Model_UserTable class, used to store or query my Model_User entities. And my Model_User class extends Zend_Db_Table_Row.