How to have the controller change its behavior depending on the view? - model-view-controller

If from one view a user enters some invalid data, e.g.:
E-mail: bill#apple.com
then i want the controller to:
not place the data into the model
color the text box reddish
not allow the user to save
But it's possible that if the user enters the same invalid data in a different view i want the controller to:
place the data into the model
color the text box reddish
allow the user to save
But it's possible that if the user enters the same invalid data in a different view i want the controller to:
place the data into the model
color the text box bluish
allow the user to save
And it's possible that another view will:
place the data into the model
leave the text box uncolored
allow the user to save
And it's possible that another view will:
auto-correct the data, placing it into the model
color the text-box reddish
allow the user to have
And it's possible for another view to:
auto-correct the data, placing it into the model
update the view with the new data
color the text-box bluish
allow the user to save
[ad infinitum]
Without using n-controllers for n-views, how do i do this?
Update
i was about to ask a new question on stackoverflow, 'How do i have the controller change its behavior depending on the view." But then i realized that i have the exact same question title in use already.
Today's example:
If the entered data is too long for some parts of some of the database tables it will be going into, then perform validation and reject a save.
unless the data is coming from another view. In which case automatically trim certain fields to fit the database rules
unless the data is coming from another view. In which case, require the database to throw it's truncated exception
So many practical problems with MVC that i never see addressed in the books/articles/blogs i've read - it's no wonder i don't use it.

The logic of what has to be done with each view must reside somewhere. I would recommend you empower the view with that information, instead of using multiple controllers, or creating some sort of mapping between view => configuration within a single controller.
I don't know what these views represent in terms of your domain, but it looks like the view seems to be commanding if invalid data can be saved into the model, if auto-correction is permitted, the visual indication for invalid data, etc. Why not empower the view with all that information?
Each of these views would have certain properties.
acceptsInvalidData => boolean, place invalid data to model
requiresAutoCorrection => boolean, auto-correct the data
synchronizeWithModel => boolean, always keep the view in sync with the model
allowsSavingInvalidData => boolean, allow saving of invalid data
invalidDataIndicator => string:color, how to color view for invalid data
Given these 5 properties (maybe missing one or two), the controller can initiate a sequence of actions that will uniquely handle each type of view. The view will have to expose himself or the properties to the controller.

Your examples can be somewhat generalized in the view as suggested, however, some use cases really ask for different controller imho. Also you might try add some logic in models.
Colors are straight view thing, controllers should decide if it is reasonable to save the data in the models, if that data doesn't have some property deciding if it should be saved or not, let it on controllers, possible different ones. Auto-corrections should be in views and helpers.
That is only my opinion.

To summarize the problem:
It seems you want N different behaviors without having N controllers.
You don't want to tightly couple the views and the controllers (no 1<->1 relationship), but the you want the controller to have strong and varied control over the behavior of each view.
Let me state this differently:
It seems you want N different behaviors without having N objects.
You don't want to tightly couple the A objects and B objects (no 1<->1 relationship), but the you want B object to have varied tight control over the behavior of each A object.
Here's how I see these 2 issues:
This isn't a problem of MVC, its a classic software problem: you either need N objects to have N different behaviors, or you need to parameterize the behaviors so that you can distill out commonality (e.g. the approach Anurag suggested) to have less than N separate objects and/or resort to a giant case statement. :-)
This one isn't a problem of MVC, but rather its one of the trade-offs. MVC has us decouple the M, V, and C code to ease future changes (e.g. changing or adding views). But the trade-off isn't free, the components necessarily have to have less knowledge and control of each other. Either you give up on the controller having tight control over the views (no N different kinds of behaviors) or you give on the segregation between the C and V (e.g. allow 1<->1 tightly coupled views-controllers).
Certainly, there has been great success with MVC in decoupling the Ms from the Vs and Cs, but less success in decoupling the Vs and Cs from each other. I think today's responsive interfaces call for coupling views and controllers, or started differently, its not worth the effort and complexity to strongly isolate views and controllers. This modified M(VC) approach has worked much better for me in the real world.

Related

Am I needlessly duplicating models in MVC ASP.NET?

I have just started an MVC project for the first time, and I have encountered a problem that I really wasn't expecting: Too many models.
Not too many different models, but too many which are subtly different, but almost exactly the same.
I have a fairly complex page, with several combo boxes, a list of detail objects and some other extraneous unrelated things that I need to keep track of. More information goes to the view than I get back (which is fine).
I have a domain model, which has remained constant throughout. (1 model)
I have a single use view model, which is the domain model and some extra information wrapped round it. (1 model)
I have a single use form model, which is a copy of the view model with an empty shell copy of the domain model inside it with validation stuff on it. (2 models)
I needed to change the type of a property this afternoon, and I had three separate places to change it in. It seems that I have too many models which are single use. It seems so much work for something that was supposed to be much easier than classic ASP.NET.
My question is: Am I doing it right? Are there supposed to be a multitude of models, or am I missing something obvious?
Not entirely sure what the form model in your example is for - are you using that to limit the post-able fields from the client or using that to map in to your domain?
In my own MVC websites I will have a domain model (which may just be a local domain or come from a remote WCF service) which I map one to one in to my individual ViewModels in order to render on screen and receive the post back. These also contain my validation (be it annotations or fluent etc).
Any property name changes would then be restricted to just the relevant page's ViewModel and the domain.
If you're in a situation where you're replicating properties between domain models then some sort of base view model structure would serve you well for common entities but on the whole it's not something I find to be a massive overhead personally.

Generating Navigation for different user types, MVC, PHP

I have this idea of generating an array of user-links that will depend on user-roles.
The user can be a student or an admin.
What I have in mind is use a foreach loop to generate a list of links that is only available for certain users.
My problem is, I created a helper class called Navigation, but I am so certain that I MUST NOT hard-code the links in there, instead I want that helper class to just read an object sent from somewhere, and then will return the desired navigation array to a page.
Follow up questions, where do you think should i keep the links that will only be available for students, for admins. Should i just keep them in a text-file?
or if it is possible to create a controller that passes an array of links, for example
a method in nav_controller class -> studentLinks(){} that will send an array of links to the helper class, the the helper class will then send it to the view..
Sorry if I'm quite crazy at explaining. Do you have any related resources?
From your description it seems that you are building some education-related system. It would make sense to create implementation in such way, that you can later expand the project. Seems reasonable to expect addition of "lectors" as a role later.
Then again .. I am not sure how extensive your knowledge about MVC design pattern is.
That said, in this situation I would consider two ways to solve this:
View requests current user's status from model layer and, based on the response, requests additional data. Then view uses either admin or user templates and creates the response.
You can either hardcode the specific navigation items in the templates, from which you build the response, or the lit of available navigation items can be a part of the additional information that you requested from model layer.
The downside for this method is, that every time you need, when you need to add another group, you will have to rewrite some (if not all) view classes.
Wrap the structures from model layer in a containment object (the basis of implementation available in this post), which would let you restrict, what data is returned.
When using this approach, the views aways request all the available information from model layer, but some of it will return null, in which case the template would not be applied. To implement this, the list of available navigation items would have to be provided by model layer.
P.S. As you might have noticed from this description, view is not a template and model is not a class.
It really depends on what you're already using and the scale of your project. If you're using a db - stick it there. If you're using xml/json/yaml/whatever - store it in a file with corresponding format. If you have neither - hardcode it. What I mean - avoid using multiple technologies to store data. Also, if the links won't be updated frequently and the users won't be able to customize them I'd hardcode them. There's no point in creating something very complex for the sake of dynamics if the app will be mostly static.
Note that this question doesn't quite fit in stackoverflow. programmers.stackexchange.com would probably be a better fit

Where does language translation fit in the MVC pattern?

I'm building a multi-lingual web application using the MVC pattern as the starting position. The application has a number of forms that users will be interacting with and many of these forms will have fields that do a lookup from a database table, 'Province' for example.
If I need the options in these lists to be displayed in the users' language on the screen, I can see a couple of ways to do this:
In the model. When querying the model, I can provide the language that I desire the results to be returned in. This would allow translations to be used everywhere that data from the model is displayed without changes. However, this also means that the Province model in my example (plus all other application models) now need to know how to do language translations.
In the controller. I can query the model in the controller action as usual and then create a 'Translator' object that I can pass the results into before completing the action. This would imply that each controller action would potentially be duplicating the same translation code, violating the DRY principle.
In the view. Since the presentation of the application is generally expected to exist in the views, and the language of the user doesn't impact the business logic of the system, an argument could be made that language translations belong here. Especially considering that a page could also contain static content that will need to be translated. The downside to this is that it would complicate the views somewhat, especially for the front-end designers who will have to work around the new translation code.
Is there an accepted best-practice for where text translations belong in the MCV pattern for web applications? Does this change at all if I were to be loading the select list options via an AJAX call instead of at page load time?
Thanks for the help!
The best place to handle it is in the view. Your question only references dynamic data from the database, but you also have to handle the static information in your views as well. Best to handle both of those in the same place. A common practice in MVC for handling multiple language is resource strings, separate views for each language, or a combination of both. For information from the database resource strings would work well. You would store a token in the database for the options in the list (that token could be the English translation) and the view would get the appropriate translation from a resource for the specified country/locale. There is a good detailed explanation on this approach in this blog post.
If you need to translate part of your UI, then I would create a helper method that would read a resource file and output a translated string for that resources. E.g.
#Translate("NewUserHeading")
So regarding the UI, it makes sense to handle this in the UI.
If the data that you are going to translate at some point might be shown in a Flash client, or a mobile app, then it should be translated by a server and it should have nothing to do with your MVC application.
Honestly, any interaction with a database should be handled in the model, and that's the only thing handled in the model. Interpreting/organizing that data should be handled in the controller. I guess more information would be need as to where this translation is coming from and how that works to really give a solid answer.
The view will just display strings from a resource file. Including the correct resource file for the locale should do it. In Web applications, it's often a single language JS file defining the UI strings per locale, e.g, strings.en-us.js, strings.pt-br.js and so on.
Some strings do come from the server dynamically, the controller doesn't need to know about it, the model should just grab the localized strings and return is as part of the data request.
So it's either in the view (if it's static) or in the model, (if it's dynamic). Controllers should just translate data from the view to the model and from the model to the view
Another very important thing to consider is WHEN to Translate. Using a once-per-each-translation method like #Translate("NewUserHeading") is fine if you only have 100 translations on your page, but what if you have more?
Because think about it, translation is based upon language choice and that only happens once-per-page or even once-per-session. The way that the Kendo UI people do it in their demo is that way, when the User clicks a new language a new set of server files is loaded. That would mean having something like:
/src/html/en-us/
/src/js/en-us/
/src/html/es/
/src/js/es/
etc..
Check it out at https://demos.telerik.com/kendo-ui/grid/localization
It's a trade off of more work for better performance. The ultimate use-case of translation right now is https://www.jw.org/ with over 900 languages!

MVC: does anyone know a multi view design for MVC?

I have a system that need two representations of the same model,
and for simplicity i want to use one model, and not keep multiple models - because than my system will suffer from translation errors (the models will not be compatible) that might cause the system to be faulty.
Does anyone know a good design practice for that problem?
For example lets say i have UserList
which contains multiple users.
From one hand i want to see the all of my userlists and the users that
each of them contains. From the other
hand i want to know for each user
which are the userlists that he
belongs to.
I can save this information twice (once from the userlist point of view
and once from the user point of
view..) but that doesn't sounds like
a good practice.
Further more, let's say that the userlist has some properties that can
be configured by the system view of
the model.
How do i let the user view of the model know that there was a
configuration change in one of the
properties (without going threw the
userlist and tell each user what was
the change,or whether there was a
change).
How do i maintain these multiple views of the same model - the system view, and the user view in the same time while prevent the duplication of data and information and the ease of query for the model information and changes in it?
Go on http://martinfowler.com/eaaDev/index.html :
The list on the right gives access to many Presentation Patterns, with everything explained.
Alternatively, if you use java/Swing, each model can easily be used by several views, so you just follow the regular flow... :-)

Can any processing be done on the model? [MVC]

I've decided to make a big push towards MVC for all new sites I make. I have a question about whether or not you can have any processing on the model level.
The case that brought up this question is a video site. I have a Video class (model) and one of the things I need to do when a user views the video I need the view to be logged in the database. I'm not sure if I need to add a query in the controller or if I can add a addView method in the Video class.
The basic underlying question for me is what kind of methods am I limited to in the models? Can it be anything or does it have to be only accessor (a.k.a getValue/setValue) methods?
Ruby on Rails has the motto skinny controller, fat model. This doesn't apply to just Rails and should be practiced with any mvc framework.
I think your model is exactly the place to handle this. Now, your model is necessarily composed of just your entity classes. Your model, in my opinion, would include your entities as well as any business logic that you need to implement. Your controller should just be handling I/O for the view, invoking model methods to accomplish the actions invoked by the user via the user interface (view).
Here how I would do this. It should be valid in pretty much any language.
The View would initiate a method call to the controller's OnView() method, then display whatever the controller spits back to it (in a controlled way, of course... I'm thinking your view is going to contain a video player component, so you're going to get a video of some kind back from the controller)
In your controller, have a method OnView() that does 3 things: instantiate the Video object (i.e. uses your data layer to get a model object), call the updateViewCount() method on the Video object, and display the video (by returning the Video object to the View, presumably).
The Video model object contains data representing your video and any houskeeping stuff you need, which includes updateViewCount(). The justification for this is that a Video has a view count (aggregation). If "view count" needs to be a complex object instead of just an integer, so be it. Your data layer that creates Video objects from their primitive representation on disk (database?) will also be responsible for loading and creating the corresponding view count object as part of the creation of the Video.
So, that's my $0.02. You can see that I've created a 4th thing (the first three being Model, View, and Controller) that is the data layer. I don't like Model objects loading and saving themselves because then they have to know about your database. I don't like Controllers doing the loading and saving directly because it will result in duplicated code across Controllers. Thus, a separate data layer that should only be directly accessed by Controllers.
As a final note, here's how I look at views: everything the user does, and everything the user sees, should go through the view. If there's a button on the screen that says "play", it shouldn't directly call a controller method (in many languages, there's no danger of doing this, but some, such as PHP, could potentially allow this). Now, the view's "play" method would just turn around and call the appropriate method on the controller (which in the example is OnView), and do nothing else, but that layer is conceptually important even though it's functionally irrelevant. Likewise, in most situations I'd expect your view to play a video stream, so the data returned by the controller to the view would be a stream in the format the view wants, which might not necessarily be your exact Model object (and adding that extra layer of decoupling may be advisable even if you can use the Video object directly). This means that I might actually make my OnView method take a parameter indicating what video format I want to get back, or perhaps create separate view methods on the controller for each format, etc.
Long winded enough for ya? :D I anticipate a few flames from the Ruby developers, who seem to have a slightly different (though not incompatible) idea of MVC.
Since you can use whatever model code you want with MVC (not just limited to LINQ) the short answer is yes. What should be done in the model is perhaps a better question. To my taste, I would add a ViewCount property (which probably maps to a column in the Video table, unless you are tracking per user in which case it would be in the UserVideo table). Then from the controller you can increment the value of this property.
With MVC, people seem to be struggling with fitting four layers into three.
The MVC paradigm does not properly address the data storage. And that's the "fourth layer". The Model has the the processing; but since it also addresses the data, programmers put SQL in there, too. Wrong. Make a data abstraction layer which is the only place that should talk to back-end storage. MVC should be DMVC.
Keep in mind, there are many variations on MVC and no real "right way" to do things. Ultimately, how you design your classes comes down to personal preference. However, since you asked for design advice, here are my two cents:
Business logic belongs in the controller. Keep it out of the model and view.
Out of the many variations on the MVC pattern, the passive view style seems to be the easiest to test. In the passive view, your classes are designed as follows:
Your controller is "smart: it makes changes to the database, updates the model, and syncronizes the view with the model. Apart from a reference to the model and view, the controller should hold as little stateful information as possible.
The model is "stupid", meaning it only holds the state of the view and no additional business logic. Models should not hold a reference to either the view or controller.
The view is "stupid", meaning it only copies information from the model to the UI, and it invokes event handlers which are handled by the controller. The view should contain no additional business logic. Views should not hold a reference to the controller or model.
If you're an MVC purist, then it would not make sense for the model to update itself or the database since those responsibilities belong to the controller, so it would not be appropriate to create an addView method to your Video class.

Resources