Team,
I am new to MVC and need some suggestion, well I have come across a situation where in I have to put multiple objects on a same view e.g. display employee, dept, etc details on same page for this I have appropriate models and since single model object is passed from controller to view I have created a view model which contain instance of the all the model my first query is
Below viewmodel EmpVM - Is this the right approach for passing object from controller to view this class will be instantiated in controller of particular view.
In case I have multiple entries of a entity i.e. address(shipping and billing) in address table is it fine to declare two instance of object in viewmodel or declare a single list and iterate in view to populeate one in grid and another in controls.
**
public class EmpVM
{
List<Address> multiAddObj{get;set}
Address singAddobj{get;set;}
}
**
Any suggestion/help on this will be of gr8 help.
Thanks in advance.
HSR.
It is perfectly OK to have a ViewModel object which encapsulates multiple model objects. You did right.
It depends on what's logically "correct" to your applications. For some purposes you should create an IEnumerable object and iterate it in the view, while in other cases it would make more sense to simply have to model objects in the ViewModel.
Related
I have a viewmodel that needs to be populated with data from an entity
I call this method within my controller
public AssessmentResponseVM ConfigureAssessmentViewModel(AssessmentResponseVM model)
{
if (model.AssessmentID != null)
{
model.Questions = getQuestionAndAnswerList(model.AssessmentID);
}else
{
model.Questions = getQuestionAndAnswerList(null);
}
return model;
}
It basically retrieves a list of questions and answers for the supplied assessment and assigns them to a property of the viewmodel. Where should this ConfigureAssessmentViewModel method live? At the moment it is sat in my controller but i'm not sure I like it there. Should it sit in the viewmodel class or elsewhere?
In this case you should just keep this logic in your controller and return an Enumerable of questions:
var questionsAndAnswersList = getQuestionAndAnswerList(model.AssessmentID);
Also note that you are checking for a null AssessmentID but then passing null into getQuestionAndAnswerList anyway.
then your View should use
#model IEnumerable<Question>
You may also want another view here that knows how to display only questions. See this other question on display/editor templates.
getQuestionsAndAnswerList most likely belongs in a Service/Business logic class that knows how to access the data and translate it into something the controller knows how to use. How you separate your ViewModel classes and Service classes really depends on the size of your application and preference.
A good answer would be quite exhaustive, but basically what you have here is what is part of an object mapping layer. I've seen lots of different architectures that handle this differently. Usually the best thing is to be consistent.
For me, because my business models and view models are two different structures, and view models are tailored highly to a view, or sometimes a handful of views in a controllers, then the controller is responsible for populating the view model from the business model. This is because my approach usually involves a data access layer, business layer, and view layer(consisting of controller, view model, view).
There is no business logic in my controllers, and so they are very thin, and all they are really responsible for is calling into the business layer, retrieving business models, and then populating view models with data from the business layer.
The controller is sort of a glue between the UI and the business layer.
Therefore, in this case if I had a function like this that did something as simple as setting some data on the ViewModel, and it for some reason needed to be reused by multiple controller actions, then I'd just make it a private function of the Controller.
If you were working with a different architecture, that might not be appropriate. I've seen cases where the business layer returned ViewModels instead of business models, and so that mapping occurred in the business model.
If you were working with an existing architecture, I would put that code as a private function in the same class that creates the view model initially, i.e. the class containing new AssessmentResponseVM(...
when do you think is it better to use ViewData over a view model?
I have the same exact partial view in a couple of main views. I'd like to control how a partial view is rendered but I'd also prefer the partial view to accept only a view model which is a collection of records, just a pure IEnumerable<> object. I'd rather avoid to send the full view model object from a main view because it also contains a lot of different properties, objects, that control paging, sorting, filtering etc.
Therefore the question is if I should create another view model for the partial view or is it ok to use ViewData? I've read soemwhere that using ViewData is a very bad practice.
With View Data, I could simply pass require details like this:
#{
ViewDataDictionary vd = new ViewDataDictionary
{
new KeyValuePair<string,object>("WithDelete", Model.WithDelete),
new KeyValuePair<string,object>("WithRadarCode", Model.WithCode)
};
}
// ...
#if (Model != null) {
Html.RenderPartial("_ListOfRecordingsToRender", Model.recordingViewModel, vd);
}
At the moment, it would be sorted out.
My worry is that currently this *.recordingViewModel has plenty of different variations in my project, because of different models for creating / editting, listing, shoing details of a record etc. I feel like it may start to be too messy in my project if I make view model for each action.
What do you think. Please could you advice on that particular problem. Thanks
I think you should stick to using a ViewModel, your ViewModel is the class that defines your requirements for the view.
My reason behind this is that in the long run, it will be a lot more maintainable. When using ViewBag it's a dynamic class so in your views you should be checking if the ViewBag property exists (And can lead to silly mistakes like typo's) e.g.:
if(ViewBag.PropertyName != null)
{
// ViewBag.PropertyName is a different property to ViewBag.propertyName
}
This type of code can make your View's quite messy. If you use a strongly typed model, you should be able to put most of the logic in your controllers and keep the View as clean as possible which is a massive plus in my books.
You also will also end up (if you use ViewBag) attempting to maintain it at some point and struggle. You are removing one great thing about C#, it's a strongly typed language! ViewBag is not strongly typed, you may think you are passing in a List<T> but you could just be passing a string.
One last point, you also will lose out on any intellisense features in Visual Studio.
I feel like it may start to be too messy in my project if I make view model for each action.
Wont it just be as messy in your controllers assigning everything to a ViewBag? If it was a ViewModel you could send it off to a 'Mapping' class to map your DTO to your View.
Instead of this:
// ViewModel
var model = new CustomViewModel()
{
PropertyOne = result.FirstResult,
PropertyTwo = result.SecondResult,
}
//ViewBag
ViewBag.PropertyOne = result.FirstResult;
ViewBag.PropertyTwo = result.SecondResult;
You could do this:
var mapper = new Map();
var model = mapper.MapToViewModel(result);
*You would obviously need to provide an implimentation to the mapping class, look at something like Automapper
I'd also prefer the partial view to accept only a view model which is a collection of records, just a pure IEnumerable<> object. I'd rather avoid to send the full view model object from a main view because it also contains a lot of different properties, objects, that control paging, sorting, filtering etc.
That is fine, just create a view model that has a property of IEnumerable<T>. In my opinion you should try and use a strongly typed ViewModel in all of your scenarios.
When assigning ViewModel fields, should the domain objects be passed directly to the ViewModel objects which will then determine how to present the data, or should another class like a service be assigning data from the Model to the ViewModel?
also:
EDIT:is there any sense in dividing a viewmodel into receiver and presenter? (instead of binding only certain fields on update?)
Usually the Controller Action takes the business objects and puts whatever is needed by the viewmodel.
If you have a business object that contains the fields Name, Address, Id and the View should only display the Name, then the ViewModel only has a field "Name", and the controller action populates it. The ViewModel should know nothing about your Business Classes, it should only know about the stuff that it needs to display.
The main/only logic is then "Display Logic", that is stuff like "if TotalAmount is negative, display it with CSS Class negativeNumber".
For the sake of SoC if that logic relates to View they safe to be in ViewModel or even in View itself but if they relate to Business or Program put them on Model and Controller respectively.
In my experience I've used services to map the Model to the ViewModel. I don't put logic in my ViewModels.
As an aside, it's probably worth your while to check out AutoMapper to assist you with the mapping. Definitely helps cut down on writing repetitive mapping logic.
My MVC application contains a parent model, which will contain 1 or more child models.
I have set up the main view to display properties from the parent model, and then loop through a collection of my child models (of various types, but all inheriting from the same base type). Each of the child models have a corresponding partial view.
My "parent" view iterates over the child models like this:
foreach (ChildBase child in ViewData.Model.Children)
{
Html.RenderPartial("Partials/"+child.ChildType.ToString()+"Child",
section);
}
My application has the appropriate /Partials/ChildType1.ascx, ChildType2.ascx, etc. Everything works great.
Is this an appropriate way to use Partial Views? It feels slightly off-kilter due to the dynamic names, but I don't know another way to perform dynamic selection of the proper view without resorting to a big switch statement.
Is it advisable to use the same view for multiple "modes" of the same model? I would like to use the same .ascx for displaying the "read only" view of the model, as well as an edit form, based on which Controller Action is used to return the view.
Iconic,
It's difficult to answer the questions without knowing exactly what you're trying to achieve.
I'll have a go though:
If you're familiar with web forms, think of your partial view as a webforms usercontrol for the moment and think of the part of your model that is relevant to your partial views as a 'fragment of information' that want to pass across to the partial view.
Natural choices for using a partial view would be for elements used in many views across your site.
So ... in answer:
1.Although what you are doing is valid, it doesn't seem quite correct. An example of a partial view I have used might be a row in a grid of data where you'd call the partial view passing in the row object as its model:
foreach (MyObject o in Model.objects)
{
Html.RenderPartial("Shared/gridRowForObject.ascx", o, ViewData);
}
You can strongly type your views also to expect a specific type to be passed through as the Model object.
Again another use might be a login box or a 'contact me form' etc.
2._Ultimately this is a personal design decision but I'd go for the option that requires the least application/presentation logic and the cleanest code in your view. I'd tend to avoid writing to many conditional calls in your view for example and by inferring a base type to pass across to all of your partial views as in your example, may well tie you down.
When learning the MVC framework I found the Oxite code to be useful.
I hope that helps.
The 'RenderPartial()' method in ASP.NET MVC offeres a very low level of functionality. It does not provide, nor attempt to provide a true 'sub-controller' model *.
I have an increasing number of controls being rendered via 'RenderPartial()'. They fall into 3 main categories :
1) Controls that are direct
descendants of a specific page that
use that page's model
2) Controls that are direct
descendants of a specific page that
use that page's model with an
additional key of some type.
Think implementation of
'DataRepeater'.
3) Controls that represent unrelated
functionality to the page they appear
on. This could be anything from a
banner rotator, to a feedback form,
store locator, mailing list signup.
The key point being it doesn't care
what page it is put on.
Because of the way the ViewData model works there only exists one model object per request - thats to say anything the subcontrols need must be present in the page model.
Ultimately the MVC team will hopefully come out with a true 'subcontroller' model, but until then I'm just adding anything to the main page model that the child controls also need.
In the case of (3) above this means my model for 'ProductModel' may have to contain a field for 'MailingListSignup' model. Obviously that is not ideal, but i've accepted this at the best compromise with the current framework - and least likely to 'close any doors' to a future subcontroller model.
The controller should be responsible for getting the data for a model because the model should really just be a dumb data structure that doesn't know where it gets its data from. But I don't want the controller to have to create the model in several different places.
What I have begun doing is creating a factory to create me the model. This factory is called by the controller (the model doesn't know about the factory).
public static class JoinMailingListModelFactory {
public static JoinMailingListModel CreateJoinMailingListModel() {
return new JoinMailingListModel()
{
MailingLists = MailingListCache.GetPartnerMailingLists();
};
}
}
So my actual question is how are other people with this same issue actually creating the models. What is going to be the best approach for future compatibility with new MVC features?
NB: There are issues with RenderAction() that I won't go into here - not least that its only in MVCContrib and not going to be in the RTM version of ASP.NET-MVC. Other issues caused sufficent problems that I elected not to use it. So lets pretend for now that only RenderPartial() exists - or at least that thats what I've decided to use.
Instead of adding things like MailingListSignup as a property of your ProductModel, encapsulate both at the same level in a class like ProductViewModel that looks like:
public class ProductViewModel() {
public ProductModel productModel;
public MailingListSignup signup;
}
Then get your View to be strongly-typed to the ProductViewModel class. You can access the ProductModel by calling Model.productModel, and you can access the signup class using Model.signup.
This is a loose interpretation of Fowler's 'Presentation Model' (http://martinfowler.com/eaaDev/PresentationModel.html), but I've seen it used by some Microsoft devs, such as Rob Conery and Stephen Walther.
One approach I've seen for this scenario is to use an action-filter to populate the data for the partial view - i.e. subclass ActionFilterAttribute. In the OnActionExecuting, add the data into the ViewData. Then you just have to decorate the different actions that use that partial view with the filter.
There's a RenderPartial overload I use that let's you specify a new ViewData and Model:
RenderPartial code
If you look at the previous link of the MVC source code, as well as the following (look for RenderPartialInternal method):
RenderPartialInternal code
you can see that if basically copies the viewdata you pass creating a new Dictionary and sets the Model to be used in the control. So the page can have a Model, but then pass a different Model to the sub-control.
If the sub-controls aren't referred directly from the main View Model, you could do the trick Marc Gravell mentions to add your custom logic.
One method I tried was to use a strongly typed partial view with an interface. In most situations an agregated ViewModel is the better way, but I still want to share this.
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IMailingListSignup>" %>
The Viewmodel implements the interface
public class ProductViewModel:IMailingListSignup
Thats not perfect at all but solves some issues: You can still easily map properties from your route to the model. I am not shure if you can have a route parameter map to the properties of MailingListSignup otherwise.
You still have the problem of filling the Model. If its not to late I prefer to do it in OnActionExecuted. I dont see how you can fill a Model in OnActionExecuting.