Need help to generate view where data comes from many models - model-view-controller

I need some suggestions about how to generates a view where data comes from 3/4 models.
I have attached an image where data is coming from 3 models. I have done that in web form using 3 different gridviews and binding different data sources.
But now I have to do the same in MVC 3 and finding it difficult.
I would really appreciate if anyone can give me some guide line about how to generate such view.

I would define a Model containing 3 Properties
public class CompositeModel
{
public MenuModel Menu {get; set;}
public OrderModel Order {get; set;}
public RestaurantModel Restaurant {get; set;}
}
And pass this model to the view.

You could, pass all your models through as properties of the 'Model' object, and then use partial views to render each section, passing through the particular model they use.
#Html.Partial("ViewName", this.Model.SubModel)
Or, use child actions, and have a separate action method for bit of the page. i.e. add this to your parent view:
#Html.Action("ActionName", "ViewName")
The advantage with the latter is you can using caching policies ([OutputCache] attribute on your action) for parts of your page which are more static that other parts.

You can use Tuple() to return more than one recordsets (models) to a view. Tuple() is a new feature in C# 4.0. View this article about Tuple().
http://www.abhisheksur.com/2010/11/working-with-tuple-in-c-40.html

You can use partialViews, and render them on page, or you can pass as much data as you want through Viewbag. Example:
ViewBag.Model1 = yourModel1;
ViewBag.SomeData = someOtherData;.....
And then in view you yust use it:
#ViewBag.Model1
You could even get data through ajax calls, and by the looks of your sample I would take that approach and use jquery templates to render view.

Related

Bind customizable views to dynamic models

We are working on an ASP.NET MVC 3 using ext.net and EF 4.
Data model is mapped using EF4.
Views’ content is rendered from customizable XML files.
Example: Within one view, I can display fields that are related to both objects “customer” and “order”, so from this view I can modify the customer data and also add a new order.
How can we bind the view to the custom model that contains 2 objects (customer and order)? Using non strongly typed views will require a source code that will check all different possibilities (If I remove/add a field to display from the XML file, object constructor and CRUD operations parameters will change also.
We are wondering how can we handle such dynamic application?
Is this a common issue that was raised before? Or is there any solution to use dynamic views bound to custom model (object, xml, etc.)?
Your help is very appreciated, please enlighten me.
Based on what you replied to my comment, I can defenitely say that you need strongly typed views. That said, you decide what the model of your view is. If your view needs to manage users and orders at the same time, you can make a class like this:
public class MyCustomViewData
{
public IEnumerable<User> Users {get;set;}
public IEnumerable<Order> Orders {get;set;}
}
and then strongly type your view to MyCustomViewData and you're set. My example is oversimplified but I think you can get the point.
Unless I'm missing something, I believe the normal way round this would be to strongly type your view to say 'user' and then on the user object, define a property which is a collection of 'orders'.

Alternative for ViewBag in MVC3

I have a MVC3 web application where I need to implement a database search functionality. I am creating a ViewModel class for my search form so that I get the search parameters from View to controller. I can successfully get all my search parameters (which includes search query and check boxes if user wants to narrow search) in my controller class and retrieve data from database using repository pattern
var searchResult = _repository.GetItems(searchParms, chkbox1, chkbox2, ..., chkbox10)
After this, I am passing my searchResult to pagination helper like
var paginatedSearchResult = new PaginatedList<Items>(searchResult, page ?? 0, pageSize);
I am displaying the retrieved data in my view page
return View(paginatedSearchResult)
The problem, I am facing is, besides the data from the database, I also need to show the search query string and topic (for which checkbox was used) in my view page so that user can see what they searched for. I did not find any proper solution to this and had to use ViewBag. And now my Controller page looks ugly with more than 10 ViewBag. I know there must some good solution to this but I am not able to find it.Any suggestions will be highly appreciated.
Thanks,
ACS
Direct answer to question's title is - alternative for viewbag in mvc is strongly typed ViewModel classes. Take a look at Create View Models
You are soooo close already.
You have a ViewModel you are using for the search - so you obviously know how to create a view model. Just create a new ViewModel that has your current ViewModel as a property and the database search viewmodel as a property.
public class SearchViewModel
{
public YourExistingSearchOptionsViewModel SearchViewModel {get;set}
public PaginatedList SearchResults {get;set;}
}
obviously that is very rough - but hopefully you get the idea there.
I think you might be searching for the strongly typed "ViewData" property

ASP.NET MVC 3: unobtrusive JavaScript validation

There are a lot of examples on how to "create your own model". Mark them with DataAnnotations. Scott Guthrie explains how to validate your model when using an ORM. What I don't find is when your model is actually coming in from an external DLL. How do you validate it?
Example:
/* Class coming in from an third-party DLL file. */
public class Person
{
public string Name{get;set;}
public int Age {get;set;}
}
The solution I am thinking of: Inherit the external class and then apply [MetadataType] to the inherited class.
[Metadata(typeof(Person2_Validation))]
public class Person2:Person{}
public class Person2_Validation
{
[Required,Stringlength(50,ErrorMessage="Name required"]
public string Name{get;set;}
[RegularExpression("([0-9]+)")]
public int Age
}
Is there a better way?
You could create a model and use a Mapper (like AutoMapper or EmitMapper or ValueInjecter) to map between your objects, and validate against the mapped model.
When you need to transfer the object back you can map between your model to the recieved model.
This is very similar to a ViewModel approach in ASP.NET MVC.
So it's something like this:
Class A (the class from the DLL)
Class B (your model)
You set all your annotations on B, and create whatever properties you need.
What you use is B. When you get something from the repository/source you map (copy all relevant values) A=>B and send it (let's say as a model in a View).
When you receive B back you validate it, and then map it the other way B=>A, and send it to the repository/service.
BTW: I would recommend using this approach even if model A was YOUR class.
Why use ViewModels instead of Domain Models in Views.
#Linkgoron answer is true. You are searching view model vs domain model. we need to think the model from dll is a domain model and map it to our own view model as we did even when dealing with our own repository/persistence. it is a best practice. don't worry about mapper, it will map automatically.
See this example:
http://weblogs.asp.net/shijuvarghese/archive/2010/02/01/view-model-pattern-and-automapper-in-asp-net-mvc-applications.aspx
See this #Nick DeVore answer why view model instead of domain model here
Why Two Classes, View Model and Domain Model?
and also
Bestpractice - Mixing View Model with Domain Model
Your issue could be one of the reason why :)

MVC: Am I doing it right?

Hey people. I don't know if I understood 100% the MVC concept.
I'm having troubles with the Model-View relation.
In order to present the data to the user, the View must have access to the data, right?
Is this access obtained by passing all the needed data to the view directly (and having the view hold the data within its class as an attribute), or just obtain the data "parsed" as strings, integers, etc... as it is needed (as the user navigates through the GUI) from the controller, by raising events? I feel like this is a little bit event overkill, since the data hasn't changed.
BTW, can you tell me what those arrows on the MVC diagram on Wikipedia do on a real example? Thanks.
A view is for presentation purposes only. The controller is in charge of fielding requests from the UI and invoking the necessary methods in the model, which then present their outputs to the views.
The arrows denote relationships between the classes. The dotted lines are relationships between classes and interfaces while the solid lines denote direct relationships, meaning that the classes likely hold instance variables of the classes they are related to.
The model is the central, authoritative repository of information. As an example, take a church's directory of its congregation.
There are controllers into that model that inform the model of data that should be changed. As an example, a congregation member informs the church office when they move or change phone numbers, and the directory is updated.
There are also views into that model that use the data, but cannot make changes to it. As an example, one church member can get information about another from the directory.
Note that in some cases views and controllers can be the same thing, or views for one model, controllers for another, etc., etc. For example a church member can be a view into other members' data, or change their own by interacting with the model.
The important thing to keep in mind is who owns the authoritative version of the data. The invariant that it is the model that has the most timely, accurate and authoritative data means you know exactly where to go to get the information you need.
There are two basic ways a model can communicate with the views: pushing and pulling. Pushing the data involves intelligence on the model side to know which views should be notified when a piece of information has been updated. Pulling the data involves intelligence on the view side to know how and when to look at the model for changes to the data it is most interested in.
To build on the previous answers, here is a super simple application showing the various usage of each of the areas in question. This app stores and displays cars which a Salesman has sold.
First we have our models:
public class Car
{
int Id { get; set; }
string make { get; set; }
string colour { get; set; }
}
public class Salesman
{
int Id { get; set; }
string name { get; set; }
IList<Sale> Sales { get; set; }
}
public class Sale
{
int Id { get; set; }
int CarId { get; set; }
int SalesmanId { get; set; }
decimal Amount { get; set; }
}
Now lets say we need to display a page which details all of the cars which a particular Salesman has sold. To do this we decide what data we will need on the page, e.g. Salesman name and a list of Car's which he has sold. We create a View Model of this data.
public class SalesViewModel
{
string SalesmanName { get; set; }
List<Car> CarsSold { get; set; }
}
Now we need to build (populate) this View model in our controller ready to be passed to our View.
public ActionResult SalesmanCarsSold(int salesmanId)
{
SalesViewModel salesVm = new SalesViewModel();
using (var dbCtx = new dbCtx())
{
salesVm.SalesmanName = dbCtx.GetSalesmanById(salesmanId).Name;
salesVm.CarsSold = dbCtx.GetCarsSoldBySalesmanId(salesmanId);
}
return View(salesVm);
}
Now all there is to do is just write this data out to our view, e.g.
#model MyProject.Web.Models.ViewModels.SalesViewModel
Salesman Name: #Model.SalesmanName
#foreach(var car in Model.CarsSold)
{
Car: #car.make
}
I believe I can add a little clarity. Basically you can use a Singleton pattern where only one instance of the model exists then you can use said Singleton within the View to bind things in your View to the model, that is you add listeners for changes to the model (in one sense or another) and the view updates itself whenever the model changes.
The model itself isn't affected directly by the view rather the view dispatches events or otherwise uses the controller to modify the model. This way you can have a common "shared" model a common controller which modifies said model and all sorts of views that display parts of said model in ways that make sense.
The views don't need to handle passing around data between one another in this way and the common functionality of modifying the model is contained in the controller. I had some trouble with these concepts when I first dove into them as well mostly because you never have 100% true separation of these parts, they are all related and will have a references to one another (via attached listeners at the least).
In Flex/AS3 my dev environment of choice this is very very easy to accomplish, you make on Model.as file that has a static variable called say modelLocator which is itself a new Model(), in the Model.as you define all your public variables, in Controller.as you have a handle on the model by creating a property (sure call it modelLocator here too) and within the controller's constructor you can instantiate the modelLocator like modelLocator=Model.modelLocator, do the same in your View then in the view you just update your view components when the model changes (in Flex you can use {} to bind values directly onto properties of your components, views pull from the model based on the post from #fbereto, good explanation btw).
From a high-level view, when you think about application architecture i.e. data layer, business logic layer and presentation layer, MVC should only be your presentation layer. I have often seen people make the mistake of thinking that in MVC, models represent their data layer, controllers represent the business logic layer and views represent the presentation layer.
You should always have a separate business logic layer (or services layer) which your MVC controllers access to carry out business logic, and also a separate data access layer (or repositories) which is only accessed by your services/business logic layer to retrieve data out of the database.
In your typical MVC application, you may have multiple view models representing the same data layer object (which typically represents a database table). For example, you may have 2 views for to represent information about a person; one is a summary view and the other is a details view. In your MVC application you will have 2 View Models i.e. PersonSummary and PersonDetail both of which are populated from the same Persons table in the data layer and are returned to your Controller Action when your controller calls methods (e.g. GetPersonSummary() and GetPersonDetails()) on the PersonService class (business logic layer).
Layering your applications in this way will make them far more maintainable and testable than treating your View Models as data models and writing all your business logic in the Controller actions.
This was my 2cents anyway! Hope it helps you understand MVC better...

MVC: pass model / model data to a view from a controller?

If a view needs to acces data from a model, do you think the controller should:
a) pass the model to the view
b) pass the data of the model to the view
c) neither; it shouldn't be the controllers concern. Let the view access the model directly to retrieve the data. Only let the controller give some parameters the view needs to filter the data from the model.
d) it depends on the situation.
e) none of the above, but [...]
Thanks
After some debate in the comments to an answer that was deleted by the user, maybe this needs clarification. My view of the MVC architecture is biased towards that of the Zend Framework (php) in which an action in a controller by default has a default view assigned to it. So it's not so much the model that dictates which view is approporiate, but rather the controller. Do you feel the model should dictate what view is appropriate? The only way I see fit to let the view be build based on a model, is by letting the controller pass the model to the view. Are there other techniques to let a view access a model without the controller being involved? Or is it perfectly fine to let a controller pass the model to a view, so that the view can be build based on the models attributes?
e) None of the above; pass in a view-optimised "ViewModel".
Example in ASP.NET MVC:-
public ActionResult Details(int id)
{
Product p = ProductService.GetProductById(id);
if(p == null) { return RedirectToAction("Index"); }
ProductViewModel model = new ProductViewModel(p);
return View(model);
}
both a) and b) "will do" subject to d). Never ever c).
Typically, the ViewModel just encapsulates the Model (if nothing complicated is going on, your view could access the model directly via ProductViewModel.Product). If the view needs to do anything complicated with the Model however, it's the ViewModel's responsibility to do that, rather than the responsibility of the Controller, or the View.
This keeps your concerns nice and segregated. Your Controller doesn't care exactly what specific data your View needs (beyond the fact that it's rendering some Details of a Product), or especially what format your View needs that data in. Your View doesn't depend on the implementation details of your Model. Your Model doesn't have to concern itself with how it's being Viewed. If you have two Views rendering Products (e.g. Create, Edit, Summary, MoreDetails etc), those Views can have different ViewModels to expose only the data that each specific View needs, so your Views aren't depending on eachother. Lovely :)
Some further reading from various viewpoints:-
http://www.thoughtclusters.com/2007/12/datamodel-and-viewmodel/
http://stephenwalther.com/blog/archive/2009/04/13/asp.net-mvc-tip-50-ndash-create-view-models.aspx
http://www.nikhilk.net/Silverlight-ViewModel-MVC.aspx
I think ViewModels are a particularly .NET thing, but I see no reason at all why the pattern can't be used in PHP.
Hope this helps.
Ideally, it should "pass the data of the model to the view" so the view doesn't need to know any explicit structure of the model and thus be more reusable and designer-friendly.
But practically, "pass the model to the view" works as just fine. Most of the time you will need a new view anyway because clients never share favorite colors (if you know what I mean :-) so views re-usability doesn't justify having a lot of tedious code required to copy data from the model to the view.
What you should concern more about is the modularity of the controller itself, since many websites do share common functionalities (controllers) such as web forums or a news listing but not looks (views)
This is late I know, but I'm having this issue on a project I am working on. I started with a) - for simplicity - and now running into road blocks.
I am coming around to this method:
e) None of the above; pass in a view-optimised "ViewModel".
because it avoid bloating both your model classes (instances of which are "transaction objects") and your views. For example, you may need to render a number with a specific number of decimal places (this is the problem I am having now).
With an intermediate "ViewModel" this is easy - you just write the relevant ViewModel "getXXX" method to return the number formatted how you wish.
If you just pass the model directly into the view, you will need to specify it in the view every time you use this figure (going against DRY - don't repeat yourself), or alternately, add a rendering method to your model classes (which goes against a class being for one purpose only).
Cheers
a) pass the model to the view
Otherwise the controller is manipulating the view via screening the model. This is what would happen in "b) pass the data of the model to the view". The b) option doesn't really even make sense in the pure MVC pattern. After all, the model IS the data. If the model is changed for consumption, a view has been applied, whether you choose to do it in the controller and pass it off as a controller function. What happens when you have a different view? Does the controller screen its data differently? You soon have two views for model, the controller sub-view and the view itself.
For me that's e).
As already mentioned here, ideally the view and the model are decoupled. The way I prefer to implement this is to have a viewHelper for a model. This has the API the view can use to get the data. Now views are not affected by changes in the model and the view doesn't need to 'get' the internals of the model. These are hidden away by the viewHelper.
example:
class Post {
public function export(ViewHelper $helper) {} // I try to avoid getters when I can
}
class PostViewHelper {
public function getTitle($parameters) {} // title of current post in the loop
}
class PostView {
private $helpers = array();
public function loadTemplate($path) {}
public function addHelper(ViewHelper $helper, $name) {}
public function __get($key) {} // if exists $this->helper[$key] etc
}
in a template
<h1><?php $this->post->getTitle(); ?></h1>
You may want to implement this differently. But my point is in how the view and the model are decoupled, introducing an intermediate viewHelper wich creates the view/template API.
I don't think it's that complicated. a or b.
The controller's job is to manage the relationship. It finds the model and view and provides the view all the model data it needs to do its job. That's it. MVC doesn't dictate the exact form the data takes.
(a) Start simple. It's pretty natural to pass the model objects directly to the view. If you have a page about a Foo, just pass the Foo.
(b) But at times-- and only at times-- you create a value object / DTO to get the data to the view (called a ViewModel above). Do this when there's a mismatch between the view and the native model, such as summary views. If the view is presenting a summary of 1,000,000 objects, you don't want to hand the view the model objects; you want to hand the view a summary of the 1,000,000 objects.
And the exact implementation really depends on the language and framework you are using. But I think these guidelines are a good start.
uhh b.
i dont really see the difference between a and b other then some technicallity of how you will be passing data.
usually you pass a map of data to the view with some data from the model

Resources