In asp.net mvc, I have been thinking it would be more advantageous to specify parametrized constructors on the view classes in contrast to using ViewData to pass data to the view. In this way the view class could be instantiated in the action and returned from there as an implementation of IView for eventual rendering to the client by the framework.
// An example of an action that returned one of two
// views while passing a data objects from the current
// scope.
IView MyAction(discriminator){
if(discriminator){
return new MyView(SomeVal, SomeVal2)
}else{
return new AnotherView(SomeVal1)
}
}
// An Example Definition for IView
public interface IView{
Render(stream OutputStream);
}
// An Example View Code Behind/Partial Class
public partial class AnotherView{
public AnotherView(string GimmeData){
this.GimmeData = GimmeData
}
// This value could be accessed in the markup like:
// <%=this.GimmeData%>
public string GimmeData {get; set;}
}
I pose this question because I have personally found strongly typed views pointless as there is not 1 or 0 but n number of objects I would like to pass to the view from the action. I also find the ViewData collection a little too "untyped" to mesh really well with the .net strongly typed world.
A parametrize constructor or even public properties on the view would allow the implementer of the view to specify a contract of what data is needed to render the view or can be rendered in the view. This approach would effectively encapsulate the view.
Why would this be a bad design? What advantages are provided with the "viewdata collection"/"strongly typed view" "way" of passing data from the action to the view. Does anyone think this would be a good idea?
update
I have had a change of heart. What I realized is that the view is really just about rendering. A very good design approach is to introduce Presentation Models that represent the user interfaces available in your application.
If something can be shown or not there should be a Boolean in your presentation model. If something can display text there should be a string for that in your presentation model. The presentation model is not anemic because you use it to encapsulate the logic of your UI. For example, if a field is empty then perhaps some other field is grayed out. This is presentation logic and it describes the way that your particular UI works.
Once a presentation model has been introduced the generic page classes work fine, you simply pass the view the correct presentation model. Presentation models allow you to clean up the code in your view as well as provide portability. If one decided to implement in winforms they would seriously only need to bind their UI to the presentation model.
Anyway, I just wanted to follow-up because I no longer agree with my original suggestion. I have accepted Travis's answer because this is essentially what he proposed.
The convention is usually to provide a View Model that encapsulates the data you need in your view. You can then pass this strongly typed object down into your view. So, for example, you might have a BlogDisplay object that looks like this:
public object BlogDisplayPage {
public string PageTitle {get; set;}
public BlogEntry Content {get; set;}
public IList<Comment> Comments {get; set;}
public IList<BlogEntry> RelatedEntries {get; set;}
public IList<BlogEntry> PreviousEntries {get; set;}
}
Excuse the contrivedness of the example, but I think you understand what I'm trying to get at. This way, you can have all of the data associated with the View in one object that can be easily tested and maintained. This also has the advantage of having strongly typed Views using generics.
I prefer this over your suggestion of parameterized constructors because its intent is clear, and the creation and aggregation of that data is going to be in one spot that will probably be easier to maintain.
Related
I have noticed a pattern that in some MVC applications I inherited from a previous developer. When defining the models all the information containing the items for selects and check-boxes are passed in the model.
public class MyModel
{
int MyEntityField1 {get;set;}
string MyEntityField2 {get;set;}
public selectList SelectItens1 {get;set;}
public selectList SelectItens2 {get;set;}
}
...
MyModelInstance.SelectItens1 = new selectlist(...
MyModelInstance.SelectItens2 = new selectlist(...
return view (MyModelInstance);
the information on SelectItens1 and SelectItens2 is one way. What is the advantage of doing as above instead of using the ViewBag to pass Select Items to the view ?
public class MyModel
{
int MyEntityField1 {get;set;}
string MyEntityField2 {get;set;}
}
...
Viewbag.SelectItems1 = new SelectList ( ...
Viewbag.SelectItems2 = new SelectList ( ...
return view (MyModelInstance);
I think it just makes the model fat for no gain whatsoever.
Please advise.
Both approaches are fine, its just a developer preference
First Approach:
There is no harm in having the SelectListItem within your model, Moreover it gives you a clear picture of what the fields must be in your UI, So looking at the model you can confirm that the UI needs to render a dropdown list control for the 2 properties in your example.
Second Approach: If this model is used only in one or minimal pages then Viewbag should be okay. Again this might mean that the developer must have knowledge on what control the UI must render.
So the approaches are purely developers choice and I don't see any major performance improvements of one over the other.
I personally use the first approach as it more clean and keeps the controller code less.
Generally I would agree that models should be kept to the minimum.
However with Microsoft ASPNET MVC pattern you want to keep your controller clean and Microsoft they recommended approach is to fatten your Model and not your controller!
"In general, you should strive for fat models and skinny controllers.
Your controller methods should contain only a few lines of code. If a
controller action gets too fat, then you should consider moving the
logic out to a new class in the Models folder."
https://www.asp.net/mvc/overview/older-versions-1/overview/understanding-models-views-and-controllers-cs
I've a Razor view with lots of graph and other text fields which gets data from controller. I'm thinking of passing a ViewModel from controller to the view which then will parse the relevant content and display it.
Could anyone suggest if above approach is the best practice to solve such, in MVC?
The ViewModel class may look like below:
public class ViewModelDemo
{
public MyChart chart {get;set;}
public string LeftContent {get;set}
public string bottomContent {get;set;}
public ChartLeged legent {get;set}
......
}
public class MyChart
{
public List<int> xAxis {get;set}
public List<int> yAxis {get;set;}
......
}
Reason I'm trying to return ViewModel is that there are may parts of the page which have different data.
Absolutely. A ViewModel is a perfectly acceptable solution to this problem. See Section 12.1.5 of Palermo's excellent MVC in Action book (conveniently in the free sample)
The other option is to create a separate view model type for our views
from the domain model. We’ll create a specialized class, just for
that one view. We can shape that type however we like, and allow the
view to shape our view model however we want. The advantage of a
separated view model is that our views won’t influence the domain
model in any way. For less complex applications, this separation is
not necessary and overcomplicates the design. As complexity of the
views increases, the design of the views has more and more impact on
our domain model, unless the view model and domain model are
separated.
http://www.manning.com/palermo/Samplechapter12.pdf
I think you solution is corret.
Another approach could be to split up the big razor view into smaller partial views, each with a simpler view model. This is usefull for readability, separation of responsability, ecc.
I'm trying to learn ASPNET MVC. I've built a DbModel starting from DB structure so, under Models, I have the .edmx file that can be used to access data.
I've read that it could be good to have ViewModels classes to act between the View and the Model (useful also for single fields formatting) but I don't' understand if this is right and in which way it's better to build them. If they reproduce classes in my model I believe it is a little bit redundant, isn't it? If this is the right way, is there a way to generate automatically ViewModel classes?
A ViewModel in MVC is a model of your view. It is a property bag containing, usually of primitive types. It may seem redundant, but you are protecting yourself from future problems by decoupling your code.
As an example, given a Person object in your domain model:
public class Person
{
public string FirstName {get; set;} // John
public string LastName {get; set;} // Doe
public DateTime Birthdate {get; set;} // 01/01/1965
}
In your view, you may want to represent this in a view as a full name, age and birthday. Your ViewModel would be similar to:
public class PersonViewModel
{
public string FullName {get; set;} // John Doe
public int Age {get; set;} // 46
public int Birthday {get; set;} // January 1
}
Somewhere in your pipeline, you need to convert from domain model to the viewmodel. I have used either projection queries from the persistence layer or object-to-object mapping frameworks, such as AutoMapper.
By structuring your data this way, you can keep logic and formatting rules out of your view markup. By using a framework, such as AutoMapper, you can also standardize string formatting of dates and times, and do convention-based mappings.
Also, I generally advise having one ViewModel per View. If you need to share View/ViewModel structures or apply conditional view information, those should be separated into partial views.
If you are just starting out I would avoid trying to incorporate every best practice you can find into your early applications. It becomes very easy to try and do everything everyone says is the best practice and you lose track of just learning the fundamentals.
View Models are obviously a great way of seperating the presentation layer and the domain layer, but they serve other purposes. If you are just starting out and your applications are not terribly complicated, I would recommend keeping it simple and use your domain classes as your view model where your views are simple. This will allow you to focus more on the application.
Also, by doing this you will come across views where the simple domain model will not cut it and you will find yourself needing a ViewModel. Which will allow you to incorporate the more specific information you need for your view page (such as multiple domain objects).
By practicing without using View Models for everything, you can gain an appreciation for their benefits and decide what works best for you and your code.
A "view model" (model for a view rather than domain model) helps you separate the domain model from what is bound to the page. Is it always necessary? No, but it is useful if you have some common data shapes used on multiple views where the view will also have some additional data. Another good use is removing certain data from certain types of views (your customer should not know your margin, but your management should?). IT is not mandatory.
I'm using the ASP.NET MVC DefaultModelBinder to bind a request to a model class, but only using two of its properties:
namespace MVCApp.Models
{
public class Ticker
{
public string Symbol {get; set;
public string Exchange {get; set;}
}
}
namespace Domain //in another assembly
{
public class Quote
{
public string Symbol {get; set; }
public string Exchange {get; set; }
//lots of other properties we need for output
}
}
public ActionResult ShowQuote(Ticker ticker)
{
var quote = quoteRespository.GetQuoteBy(ticker);
return View(quote);
}
In the view, they can specify the Ticker and Exchange; and that's ModelBound using the DefaultModelBinder. However, each time we need to actually use this Ticker object for something, we need to go to the QuoteRespository and get all of the properties populated for that Ticker.
Question
Should I get rid of the Ticker Object and just create a custom modelbinder to Model-bind to the Quote object; and in the Modelbinder make the respository calls to actually fill out the Quote object? Or should I violate DRY and make the call to that respository in every place we need a quote? Is there a built-in framework way of doing this that I'm missing?
It appears there is a school of thought that says not to make service-layer calls in the Modelbinder.
Update
I created the Ticker class just because we had these two properties in (almost) every single action:
public ActionResult ShowQuote(string symbol, string exchange)
Since they always belong together, I created a small Model class in the UI layer to push them around together (the aforementioned Ticker class). Ticker is not a view model class, and it isn't meant to be.
"Or should I violate DRY and make the call to that respository in every place we need a quote? Is there a built-in framework way of doing this that I'm missing?"
You could always retrieve the quote as part of a Quote controllers OnActionExecuting function.
I wouldn't consider this a DRY violation. Just the cost of doing business. Chances are the way you retrieve quotes won't change and you'll probably have < 10 places were you need this functionality. Depends on how many times you'll need to include that line.
Better to have short and concise action methods than getting all mangled up in base controller and onactionexecuting stuff.
Don't get into model binding against your repository. Did it in a previous project and its the worst and most brittle piece of the application.
I would use AutoMapper to map between view models and domain models.
For me it would be important to see what does Quote contains ? You mention it has other properties for output but does it have other properties and methods which are only relevant to the Domain namespace? If yes then I would like to keep an abstraction between the types used for views and the types in your domain namespace.
So you could end up having a TicketViewModel which contains everything required by your views and as Darin mentioned, use AutoMapper to map TicketViewModel to Quote.
EDIT:
If you really want to ensure DRY, then you can create your own ModelBinder (it's easy, tons of tutorials on Google) and bind your viewmodel from repository in it.
I am working on my model hierarchy and have a few questions.
1) I have a base model for each view type (Add, Edit and View). I put thing in these that are specific to each view type.
2) I then have a model base which the bases above inherit from. This allows me to include things that pertain to ALL views.
3) In my ModelBase, i have a couple of other view models like FeedbackViewModel, ShoppingCartViewModel, etc that I can consume on any view.
4) I have my MasterPage inheriting ModelBase.
Example
Public MustInherit Class ModelBase
Public Property ErrorMessage As String
Public Property InformationMessage As String
Public Property WarningMessage As String
Public Property FeedbackModel As New FeedbackViewModel
End Class
Public MustInherit Class ViewModelBase
Inherits ModelBase
'View Model Specific Stuff
End Class
'Allows contact us form to be submitted.
Public Class ContactUsViewModel
Inherits ViewModelBase
Public Property Name As String
Public Property EmailAddress As String
Public Property Phone As String
Public Property Comments As String
End Class
That is the basic structure of my models, but a few questions:
1) What do I do with a view that requires no model, but I need to pass the FeedabckViewModel, SHoppingCartViewModel, etc.? I was thinking of a GenricViewModel?
2) Do you see any flaws in this design?
Thank You!
Some points:
Why use ErrorMessage, InformationalMessage, WarningMessage, etc. ModelState should be more than enough, and it ties in better with the validation helpers as opposed to you writing the manual stiching in the View.
I think a "base" model to handle different view types is a bit overkill. I think a enum specifying the mode would be better, then you can make decisions accordingly.
Overall, there is nothing really wrong with your design. It's a matter of opinion - for which mine is i usually create a ViewModel per View. Keeps it simple. I use areas extensively so it doesn't get messy. I generally try and create the ViewModels to make the View simple - that's the ultimate goal, not to re-use code across View's, but to keep the View simple. Such as augmenting the model with nested models to make use of partials/templates, as opposed to having a bunch of strings.
1) What do I do with a view that requires no model, but I need to pass the FeedabckViewModel, SHoppingCartViewModel, etc.?
Doesn't that kind of contradict itself? :) If you just need "parts" of a couple of ViewModels, either create another ViewModel, or if it's just a couple of fields, just stick it in the ViewData.