I'm new to MVC / MVP and learning it by creating a Winform application.
I have to some extent created the Models, Presenters and Views... Now where do my validations fit.
I think the initial datatype validation (like only numbers in Age field), should be done by view. Whereas the other validations (like whether age is within 200) should be done by model.
Regarding datatype validation, my view exposes the values as properties
public int? Age
{
get
{
int val;
if (Int32.TryParse(TbxAge.Text, out val))
{
return val;
}
return null;
}
set
{
TbxAge.Text = value;
}
}
I can perform validation seperately, but how do I inform presenter that validation is still pending, when it tries to access the property Age ?. Particularly when the field is optional.
Is it good to throw a validationpending exception, but then the presenter must catch it at every point.
Is my understanding correct, or am I missing something.
Update (for the sake of clarity) : In this simple case where the age field is optional, What should I do when the user typed his name instead of a number. I cant pass null as that would mean the field has been left empty by the user. So how do I inform the presenter that an invalid data has been entered...
Coming from the MVP side (I believe it's more appropriate for WinForms) the answer to your question is debatable. However the key for my understanding was that at anytime you should be able to change your view. That is, I should be able to provide a new WinForms view to display your application or hook it upto a ASP.NET MVC frontend.
Once you realise this, the validation becomes aparant. The application itself (the business logic) should throw exceptions, handle errors and so forth. The UI logic should be dumb. In other words, for a WinForms view you should ensure the field is not empty, or so forth. A lot of the properties for the controls allow this - the properties panel of Visual Studio. Coding validation in the GUI for the likes of throwing exceptions is a big no no. If you were to have validation on both the view and the model you'd be duplicating code - all you require is some simple validation such as controls not being empty for example. Let the actual application itself perform the actual validation.
Imagine if I switched your view to a ASP.NET MVC front end. I would not have said controls, and thus some form of client side scripting would be required. The point I'm making is that the only code you should need to write is for the views - that is do not try to generalise the UI validation across views as it will defeat the purpose of separating your concerns.
Your core application should have all your logic within it. The specalised view logic (WinForms properties, Javascript etc...) should be unique per view. Having properties and interfaces that each view must validate against is wrong in my opinion.
If your "view exposes the values as properties", I suspect that you are missing something. The principal distinction between MVP/MVC and some of the other UI decoupling patterns is that they include a model, which is intended to be the main container for data shared by the view and presenter or controller.
If you are using the model as a data container, the responsibility for validation becomes quite clear. Since only the presenter (or controller) actually does anything besides display the data, it is the one responsible for verifying that the data is in an acceptable state for the operation which it is about to perform.
Addition of visual indicators of data validation problems to an editor form/window during editing is certainly nice to have. However, it should be considered more or less equivalent to view "eye candy", and it should be treated as an add-on to the real validation logic (even if it is based on shared metadata or code). The presenter (or controller) should remain the true authority for data validity, and its validation code should not be hosted in the view.
I believe view validation is only relevant in javascript as the view does not run any code on post, only the controller does.
But I would also not ever trust javascript validation as a malicious user could bypass it or an ignorant user might have JS disabled so repeat any JS validation in serverside code in the controller.
The view might have means to display any errors though .
Related
I'm pretty experienced with Web Forms, but attempting a site in MVC to broaden my skill set. In Web Forms, you could do something like this to execute some JavaScript when the page loads:
ScriptManager.RegisterStartupScript(this, this.GetType(), "unique-script-id", "alert('Data saved.');", true);
What is the equivalent way to do this from a Controller? Should I pass a JavaScript block in the ViewBag, then in my View check for the existence of that script and render it? Or should I abandon the idea of doing this from my controllers and instead use AJAX from the client side to post the form to a Web API, and then based on the HTTP status code display the appropriate message?
public ActionResult Submit(ArticleModel article)
{
//save model to database
//I think here I want to do the MVC equivalent of registering a startup script providing a success message.
return RedirectToAction("Index");
}
What is the equivalent way to do this from a Controller?
You don't. Not from the controller anyway.
JavaScript is part of the view. The controller provides a model to the view, nothing more. It shouldn't be coupled to the view in any way. Your JavaScript would be invoked within the view.
If you're looking to conditionally include JavaScript in the view, you can wrap it in a conditional check on a model property:
#if(Model.SomeBooleanProperty)
{
<script type="text/javascript">
// your script here
</script>
}
Then the model would be logically determining whether or not that functionality is invoked. The view is simply binding to the properties on the model.
Edit: Another approach, structurally similar but without adding a property to a model, is to use something like ViewBag. In your controller you'd set the value:
ViewBag.SomeBooleanProperty = true;
Then you'd check it in the view:
#if(ViewBag.SomeBooleanProperty)
{
<script type="text/javascript">
// your script here
</script>
}
Keep in mind, however, that this introduces some coupling between the controller and the view. The view now assumes that something other than the model has been set. It then becomes the responsibility of any code which returns that view to explicitly set that value. Models are a way to enforce this more explicitly, eliminating the coupling.
Additionally, you seem to be misunderstanding something in one of your comments:
This information I'm talking about isn't data, so it doesn't belong in the model.
Models don't contain just data. Models contain the core business logic of your application. Just data results in "anemic models."
Learning the "MVC Way" of doing things will help you in the long run to develop more modular, testable applications.
In your example, you are wrapping your functionality around multiple components. You are wanting your controller to tell your view to perform some action. This is the practice that MVC frameworks in general strive to deviate from.
MVC frameworks, including ASP.NET MVC, adhere to the principal of least responsibility.
The job of your controller is to Control your application flow. It isn't even really responsible for program logic, you will likely have Services to handle things like Database management, complex calculation, etc. Your controller shouldn't really care about the view, or how the view displays information; it should only care how to make a view and tell the view to do it's thing. Typically, controllers can be slimmed down to less than 10 lines of code in all but extremely complex scenarios.
By the same token, the view shouldn't care how the controller works, or the services that the controller responds to. Views should never be told how to display information, errors, etc, only given data or a status to work with.
Keeping this separation of concerns means a few things. First, it ensures that you can make changes to one part of the application without it having a major impact on another portion. Secondly, you can test if the controller is working without ever having a view, and you can render the view with sample information without a functional controller. This makes your development team much more efficient.
Bottom line, you should keep the idea of Separation of Concerns in the front of your mind when working with MVC, and if you are ever thinking that you need to have your controller tell the view to show something, you are probably going the wrong direction with your overall architecture.
Hmm..
You can directly use javaScript in CSHTML and if you want to show your script under condition than you can bind it inside if condition just pass a signal from controller to show your script only
true or false
EXAMPLE
set a boolean value from controller and keep in ViewBag
ViewBag.isSubmit= true;
and then check condition in your view
#if ((bool)ViewBag.isSubmit==true)
{
<script>
alert('Submit Successfully');
</script>
}
but remember to insert # before if because this is CSHTML and uses Razor syntax.
I have a view model which should check that label of a new entity is unique (not in DB yet).
At the moment I've done it in the view model class:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (PowerOrDuty != null)
{
if (PowerOrDuty.Identifier == null)
{
using (var db = new PowersAndDutiesContext())
{
var existingLabels = db.PowersAndDuties.Select(pod => pod.Label);
if (existingLabels.Contains(PowerOrDuty.Label))
{
yield return new ValidationResult("Cannot create a new power or duty because another power or duty with this label already exists");
}
}
}
......
Please note that this is a small internal app with small DB and my time is limited, so the code is not perfect.
I feel that DB access from view models might be a bad practice. Should view model have direct DB access? Should it be able to call a repository to get the available labels? Should validation requiring DB access be done in a controller instead?
Should view model have direct DB access?
I think this should be avoided at all cost
Should it be able to call a repository to get the available labels ?
This is not the concern of a ViewModel.
This would introduce some complexity in the testing of your ViewModel (which should almost need none) I guess it is a sign of trouble coming.
Should validation requiring DB access be done in a controller instead ?
Maybe, if by "DB" you mean "Repository". But what comes to mind is a separate custom validation class that you will be able to (un)plug, test, and reuse, in another controller for ajax validation, etc
I think that accessing DB from VM is not wrong... AFAIK it is not breaking MVC concept (since it is a presentation layer concept). Said that, it could be better if you have the Validate method provided by a Service Layer.
But all the logic related to the content of the ViewModel, it is better kept in the VM than in the Controller. Cleaner controllers is better.
Your view model should not be tied to your context, it only cares about displaying data and validating it after a submit. You can perform validation like a required field or a value in range, but you can't know if a label already exists in your database.
You can't also fetch a list of "forbidden labels" before displaying your form, in order to test your label afterwards, because that list could have changed during this time (another user updating you database).
In my opinion, validation at model level should focus on what it can validate without knowledge of the data source, and let your database notify you errors like submitting a duplicate value in a field which has an unique constraint. You'll catch exceptions coming from your database for errors like those, and manage them accordingly.
Anyway, i think there's no straightforward answer for a problem like this.
I personally like the ViewModels to be anemic -- simply classes with properties.
For custom server-side validation like this, I prefer it go either in a service, with the consumption of the service in your controller, or even behind a custom validator.
With a custom validator, you could even (optionally) execute the validation remotely. That gets a little more complex though, but I've done it using a generic remote validator that consumes an Ajax action method to perform the validation, and wire that up through both the client validator and remote validator (to ensure you have your validation logic in a single method).
But which ever way you go, I think it is more common -- and in my opinion, more clean -- to keep all logic out of your ViewModel. Even in a simple app, your ViewModel should be dumb to your database context. Ideally, only services (not necessarily web services, but just an abstraction layer) are aware of your database context.
This, to me, should be done regardless of the size of application. I think the effort and complexity (it only adds another assembly to your solution) is worth the abstraction you get. Down the road, if you happen to decide to consume your services from another application, or if you decide to swap out your database context, it's much easier with that abstraction in place.
Say my phone number is stored in the database as a 10-digit string:
0000000000
And I want to format this phone number when presenting it to the user as:
(000) 000-0000
And I have an extension method in a utility assembly that handles this formatting:
static string ToPhoneNumber(this string value)
{
return Regex.Replace(value, #"(\d{3})(\d{3})(\d{4})", "($1) $2-$3");
}
My question is, at what point do I apply this conversion?
1) In the view:
#Model.PhoneNumber.ToPhoneNumber()
2) In the view model:
public string FormattedPhoneNumber
{
get
{
return this.PhoneNumber.ToPhoneNumber()
}
}
3) In the controller:
userModel.FormattedPhoneNumber = userModel.PhoneNumber.ToPhoneNumber()
4) In the domain model (same implementation as #2)
5) In the service (same implementation as #3)
Also, does the answer depend whether it's a global formatting need (like phone number) vs. an isolated one-time formatting on a single view?
I would give my thoughts, but don't want to influence any answers.
I personally like to keep things in my ViewModel because what you end up with is strange looking code in your view if you don't. Let's take your example.
Razor View:
#using MyNamespace.Models.Extensions
#model MyNamespace.Models.ViewModels.IndexViewModel
#if (string.IsNullOrWhiteSpace(Model.PhoneNumber) {
<div> #Model.PhoneNumber.ToPhoneNumber() </div>
}
Versus the alternative:
Razor View:
#model MyNamespace.Models.ViewModels.IndexViewModel
#Model.FormattedPhoneNumber
ViewModel :
public string FormattedPhoneNumber {
get {
return PhoneNumber.IsEmpty()
? "Not Available"
: PhoneNumber.ToPhoneNumber();
}
}
You could definitely improve my code, but the point is that it keeps your views simpler and lest cluttered with branching logic.
Also, I never claimed to be a saint, so I don't always follow my own advice, but I should. Do as I say, not as I do :)
I think it is view responsibility to decide how to display data. Because only the view knows what is available for presentation. On the other hand it is probably easier to do it in controller. And controller would know about locale of the user. Over all I think it makes very little difference.
First off, with architectural patterns in general, and especially those dealing with "separation of concerns", the final arbiter is always "what is the best approach in my scenario" - I strongly believe that dogmatic adherence to a set of rules without considering your own plans and needs is a horrible practice. Not to mention the fact there is no clear consensus here: depending on your variety of XYZ (MVC, MVP, MVVM) you'll find opposing thoughts on what goes where all over the internets.
That said, my quick-twitch answer to the question is "Use your judgement".
Arguments for "in the view":
it deals with presentation, therefore it is the views responsibility
Arguments for "in the view model":
generally, the role of the view model is to provide "ready to data bind" representations of the model - hence, transforming model data into a form directly consumable by the view is the responsibility of the view model
Arguments for the model:
this could be an excessively common representation for the model data; therefore, following DRY, the model will assume responsibility for this representation
Arguments for the controller:
... Ok, can't think of a reasonable one here. Controllers typically respond to actions, so it's a stretch to justify it belonging here.
The point I'm trying to make is that so long as a single point of your system accepts and takes on the responsibility and that responsibility is handled solely by that component/layer/class, you've accomplished the primary goal, which is to prevent dilution/repetition/low cohesion.
My personal opinion, fwiw, would probably fall on the view or view model. If this were WPF I'd almost certainly say the view (via the format providers available to wpf data binding). In the web world, I'd probably lean towards the view, although a strong argument for the model exists - say you now want to expose this data via a REST/JSON/etc service: you can easily handle this change (assuming you want to return the formatted data, that is)
TL/DR: It really depends; follow common sense and use your judgement. Just keeping all the related logic in a single place is the important part, and question any dogmatic/commandment-style "Thou Shalt" statements.
It depends on a few things your definition of ViewModel, are you following a (self-coined) MVCVM* approach, where you'd have a ViewModel specific to your view in addition to your domain models?
If so, the VM could certainly contain the formatting logic, that is the whole point of having this View Model in the first place, to Model the View. So Option 2.
That said, the reasoning behind this is that formatting yourself would begin to the DRY principle if you were formatting like this:
#Regex.Replace(Model.PhoneNumber, #"(\d{3})(\d{3})(\d{4})", "($1) $2-$3");
Since you've got an extension method, it's not that much of a problem to call the formatter in your view at all, but I'd still prefer to do it in the dedicated VM.
If your VM is really just the domain model that contains the raw data (see this, pattern 1) then it should definitely be in your View, so Option 1. Just a note, that if you're using this pattern I'd suggest against it as it's making your view strongly coupled against a low-level object, you're better abstracting this out into what you need ensuring that your couplings between Domain Model + View Model are actually strong (ie. compiled at compile time, not runtime!).
Above all - This should certainly not go into your domain model.
* Model, View, Controller, ViewModel. Where the ViewModel contains the data that is to be consumed in your View, in the format of which it requires.
I would place this in the viewmodel and not in the view. The view is intended to just present the data/information to the end-user. Keeping up the separation of concerns makes sure every object is as independent as possible. If you pass the formatted numbers to the view, the view has no concerns about what is to be displayed, just display the formatted numbers.
I would argue that this is modeling, not formatting. If the receiving application needs to re-format the order, spacing or capitalization of these fields it must first split the single field into several separate fields.
This should be the responsibility of the Services layer. We are talking schema, not format. The application requires that the fields be split as part of its data contract. Where this split happens should be in the Application Services layer that your app consumes.
The services layer should try to add metadata to the information through schema.
For example, if I receive a phone number from a data contract like this:
1234567890
The requriements for presentation are as follows:
(123) 456 – 7890
The services tier should be breaking the phone number apart into its elements
<PhoneNumber>
<CountryCode>1</CountryCode>
<Area>123</Area>
<Prefix>456</Prefix>
<LineNumber>7890</LineNumber>
</PhoneNumber>
Option 1 is the best, followed by 2.
In the controller, you should actually remove the formatting to send it to the service layer, so neither the domain model nor the service model are aware of the formatting.
I am trying to break some of my old habits of writing bad code. One of them is where to put validation code. I don't think validation should be in the presentation layer. Or there could be some validation there?
Here is an example of what I used to do
protected void SaveBtn_Click(object sender, EventArgs e)
{
Item itm = new Item();
itm.Name = txtName.Text;
if(String.IsNullOrEmpty(itm.Name))
{
//reject
}
else
{
ItemBLL.Save(itm); //no more validation here
}
}
OR
public class ItemBLL
{
public static int Save(Item itm)
{
//no more validation in .aspx.vb
if(String.IsNullOrEmpty(itm.Name))
{
//reject
}
else
{
//Save item
}
}
}
I have been using the first approach and I am thinking of switching to the second but I can't anticipate what the problem would be or the advantage of one over the other. Please advice is appreciated even for better approach
UPDATE:
I agree that for the sake of the users simple validation (e.g. common mistakes) should be done in presentation (.aspx) (using javascript, jQuery).
Some business logic validation should also reside in the BLL for portability and reusability.
Does this mean we can skip validation in codebehind (.aspx.vb or .aspx.cs)?
Both is best, but the BLL is a must. Today your business class is only used by the one interface - the browser, but tomorrow maybe you may want a web service to also use that class. Then you will need all of the business rules to be in the class, not the web page. But a lot of rules you will want to test client-side in Javascript to provide a responsive interface. The example you give where the Name cannot be empty is a classic for testing in Javascript and not allowing the "Save" button to be enabled until the Name has a value. However, lets say the Name field has to be unique - this may not be something you want to validate client-side, and are willing to wait until it gets to the server.
Depends on what you mean by 'validation' - it's perfectly legitimate (and preferable, IMO) to do simple data validation in the presentation layer, especially if it saves the wait time of a round-trip postback to the server. That's kind of the whole point of the Unobtrusive Validation library in jQuery, for instance - prevent the user from submitting data we know is not valid (empty required fields, letters where only numbers are valid, etc.).
I would also say that it isn't such a bad idea to have a sort-of "checkpoint" mentality to validation: once you cross a boundary between layers (especially if you're mapping to different data classes at any point), make sure the data is kosher for what that layer intends to do with it.
One advantage to having each layer validate in some fashion is that if you reuse that layer again somewhere, the validation logic comes along with it, rather than needing to be reimplemented again in the new project.
Of course, this is just my opinion (from my experience). I'd like to hear what more experienced developers have to say...
I have a partial view that loops through its Model (a list of things) to show the thing.Name and three integer values that are counts of related entities.
First of all, I tried putting: (pseudo-razor)
foreach(thing in Model){
#thing.Name :
#thing.related.entities.where(condition1).Count()
#thing.related.entities.where(condition2).Count()
#thing.related.entities.where(condition3).Count()
}
But its really slow... so I created a function in the ThingRepository that does same queries faster, something like this (pseudo-code)
function GetCountofRelatedEntities(relatedID,condition){
return db.entities.where(relatedID==relatedID && condition).count()
}
and its much faster, so I want to call it. I think I should call it from the controller, but then I need a ViewModel to keep a (thing, int, int, int) collection as the model, or I can use the ViewBag extremely to pass the results to the view, but, and here is the question:
Why not simply use the repository from the view? whats wrong with this code in the view? (pseudo-razor)
#repo=new ThingRepository()
foreach(thing in Model){
#thing.Name :
#repo.GetCountofRelatedEntities(thing.relatedID,condition1)
#repo.GetCountofRelatedEntities(thing.relatedID,condition1)
#repo.GetCountofRelatedEntities(thing.relatedID,condition1)
}
Could you tell me why I shouldn't instantiate the repository inside a View? Or I can do it?
Why not simply use the repository from the view?
Because you are violating the MVC design pattern. A view's responsibility is not to fetch data. It is to display data that it is being passed to it from the controller under the form a view model. And it's as simple as that.
You could call repositories or whatever you like in your views but just don't tag your questions with asp.net-mvc anymore because you are no longer doing any MVC. I mean you could do whatever you like - you could even write SQL queries in your view if you want.
But the whole point of the MVC design pattern is to separate the data retrieval logic from the presentation logic.
One purpose of the MVC pattern is to provide a structure that fits a wide range of common programming situations. To simplify:
Model: Describes the shape of your application, i.e. the parts of your software specific to your business.
View: Display the data to the user and transmit user events to the server.
Controller: Acts as a middleman between the view and the model.
What you're proposing "works," in the sense that it gets the data on the page where you want it. In the short term, it appears to be saving you time and effort, as you don't have to bother with controllers, viewbags, etc.
However, you are breaking the MVC structure in a way that you will probably regret later on. For example, say in a few weeks your boss comes to you and says, "Hey, you know that page you added to display that list of entities? We need to do some filtering and sorting on it. And I need it yesterday."
Now you're faced with a choice: Do I add this filtering logic to my view page and meet the deadline, or do I take the time to move the data access code to a controller and rework my view, at the risk of missing the deadline and breaking what's already working?
You'll probably take the easy way out and add the logic to the view, and now you've got a growing mess on your hands. We've been down this road with VB6 and Webforms apps with 6,000-line codebehind files. Trust me--you don't want to go there.
Another problem is that the MVC structure is well understood by the programming community. If someone else comes along and tries to work on your code, you're making it harder for them by deviating from the conventional approach.
The MVC structure is time tested and sound. Until you fully understand its purpose and the benefits it provides, try to follow it closely. It's not a good idea to break the rules until you have a firm grasp on them.
My main objection would be the separation of concerns. Once you start hitting your DB from your view, your "view" really isn't just a view anymore. It's really handy to have a clean separation between your data access and your view.
Why is this separation of concerns important? It makes it easier to work with systems that are composed with these clean separations. When you need to adjust what data is retrieved, you'll never need to fuss with the view. So long as the view gets the right value, it will display it correctly. Likewise, if you want to change how values are displayed, you can modify the view without any chance of borking the data.
The thing is that you should not have any logic in your View because this is not the MVC approach.
MVC is Seperation of concern.
So you should create your ViewModel wich contains ALL the data your View needs.