Bind customizable views to dynamic models - asp.net-mvc-3

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'.

Related

Need help to generate view where data comes from many models

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.

Need expert's voice for mvc beginner about Controller & Model

I am quite new to MVC. I am having the following questions, please help me clarify those questions, thanks a lot.
Q1. Where should I populate my view model? e.g. My view model is very big, and contains a lot of the dropdown listbox, multi select list and the other few complex objects. I am currently populate them inside the view model self, by passing the model through the constructor, and load all the object data within the constructor. I also see my college populate the viewmodel inside controller. so I am confusing now, coz lots of people suggest to keep the controller small and skinny.
Q2. We are using the linq2sql as data access layer, should I use the table entity in my viewmodel instead of creating separate model class? Expert said it's bad, but if create seperate model class, I basically repeat them and I also need to copy those value to linq 2sql entity every time when I want to persist data, it's not that fun, too much work.
lots of people suggest to keep the controller small and skinny.
Yes. What people mean is that the controller should not contain any logic, except for model <-> view mapping. With model I mean the "M" in MVC.
Q2. We are using the linq2sql as data access layer, should I use the table entity in my viewmodel instead of creating separate model class? Expert said it's bad, but if create seperate model class, I basically repeat them and I also need to copy those value to linq 2sql entity every time when I want to persist data, it's not that fun, too much work.
No. You should not. Read my answer here: ASP.NET MVC Where to put custom validation attributes
Use a mapping framework for the model -> viewmodel conversion.
Update:
From what I understand, you suggest to assembly the viewmodel inside the controller (I mean call the business layer or repository to get my data) and use controller to call the business logic dealing with the data, am I right?
yes. The controller is really a glue between your business layer / repositories and your views. The views (and view models) should know nothing about them and the business layer / repositories should know nothing about the controller/view.
The controller was created for just that purpose. To create an abstraction between the user interface layer and the lower layers. Hence the only code that should exist in the controller is to make that possible (and therefore following the Single Responsibility Principle)
If you start adding that logic into your view models you start to add coupling between the lower layers and the user interface layer. Doing any changes in the lower layers will therefore also affect all your view models (instead of just the controller
your viewmodel should be a poco, and should most certainly not be handling the mapping of the model. if you don't want to map your model to your viewmodel in the controller i would suggest you look at something like automapper. it makes it easy.
once you've mapped from your model to your viewmodel, any extra properties that need to be set such as your lists should be set in the controller.
as i stated previously, definitely don't tie your viewmodel to your current orm or table structure. you never know what might need to be refactored, and if you can handle it via an automapper mapping instead of changing your view and viewmodel then you've saved yourself a significant amount of time.

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

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

MVC model design / inheritance

Forgive the vague title, I wasn't sure how to describe it.
If you have a generic model "Archive", how do you show different views/forms based on a user selected 'type'?
For example, the user creates a new "Archive", then gets the choice of video, book, audio etc. From there they get different forms based on the archive type.
Or would it be better to split them into different models - Video, Book, Audio?
Or can models inherit (like Video extends Archive). I guess this is basic OOP / classes, but have no idea how to apply that here.
Examples from any MVC framework are welcome!
Seems like you would not want to have the type inherit from Archive.
"Always favor encapsulation/containment over inheritance".
Why not create a class called Archive and give it a type property. The type can use inheritance to specialize for Audio, Video, etc.
It would seem that you would specialize Archive based on some other criteria. "FileSystemArchivce", "XMLArchive", "SQLArchive" and the type would not change. But the agilist in me says that this may not be necesscary at first, and you can always refactor the design later...
In terms of a controller, you probably get the biggest bang for the buck by encapsulating the differences of presentation for each type in the view. So only the view changes based on the type. Likely the semantics and rules for each one are the same and you would not need to have seperate controllers for each type. The views will be different for each type as it will have different attributes.
To actually show a different view should be easy in any MVC framework. For example, in Microsoft ASP.NET MVC you would not just return a view from a controller like the following:
return View();
but would actually state the name of the view as a parameter:
return View("VideoArchive");
which would then show the view from Views/Archive/VideoArchive.aspx
Your models Video, Book and Audio can inherit from Archive.
And each model will have a controller.
http://yourserver/Books/Edit/11
You will have to get your user to pick the type of archive they want before you create the corresponding model.
EDIT (in response to comment)
In ASP.NET MVC your model will be a class.
public class Video : Archive
{
public int Id {get;set}
public string Name {get;set;}
...
}
You will also have a controller
public class VideoController : Controller
{
public object Edit(int id)
{
Video myVideo = GetVideo(id);
return View("Edit", myVideo);
}
...
}
And you will have a view in the Views directory for example, the page which contains
public class Edit : View<Video>
{
...
}
So you can call this if you had a URL which was
http://localhost/Video/Edit/11
This was all done from memory, so there may be some mistakes, but the take-home message is that you specify the inheritance at the model. The model is just a class. In your case you want to inherit from Archive. Once you've done that the model is pass around as normal.
The Single Responsibility Principle (PDF) states that:
THERE SHOULD NEVER BE MORE THAN ONE REASON FOR A CLASS TO CHANGE.
Your Archive class violates this principle by handling multiple different types of archives. For example, if you need to update the video archive, you are also modifying the class that handles book and audio archives.
The appropriate way to handle this is to create separate classes for each different type of archive. These types should implement a common interface (or inherit a common base class) so that they can be treated interchangeably (polymorphically) by code that only cares about Archives, not specific archive types.
Once you have that class hierarchy in place, you just need a single controller and view for each model class.
For bonus points, the Single Responsibility Principle can even justify using a factory method or abstract factory for creating your model, view and controller objects (rather than new-ing them up inline). After all, creating an object and using that object are different responsibilities, which might need to be changed for different reasons.
Seems to me that one solid point in favor of MVC is that you may not need to customize the model (or the controller - of which you want only one) if all the user needs is a different view. Multiple models would appear only if the storage (persistence) architecture dictated a need for it. Some feature like data access objects (DAO) would potentially appear as another tier, between the controller and the model,should you require multiple models.
Take a look at the Apache Struts project for examples. As stated in Struts for Newbies, "To use Struts well, it's important to have a good grasp of the fundamentals. Start by reviewing the Key Technologies primer, and studying any unfamiliar topics."
For another resource, see Web-Tier Application Framework Design (Sun J2EE Blueprints)

Resources