Which layer should decide to display the next view in Spring MVC? - spring

I am building an application using the Spring MVC framework and there is an architectural issue that I cannot clearly resolve. My problem is that I don't fully understand which part (layer) of the application should be responsible for the control flow (by flow control I mean the display of successive views - pages).
Controllers in Spring MVC are some kind of adapter between the view and the application. Services, on the other hand, are implemented based on business logic.
Suppose we have a controller that supports a certain endpoint:
#GetMapping("/goToPageBasedOnLogic")
public ModelAndView passParametersWithModelAndView() {
ModelAndView modelAndView = null;
// business logic calculates some stuff...
if(fooService.bar()) {
modelAndView = new ModelAndView("viewPageHello");
modelAndView.addObject("message", "hello");
}
else {
modelAndView = new ModelAndView("viewPageGoodbye");
modelAndView.addObject("message", "goodbye");
}
return modelAndView;
}
In the above example, the controller decides which view to display based on the result of the fooService, thus managing the flow of control. If there were many conditions, it could lead to ugly code in controller.
Let's consider the next example:
#GetMapping("/goToPageBasedOnLogic")
public ModelAndView passParametersWithModelAndView() {
ModelAndView modelAndView = null;
session.fooBarResult = fooService.bar(); // logic calculates some stuff and saves in session
State newState = stateMachine.sendEvent(PAGE_FINISHED_JOB);
if(newState == State.PAGE_HELLO) {
modelAndView = new ModelAndView("viewPageHello");
modelAndView.addObject("message", "hello");
}
else {
modelAndView = new ModelAndView("viewPageGoodbye");
modelAndView.addObject("message", "goodbye");
}
return modelAndView;
}
In this example, the decision which view to display is made in terms of services and business logic. The state machine receives the event and then based on the session and the encoded conditions, it makes a decision to select the next view. Then the controller, based on the new state, prepares the correct view and returns it. The controller knows nothing about the control flow logic.
Which solution for deciding whether to display the next view (page) is better? Are there other more interesting solutions?

My rule of thumb are :
The service layer should not aware the existence of the UI . It should not have any knowledge about the ui such that service class is decoupled to the ui and can be easily reused in other contexts (e.g exposed it as API , another new ui in the future etc.) So if you find there are service classes that nees to depend on some classes from spring-mvc or servlet etc., something should go wrong.
The logic related to the ui such as what is the next screen to be display should be placed in the controller layer.
The controller layer should keep thin. Try to push as much as the business logic code to a service layer.
So the controller layer should decide the next view to be displayed. It does not make sense to put it in the service layer. Otherwise the service layer will be coupled to the UI (see my point 1)

Related

Update clients in asp.net core 2.0 using SignalR

I am going through several examples on Asp.net Core WebAPI with SignalR where most of them are demonstrating simple chat application where this is what Hub returns:
return Clients.All.InvokeAsync("Send", message);
And this is how it gets called in Startup.cs
routes.MapHub<Chat>("chat");
The above example is good if message is not be send and updated to all the clients. In my case I have several APIs to be called whenever a data is changed:
Like Bank Transaction is done, I have to update ledger and several other reports at client side. But I don't see any option to pass Json.
Not finding exactly how to do this so that WebAPI gets refreshed everytime a change is there in the database.
As far as I understood, here "chat" is the endpoint which will be called from the frontend.
In this case what will happen to the endpoint I have created so far. Have a look at the below code example:
This api is to be called every time an entry is done:
public async Task<object> GetMarket(string marketshortcode)
{
Markets market = new Markets(marketshortcode);
return market.GetMarket();
}
and this the entry:
[Authorize]
[HttpPost]
public async Task<object> sellCurUser([FromBody] SellCur model)
{
if (model != null)
{
SellCurUser suser = new SellCurUser();
suser.sellcur = model;
my addition code...
}
return ....
}
There are several more endpoints which needs to be called at certain update/creation.
Now the point is how these apis will be changed or even not changed at all.
Do anyone have any example to understand it simply.

ModelAndView Model objects not emptied on re-creation

My question is related to
Spring mvc interceptor addObject
At some point my application needs to know what the previousUrl is that has been visited, so in some occasions the previousUrl is stored in the ModelAndView and 'previous' can be called.
In another case I want to do a redirect and I don't want a previousUrl showing up in the URL bar of my browser. But when I try to initialize a new ModelAndView that old previousUrl object is still there. How is this possible?
The code
if (requestEmployee == null) {
LOGGER.warn("User [" + requestEmployeeName + "] not found.");
model = new ModelAndView(AbstractController.VIEW_REDIRECT_OVERVIEW, null);
return model;
}
should create a new ModelAndView without model objects so why is the previousUrl object still added to the URL as path variable in the browser?
This might depend on what your handler method signature is.
Spring's RequestMappingHandlerAdapter is actually adding model attributes from the returned ModelAndView to the existing model attributes. If you have Model as one of your handler method argument and you are adding some attributes there, they will get merged.

how to achieve MVC in my Zend Framework

currently i am doing a project in zend the way i am doing is working perfectly but i am sure its not the way i am suppose to do i mean i am not following MVC and i want to apply MVC in my zend app.
i am pasting code of one simple module which will describe what i am doing .kindly correct me where i am making faults.
my controller
class ContactsController extends Zend_Controller_Action{
public function contactsAction(){
if(!Zend_Auth::getInstance()->hasIdentity()){
$this->_redirect('login/login');
}
else{
$request = $this->getRequest();
$user = new Zend_Session_Namespace('user');
$phone_service_id = $user->p_id;
$instance = new Contacts();
$select = $instance->Get_Contacts($p_id);
$adapter = new Zend_Paginator_Adapter_DbSelect($select);
$paginator = new Zend_Paginator($adapter);
.
.
//more code
}
plz note this 2 line in my controller
$instance = new Contacts();
$select = $instance->Get_Contacts($pid);
this is my contacts class in models
class Contacts extends Zend_Db_Table{
function Get_Contacts($p_id){
$DB = Zend_Db_Table_Abstract::getDefaultAdapter();
$select = $DB->select()
->from('contact', array('contact_id','contact_first_name','contact_mobile_no','contact_home_no','contact_email','contact_office_no'))
->where('pid = ?', $p_id)
->order('date_created DESC');
return $select;
}
}
after this i simple assign my result to my view.
note please
as its working but there is not private data members in my class,my class is not a blue print.there are no SETTERS AND GETTERS .how can i make my code that best suits MVC and OOP??
The most simple answer: you are already almost MVC. You use a Zend_Controller_Action to grab some data and pass this on to a view layer where you render the html. The only missing part is your model, which is mixed up between the controller and your data gateway (where you implemented a table data gateway pattern, that Zend_Db_Table thing).
I gave a pretty thorough explanation in an answer to another question how I'd properly set up the relations between Controller and Model. I also combined this with a Form, to handle data input, filtering and validation. Then to bundle some common functions, I introduced a Service layer between the Model and Controller.
With the controller, you perform some actions (list all my contacts, create a new contact, modify a contact) and the model is purely containing the data (id, name, phone, address). The service helps to group some functions (findContactByName, findContactById, updateContactWithForm).
If you know how to split Controller, Mode, Form and Service, your controller can become something like this:
class ContactsController extends Zend_Controller_Action
{
public function indexAction ()
{
if (!$this->hasIdentity()) {
$this->_redirect('login/login');
}
$service = new Application_Service_Contacts;
$contacts = $service->getContacts();
$paginator = $service->getPaginator($contacts);
$this->view->paginator = $paginator;
}
protected function hasIdentity ()
{
return Zend_Auth::getInstance->hasIdentity();
}
}
It is your personal taste what you want to do in your controller: I'd say you put as less as possible in your controllers, but you need to keep the control. So: a call to get data happens in the controller, retrieving this data happens somewhere else. Also: a call to convert a dataset into something else happens in the controller, the conversion happens somewhere else.
This way you can change the outcome in controllers extremely fast if you provided enough methods to your service classes to fetch the data. (Note I took the Zend_Auth to another function: if you have other actions, you can use this same function. Also, if you want to change something in your authentication, you have one place where this is located instead of every action in the controller)
keep one thing in mind when u learn new technology so first read thier own documentation. No one can explain better than them. Its hard to understand firstly but when you study it you will usedto and than u will love it like me Zend Offical Site

mvc3 OutputCache RemoveOutputCacheItem RenderAction

I did my research but haven't found any answers.
I'm using Html.RenderAction in a masterpage ( to render page header with links specific to user permissions ). Action is decorated with OutputCache, returns partial control and gets cached as expected.
When the event happens ( let's say permissions are changed ) I want to programmatically invalidate cached partial control.
I'm trying to use RemoveOutputCacheItem method. It takes a path as a parameter. I'm trying to set the path to the action used in Html.RenderAction. That doesn't invalidate the action.
How can I programmatically invalidate the action?
Thanks
The cache for child actions is stored in the OutputCacheAttribute.ChildActionCache property. The problem is that the API generating ids for child actions and storing them in this object is not public (WHY Microsoft??). So if you try to loop through the objects in this collection you will discover that it will also contain the cached value for your child action but you won't be able to identify it unless you reverse engineer the algorithm being used to generate keys which looks something like this (as seen with Reflector):
internal string GetChildActionUniqueId(ActionExecutingContext filterContext)
{
StringBuilder builder = new StringBuilder();
builder.Append("_MvcChildActionCache_");
builder.Append(filterContext.ActionDescriptor.UniqueId);
builder.Append(DescriptorUtil.CreateUniqueId(new object[] { this.VaryByCustom }));
if (!string.IsNullOrEmpty(this.VaryByCustom))
{
string varyByCustomString = filterContext.HttpContext.ApplicationInstance.GetVaryByCustomString(HttpContext.Current, this.VaryByCustom);
builder.Append(varyByCustomString);
}
builder.Append(GetUniqueIdFromActionParameters(filterContext, SplitVaryByParam(this.VaryByParam)));
using (SHA256 sha = SHA256.Create())
{
return Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(builder.ToString())));
}
}
So you could perform the following madness:
public ActionResult Invalidate()
{
OutputCacheAttribute.ChildActionCache = new MemoryCache("NewDefault");
return View();
}
which obviously will invalidate all cached child actions which might not be what you are looking for but I am afraid is the only way other than of course reverse engineering the key generation :-).
#Microsoft, please, I am begging you for ASP.NET MVC 4.0:
introduce the possibility to do donut caching in addition to donut hole caching
introduce the possibility to easily expire the result of a cached controller action (something more MVCish than Response.RemoveOutputCacheItem)
introduce the possibility to easily expire the result of a cached child action
if you do 1. then obviously introduce the possibility to expire the cached donut portion.
You might want to approach this a different way. You could create a custom AuthorizeAttribute -- it would simply allow everyone -- and add override the OnCacheValidation method to incorporate your logic. If the base OnCacheValidation returns HttpValidationStatus.Valid, then make your check to see if the state has changed and if so, return HttpValidationStatus.Invalid instead.
public class PermissionsChangeValidationAttribute : AuthorizeAttribute
{
public override OnAuthorization( AuthorizationContext filterContext )
{
base.OnAuthorization( filterContext );
}
public override HttpValidationStatus OnCacheAuthorization( HttpContextBase httpContext )
{
var status = base.OnCacheAuthorization( httpContext );
if (status == HttpValidationStatus.Valid)
{
... check if the permissions have changed somehow
if (changed)
{
status = HttpValidationStatus.Invalid;
}
}
return status;
}
}
Note that there are ways to pass additional data in the cache validation process if you need to track the previous state, but you'd have to replicate some code in the base class and add your own custom cache validation handler. You can mine some ideas on how to do this from my blog post on creating a custom authorize attribute: http://farm-fresh-code.blogspot.com/2011/03/revisiting-custom-authorization-in.html

Where does input validation belong in an MVC application?

I have a MVC application that receives an input from a form.
This is a login form so the only validation that is necessary is to check whether the input is non-empty.
Right now before I pass it to the model I validate it in the controller.
Is this a best practice or not? Does it belong to the model?
I don't think there's an official best practice limiting validation to any single part of the MVC pattern. For example, your view can (and should) do some up-front validation using Javascript. Your controller should also offer the same types of validation, as well as more business-logic related validation. The model can also offer forms of validation, i.e., setters not allowing null values.
There's an interesting discussion of this at joelonsoftware.
I have been thinking about this for a LONG time and after trying putting validation in both controllers and models.... finally I have come to the conclusion that for many of my applications... validation belongs in the model and not in the controller. Why? Because the same model could in the future be used by various other controller calls or APIs... and then I would have to repeat the validation process over and over again. That would violate DRY and lead to many errors. Plus philosophically its the model which interacts with the database ( or other persistent storage ) and thus is sort of a 'last call for alcohol' place to do this anyway.
So I do my get/post translation in the controller and then send raw data to the model for validation and processing. Of course I am often doing php/mysql web applications and if you are doing other things results may vary. I hope this helps someone.
Validation must be in the Model
Only the model knows the "details" of the business. only the model knows which data is acceptable and which data is not. the controller just knows how to "use" the model.
for example: let's say we need the functionality of registering new users to our system.
The Model:
public function registerUser(User $user){
//pseudo code
//primitive validation
if(!isInt($user->age)){
//log the invalid input error
return "age";
}
if(!isString($user->name)){
//log the invalid input error
return "name";
}
//business logic validation
//our buisnees only accept grown peoples
if($user->age < 18){
//log the error
return "age";
}
//our buisness accepts only users with good physique
if($user->weight > 100){
//log the error
return "weight";
}
//ervery thing is ok ? then insert the user
//data base query (insert into user (,,,) valeues (?,?,?,?))
return true;
}
Now the controller/s job is to "use" the model registerUser() function without the knowledge of how the model is going to do the validation, or even what is considered "valid" or not!
the Controller:
$user = new User();
$user->age = isset($_POST['age']) ? $_POST['age'] : null;
$user->name = isset($_POST['name']) ? $_POST['name'] : null;
$user->age = isset($_POST['weight']) ? $_POST['weight'] : null;
$result = $theModel->registerUser($user);// <- the controller uses the model
if($result === true){
//build the view(page/template) with success message and die
}
$msg = "";
//use the return value from the function or you can check the error logs
switch ($result){
case"age" :
$msg = "Sorry, you must be over 18";
break;
case "name":
$msg = "name field is not correct";
break;
case "weight":
$msg = "Sorry, you must have a good physique";
break;
}
//build the view(page/template) with error messages and die
The class user
class User {
public $age;
public $name;
public $weight;
}
having an architecture like that will "free" the controllers completely from the details of the business logic -which is a good thing-.
Suppose we want to make another form of user registration somewhere else in the website (and we will have another controller allocated for it). now the other controller will use the same method of the model registerUser().
But if we distributed the validation logic between the controller and the model they will not be separated -which is bad and against MVC- meaning that every time you need to make new view and controller to register new user you must use the same old controller AND the model together. Moreover if the business logic is changed (we now accept teenagers in our sports club) you are going only to change the code in the model registerUser() function. the controllers code is still the same.
Its business logic, so no, it doesn't belong in the model.
Within the controller you have the ModelState property to which you can add validation errors to.
See this example on the MSDN.
Assuming your application is structured like:
Model-View-Controller
Service
Persistence
Model
The user input would come to your controller, and you would use services in the service layer to validate it.
Business Logic -> Controller
Data Validation -> Model

Resources