I'm designing an application trying to follow the REST spec. I'm trying to figure out the best way to design it.
So let's say I'm doing a POST call that so I have a "post" method in my controller and model
// in controller
function post()
{
//call post model here
}
In my post request I need to make the following checks:
-validate fields
-make sure item name is unique for that user
-make sure there are less than 10 items
-etc (there could be more cases)
Now in controller post function I will return a REST message and status code based on whatever happens, which is fine, but I'm curious to know where it's better to keep all those checks.
I can put all the checks in the model and then return some kind of array like:
array('text' => 'return response text/array or whatever here', 'code' => '200/400/etc')
Then just return this in the controller, or is it better to break up those checks into individual functions within the model and then do all the checks in the controller?
// in controller
function post()
{
//if validation fails -> send response
//if name is not unique -> send response
//etc...
}
From a design point of view, if I ever wanted to potentially call the "post" method in the project model from other methods, it would not have an all encompassing function to handle it, however if I do keep it all in one model function it doesn't give me a lot of reusability. If I had to pick sides, chances are I probably wouldn't need to reuse those "check functions" too much anyway, however it also seems weird to have all that response info in the model rather than the controller.
Can anyone please give me some input on this.
I would not create post method inside the model (although having it in the controller is perfectly fine) simply because you just put code/model in such a frame that is not re-usable plus less readable. For instance, instead of post method in the model I would create create method.
There is no one-fits-all way for data validation. I like creating validation classes which have only one method validate for various data types (e.g. username validation class checks if it matches regex and is unique). It's better than copy pasting the validation code to every action (DRY). Where to call this class method? It depends. You can simply call that it in the action. Since the validation code is inside the validation class, it will look alright. You can also create a mapper which takes the request, determines what validations have to be performed and etc. but it might be overkill and is hard to do properly (maintainability wise).
For output again - DRY. It depends on what MVC framework are you using and there might be a good solution for this already. If not, you can create a class for that (yup, I am DRY maniac). You pass response code, array (or string) with response and class nicely wraps everything into JSON, XML format. Advantages: if you change then output format then you need to change only in one place.
Also consider using Remote Facade pattern.
Hopefully, you found something useful in this post.
I would separate the API from the MVC application and use Apify
Related
I was wondering where exactly we should put input validations(imagine an API call send input to apply free times of a user). Is it right to inject validation class in service Layer and call validate method inside service? or it's better to put it in the infrastructure layer or even in Domain model? I just wanted to see a sample code that's implement validation of input for an API in Domain-driven design approach? what if I use CQRS architecture?
I use in my DDD/CQRS project following approach, structure of a project is API layer, Domain layer, Data Access layer, all input data from UI or from User are validated before, command are created and dispatched, to update the state of Domain, and we validate input data two times one is on the UI, (Angular app), and second one in Web API layer, if the data are valid the CQRS command are created and dispatched after that you can have Business logic validation. For validation you can use FastValidator or FluentValidation
UPDATE: Here is the simple example we have API for Create Batch Entity.
[HttpPost]
[Route("create")]
public IHttpActionResult Create([FromBody] BatchEditModel model)
{
var createCommand = model.Map<BatchEditModel, CreateBatchCommand>();
var result = (OperationResult<int>) _commandDispatcher.Dispatch(createCommand);
return Result(result);
}
As you can see as user input data will be BatchEditModel.
so we have BatchEditModelValidator which contains input data validation:
public class BatchEditModelValidator : AbstractValidator<BatchEditModel>
{
public BatchEditModelValidator()
{
RuleFor(x => x.Number).NotEmpty()
.WithMessage(ValidatorMessages.MustBeSpecified);
RuleFor(x => x.ClientId).GreaterThan(0)
.WithMessage(ValidatorMessages.MustBeSpecified);
RuleFor(x => x.EntryAssigneeId).GreaterThan(0)
.WithMessage(ValidatorMessages.MustBeSpecified);
RuleFor(x => x.ReviewAssigneeId).GreaterThan(0)
.WithMessage(ValidatorMessages.MustBeSpecified);
RuleFor(x => x.Description).NotEmpty()
.WithMessage(ValidatorMessages.MustBeSpecified);
}
}
this Validator will be executed before BatchEditModel will be mapped to CreateBatchCommand
and in CreateBatchCommandHandler we have Business logic validation CheckUniqueNumber
public OperationResult Handle(CreateBatchCommand command)
{
var result = new OperationResult<int>();
if (CheckUniqueNumber(result, command.ClientId, command.Number))
{
if (result.IsValid)
{
var batch = _batchFactory.Create(command);
_batchRepository.Add(batch);
_batchRepository.Save();
result.Value = batch.Id;
}
}
return result;
}
My approach is putting validation in the domain model, I validate the functionality of aggregates, entities, value objects, etc.
Then you can validate application services too, and user interface too. But those validations are a plus, a validation enhancement from the user point of view, as validation is faster.
Why this duplication of validations at different layers? Well, because if you just rely on UI or application service validations, it maybe possible that if they don't work well for whatever reason, and you don't validate the domain model, you are executing domain functionality without validating it.
Also, I would point out that not all the validations can be done at UI or at application layer, because you may have to access domain.
Finally, doing CQRS or not is independent on where you decide to put the validations. It's just that if you do CQRS, then validations at application layer are easier to do, as you can put them in decorators that wrap commands and queries.
Hope my explanation helps.
where should put input validation [in Domain Driven Design]?
This is largely unrelated to DDD, but: the closest possible to the input source.
You aren't going to wait until invalid data has crossed 4 layers to discard it.
Input validation precisely means you don't need anything else (e.g. loading other data) to check it, so you might as well do it as soon as you can. Of course, caveats apply, like any validation that can be circumvented must be double checked - client side javascript for instance.
what if I use CQRS architecture?
I wouldn't expect CQRS to change things very much.
Usually, by the time you are invoking a method in a domain entity, your inputs should have already been converted from their domain agnostic form into value objects.
Value objects are expected to be constructed in a valid state, and often include a check of a constraint within the constructor/factory method that produces it. However, in Java and similar languages, the implementation of the constructor usually throws (because constructors don't have any other way of reporting a problem).
Often what clients want instead is a clear understanding of all of the constraints violated by the input data, rather than just the first one. So you may need to pull the constraints out as first class citizens in the model, as predicates that can be checked.
You should validate in your app service before attempting to modify your domain. Validation should be towards the edges of your app (but not in the UI) so invalid or incomplete requests aren't even getting into your domain model.
I consider it two levels of validation because you will validate the request before attempting some behavior on the model then the model should again verify for internal consistency, since it can never be persisted in an invalid state.
It's more a general question, I want someone to point me to the direction I should go.
1) FUNCTION FOR SAME CONTROLLER: I have two methods: Store and Update in the same controller. They both should contain some complex request validation (which I can't do via validator or form request validation because it's too complex). This means for me now using the same code twice in two methods... How can I take this code, create a function and use it in both Store and Update methods just with a single line, like:
do_this_function($data);
2) FUNCTION FOR DIFF. CONTROLLERS: I have another code which I use in many different Contollers. It transliterates Russian letters into Latin ones ('Сергей' = 'Sergey' and so on). How and where should I register this function to be able using it in different Contollers?
transliterate_this($data);
I have read something about helpers. Should I use them? If you an experienced Laravel develper and say so, I will read everything about them. Or, if you advice something else - I'll read about that.:) I just don't want to spend time reading about something useless or "not right way to-do-it".
Appreciate any help!
1) You could create a form request validation or you could just create a private function that would handle the validation and return the result.
2) You can create a helpers.php file, see here, and you put your translation function inside. Then you can call it from anywhere:
In a controller transliterate_this($data);
In a view {{ transliterate_this($data); }}.
You can do complex validation even inside a FromRequest. You can override the getValidatorInstance for example, or any other method from the base class to plug your validation logic on top of the basic validation rules. Else just consider making an external class to handle that complex validation and inject it in your controllers using Laravel's IoC container.
You should create a facade to provide that feature. Then you can easily use it anywhere (and additionally create a helper method for it if that makes you feel better). Something like Transliterate::toLatin($str)
everyone! Thank you all for great answers. But I have discovered that the problem was that I didn't know anything about Object-Oriented Programming.
(Ans I was working in Laravel:)).
After I took an Object Oriented Bootcamp from Laracasts, I started 'seeing' how Laravel actually works and I know can easily create methods inside classes and use them in other classes.
https://laracasts.com/series/object-oriented-bootcamp-in-php
(of course, you can read something else on OOP, but Jeffrey Way has really outstanding explanation talent!)
I have the action contlrSaveText() in controller and the method modelSaveText() in model.
When the data comes from the website to the contlrSaveText(), I check whether the required information is received to save text, i.e. text name, text content etc. Then I call modelSaveText() to actually perform saving text. Do I need to validate data in this method as well or I can expect that controlled already did the job?
A model is only an abstract description, while a controller does the work.
Your model might have a controller on its own that take care of the data and updates the model. But that is technically a controller.
How he works with toward the outside, e.g. another controller that fills data in, is up to you how you define the interface. If your model uses relations or properties that require to be set up by the controller then you have to validate the data before inserting/accepting. But if not, then there is no point in validation and it can be skipped for performance reasons.
If you need to reject invalid data you have to think of a way how to tell the outside what whent wrong so it can respond to the error.
In your example I would go for validation, but that is just my opinion.
i am new in mvc and learning it by going through wrox book. i encounter few thing and i am looking for good clarification.apologized for asking many question in one shot.
1) #Html.DisplayFor & #Html.EditFor
when we use #Html.DisplayFor then what html control render at client side ?
when we use #Html.EditFor then what html control render at client side ?
2) what ModelState.IsValid does ?
i always see ModelState.IsValid return true ? when it actually return false ?
3) how to extract the form submitted value from ModelState ?
i try to do it this way like ModelState["Name"] or ModelState["Name"].ToString() both gives error.
4) what is Remote Validation in mvc ?
5) when we use html helper to render text boxes then how could i attach multiple attribute with it. i tried this way
i tried to display model text like this way but did not
#Html.LabelFor(m => m.Name, new { #id = "name", #class = "", title = "#m.Name" })
can't we specify or assign model text like this way title = "#m.Name" ? if not then how could i assign a model text to title attribute ?
when we need to use # sign when we work with html controls attribute
6) Is it possible to call different type of function/method directly from view
i like to know that
a) if i have few static function or static classes function then can we call it directly from view ?
b) can we can controller method directly from view ?
c) how to call any generic method directly from view?
d) is it possible to call any action method directly from view ?
e) can we can call any model method directly from view ?
which is possible and which is not please explain with reason and sample code
7) regarding data annotation
i want to work with data annotation but i want data annotation should render different js in page for fancy validation message. how to use different jquery validation plugin with data annotation....where we need to change in code.
please answer all my question point wise with example & sample code for better understanding. thanks
when we use #Html.DisplayFor then what html control render at client side ?
That's totally gonna depend on the specific type of the property you are calling the DisplayFor on. The DisplayFor helper will analyze the specific type of the property used in the expression and invoke the corresponding display template. You could also write custom display templates for your view model types. Brad Wilson wrote a nice blog post about templates that I invite you to go through to better familiarize with the basic concepts: http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html
There are a series of posts, make sure you've read them all.
when we use #Html.EditFor then what html control render at client side ?
That's totally gonna depend on the specific type of the property you are calling the EditorFor on. The EditorFor helper will analyze the specific type of the property used in the expression and invoke the corresponding editor template. You could also write custom editor templates for your view model types. Brad Wilson wrote a nice blog post about templates that I invite you to go through to better familiarize with the basic concepts: http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html
There are a series of posts, make sure you've read them all.
i always see ModelState.IsValid return true ? when it actually return false ?
When there are errors added to the ModelState. Could happen if you have used some data annotations on your view model to do validation and the values submitted to the server failed this validation. Normally it's the default model binder that is adding error messages to the ModelState (making ModelState.IsValid return false) when binding the request values to your view model.
i try to do it this way like ModelState["Name"] or ModelState["Name"].ToString() both gives error.
In ASP.NET MVC you use a view model. Your [HttpPost] controller action takes a view model as parameter which is a class specifically designed to meet the purpose of your view logic. Here's an example of how a typical POST action might look like in ASP.NET MVC:
[HttpPost]
public ActionResult SomeAction(MyViewModel model)
{
if (!ModelState.IsValid)
{
// validation on the view model failed => redisplay the view
// so that the user can fix the errors
return View(model);
}
// At this stage you know that the model has passed validation
// It is here that you would typically map the view model to some domain model(s)
// and pass them to your DAL for some processing.
// Finally when this processing completes redirect (Redirect-After-Get pattern)
return RedirectToAction("Success");
}
4) what is Remote Validation in mvc ?
It's a view model property decorated with the [Remote] attribute which in turn emitted some HTML5 data-* attributes on the corresponding input field. In turn the jquery.validate.unobtrusive.js script will use those properties to send an AJAX request to the corresponding controller action to perform validation before the form is actually submitted. Please feel free to read the corresponding documentation: http://msdn.microsoft.com/en-us/library/gg508808(v=vs.98).aspx
a) if i have few static function or static classes function then can
we call it directly from view ?
No of course not. This question doesn't have any sense. The view doesn't know about any server side specific things other than controller actions. So if you want to call something from a view this something in the ASP.NET MVC world is called a controller action. You could of course us AJAX or something to call it.
b) can we can controller method directly from view ?
Yes, of course, if this controller method returns an ActionResult in which case this controller method has a name: A controller action.
c) how to call any generic method directly from view
Absolutely impossible. That would have been a huge security vulnerability if it was possible. You can only invoke controller actions from a view.
e) can we can call any model method directly from view ?
No, for the Christ sake. I repeat: That would have been a huge seurity vulnerability if it was possible. You can only invoke controller actions from a view.
i want to work with data annotation but i want data annotation should
render different js in page for fancy validation message. how to use
different jquery validation plugin with data annotation....where we
need to change in code.
Sorry, I have strictly no idea what you are asking here. ASP.NET MVC client side validation is tightly coupled with the jquery.validate plugin (whose documentation I invite you to read to better understand its functionality: http://jqueryvalidation.org/documentation/). And if this plugin doesn't meet your requirements, after all, ASP.NET MVC view spits HTML, so feel more than free to use some of the gazillions available javascript validation plugins out there that might fit your specific needs.
Hopefully this answers some of your questions. Next time you post a question on StackOverflow make sure that it is very specific and not asking about the philosophy on the entire world (as you did here). Make your homework, read the documentation, and if you have specific issues, post your code, explain the difficulties you encountered with it, and we will be glad to help.
Given that there is file selection widget on the view and controller need to handle event of selecting file, should I rather write controller method:
public void fileSelected(String filePath){
//process filePath
}
or
public void fileSelected(){
String filePath = view.getSelectedFilePath();
//process filePath
}
The first approach seems to introduce less coupling between C and V: C don't know what exactly data does C need while handling given event.
But it requires creating a lot of verbose methods similar to getSelectedFile on V side.
On the other hand, second approach may lead to cluttered controller methods in more complex cases than in example (much more data to pass than just filePath).
From your own experience, which approach do you prefer?
The first approach is my favourite. The only difference is I would rather use an object (like Mario suggested) to pass arguments to the method. This way method's signature will not change when you add or remove some of the arguments. Less coupling is always good :)
One more thing:
If You want to try the second solution I recommend using a ViewFactory to remove view logic from the controller.
The first approach is the way to go;
public void fileSelected(String filePath){
//process filePath
}
The Controller should not care about how the View looks like or how it's implemented. It gets much clearer for the developer as well, when creating/updating the view, to know what an action in the controller wants. Also it makes it easier for method overloading.
Though, I don't know really how String filePath = view.getSelectedFilePath(); would work. Are we talking about parsing the View code/markup?
On the other hand, second approach may lead to cluttered controller methods in more complex cases than in example (much more data to pass than just filePath).
That's when you would create a View Model class (let's say we name it MyViewModel) to store all the properties that you need to send (may it be 10 properties) and then pass that in the action: fileSelected(MyViewModel model). That's how it's intended to be used and what the *ModelBinder's in asp.net mvc are there to help you with.
I think you need to look at this from a step back.
Worry less about how it gets in, and be more concerned with validation and error raising.
Tomorrow, your requirements could change and demand that you source the information via a different architectural approach. You could refactor the setup of [inputs / an input object] into a base controller class - or one of several classes for different controller domains.
If you focus on proper validation, whether within the controller (scrubbing) or outside of it (unit tests), then you perform more thorough decoupling though duck typing.
I would go with the first approach. It's reusable and separates concerns. Even if the method of getting the filePath in the future were to change, it won't affect your method's functionality.