Passing data from the controller to the view in asp.net - asp.net-mvc

I'm currently developping a website on asp.net MVC 4.
I'm a bit confused about the different ways to pass data from the controller to the view.
First of all, if we have a list of objects users, what's the difference between passing this list to the view using:
return View(users);
and
ViewBag.users = users;
My other question is about the first solution.
If we use this solution, do we have to use this
#model IEnumerable<mydb.users>
in the View?
Or could we use for instance
#model IEnumerable<mydb.registrations>
I know it would be odd to use a different model in the view than what we've used in the controller, but VS doesn't seem to be bothered.
Thanls a lot for you answers

You can pass parameters as you want, but the best way is to make your own "view model" for each view.
public class UsersViewModel
{
public IEnumerable<UserViewModel> Users { get; set; }
public int UserCount { get; set; }
}
Then pass this view model back to the view:
var viewModel = new UsersViewModel();
// ...
return View(viewModel);
You can use Automapper tool to automatically convert your entities to viewmodels and back. It will look like this:
// in Global.asax.cs on Application_Start
Mapper.CreateMap<User, UserViewModel>();
Mapper.CreateMap<IEnumerable<User>, UsersViewModel>();
// in your action
var viewModel = Mapper.Map<UsersViewModel>(mydb.users);
Your view model will be created automatically, check automapper docs for more info. Good examples on Automapper usage are available in RacoonBlog.

ViewBag is a container. You can pass anything to the View using the ViewBag say it a string or class or whatever. You can use any no of ViewBags to pass to view from controller.
return View(users); here you have the list there and you can pass only one object as model from controller to view.
The reply to the second question you can receive the object Model to View using #model where we use the reference to a Object in particular which is generic. The controller helps in identifying what is being passed to the view. You can use it in further coding using Model in your View. ex: Model.Users

Related

Entity - Automatically Create MVC Controller with dropdown

There's probably a really basic answer to this question but I am new to Entity and MVC and am getting used to the basics.
I'm trying to automatically generate a MVC controller for the main table Sites with a dropdown for server. It seems like I would need a model like this:
public class Sites
{
public TTSites TTSites { get; set; }
public List<servers> server { get; set; }
public Sites()
{
server = new List<servers>();
}
}
This is using the classes TTSites and servers both with string server
But if I set this as my model class and my entity database as data context it says I need to define a key. Should I be using the base classes instead of the model or what? Do i need to set something up in the model or base class?
It seems like you've got some terminology confused. You code the controller actions in a controller class, and the routing engine determines what controller action to call based on the URL. For example, if you have a HomeController class with a default Index action, it might look like this:
public ActionResult Index()
{
// code here
}
This would be invoked with the default routing, if you went to your site with a URL like this (let's say your site can be hit via the www.mysite.com URL:
http://www.mysite.com/Home
That would get you into the Index action in the controller.
Ordinarily, one would use a view model to use on the UI side, and that would be populated from an entiy with the data you need in the view itself. If you had two entities like TTSite and Server, you'd populate the Sites view model like so, as a (very simple) example:
public ActionResult Index()
{
var servers = yourDbContext.Servers.ToList();
var ttSite = yourDbContext.TTSites.GetByID(1); // retrieve one entity by its ID value, this would be acquired dynamically based on some sort of user input rather than hard-coded
var viewModel = new Sites(servers);
viewModel.TTSite = ttSite;
return View(viewModel);
}
I'm not including anything regarding making drop-downs, just illustrating getting data into a view model and then creating a view with that view model.
Note that you would not use the Sites class as an entity but rather a view model, and setting its data based on entities from your database. You wouldn't be setting any primary keys in a view model class; those are the concern of the data model, and you've presumably already got those entities (such as TTSite) set up in a usable fashion in your data layer.
Once you've got a controller action and a view up and working, you can turn to getting the view model data into a form usable by a drop-down list, and going from there.

Can you remove the HTML Field Prefix from strongly typed models in MVC 3?

I have a view model like this:
public class EditVM
{
public Media.Domain.Entities.Movie Movie { get; set; }
public IEnumerable<Genre> Genres { get; set; }
}
Movie is the real entity I wish to edit. Genres is simply present to populate a drop down. I would prefer that when I call:
#Html.TextBoxFor(m => m.Movie.Title)
inside my strongly typed view that the input control have a name = "Title" instead of "Movie.Title"
I do not wish to split my view into partial views or lose my strongly typed view by using ViewData or the like.
Is there a way to express to the View that I do not wish to have the Movie. prefix? I noticed that you can set:
ViewData.TemplateInfo.HtmlFieldPrefix = "x";
in the controller, but unfortunately it seems only to allow adding an additional prefix. Setting it to "" does nothing.
Is there any work around for this? Or am I stuck with the unfortunate prefix that isn't really necessary in this case if I wish to keep strongly typed views and lambdas?
Thanks for any help.
Update:
Here's the controller actions to maybe make things a bit clearer.
public ActionResult Edit(int? id)
{
var vm = new EditVM
{
Movie = id.HasValue ? _movieSvc.Find(id.Value) : new Movie(),
Genres = AppData.ListGenres()
};
return View(vm);
}
[HttpPost]
public void Edit([Bind(Prefix = "Movie")]Movie m)
{
_movieSvc.AddOrUpdateMovie(m); //Exceptions handled elsewhere
}
No, in order to do what you want you would have to rewrite the Html helpers, and then you would have to write your own model binder. Seems like a lot of work for minimal gain.
The only choice is a Partial view in which you pass the Movie object as the model. However, this would require you to write your own model binder to have it be recognized.
The reason you have to do m.Movie.Title is so that the ID has the correct name, so the model binder can recognize it as a member of your model.
Based on your update:
Your options are:
Use non-strongly typed helpers.
Use a partial view.
Rewrite the stronly typed helpers
Don't use the helpers at all, and write the values to the HTML
Personally, i'd just use 1 or 2, probably 2.
EDIT:
Based on your update above. Change your code to this (note, Genres does not get posted back to the server, so m.Genres will just be null on postback):
[HttpPost]
public void Edit(EditVM m)
{
_movieSvc.AddOrUpdateMovie(m.Movie); //Exceptions handled elsewhere
}
EDIT:
I did just think of an alternative to this. You could simply do this:
#{ var Movie = Model.Movie; }
#Html.TextBoxFor(m => Movie.Title)
However, if there was a validation error, you would have to recreate your EditVM.
I have a view model like this
I think that you might have some misunderstanding about what a view model is. A view model shouldn't contain any reference to your domain models which is what those Movie and Genre classes seem to be. I mean creating a new class that you suffix with VM and in which you stuff all your domain models as properties is not really a view model. A view model is a class that is specifically designed to meet the requirements of your view.
A much more correct view model would looks like this:
public class EditVM
{
public string MovieTitle { get; set; }
public IEnumerable<GenreViewModel> Genres { get; set; }
}
and in your view you would have:
#Html.EditorFor(x => x.MovieTitle)
#Html.EditorFor(x => x.Genres)
Another option is to either use the TextBox(string name, object value) overload instead of the TextBoxFor:
#Html.TextBox("Title", Model.Movie.Title)
You could also specify the input tag HTML instead of using a helper.
Another option is to take EditVM as your postback parameter. This is what I would do. My post action parameter is always the same type of the .cshtml model. Yes there will be properties like lists that are null, but you just ignore those. It also allows you to gracefully handle post errors as well because if there is an error you'll need to return an instance of that view model anyhow, and have the values they submitted included. I usually have private methods or DB layer that handles retrieving the various lists that go into the ViewModel, since those will be empty on postback and will need to be repopulated, while not touching the properties that were in the post.
With your post method as it is now, if you need to return the same view, you've gotta create a new EditVM and then copy any posted values into it, and still populate the lists. With my method, you eliminate one of those mapping steps. If you are posting more than one thing, are you going to have umpteen different parameters on your post action? Just let them all come naturally into a single parameter typed to the EditVM of the View. While maybe having those null properties in the VM during the postback feels icky, you get a nice predictable consistency between View and postback IMO. You don't have to spend alot of time thinking about what combination of parameters on your post method will get you all the pieces of data from the form.

Correct use of Model vs Controller in MVC / ASP.NET MVC

I have a Service class with a method called GetProducts(). That encapsulates business logic and calls the repository to get a list of products.
My MVC view wants to show that list of products as an MVC SelectList. Where is the correct place for that logic to go. I seem to have 3 options:
Model
The Model should expose a property called ProductSelectList. When the getter of this property is called by the View, the Model should call Service.GetProducts() and convert the result to a SelectList before passing it on.
Plausible argument: The Model should make calls to business logic and the repository. The View should merely render predetermined data. The Controller should not be involved, save for passing contextual data to the Model.
View
The View should contain code that calls Service.GetProducts() directly and converts the result to a SelectList inline.
Plausible argument: The View should call for this data directly as it is specifically for use on the View. There is no need to involve the Model or Controller, as we are calling an abstracted Service method anyway, so anything else just adds extra overhead.
Controller
The Controller should make the call to Service.GetProducts(), convert the results to a SelectList and pass it through to the Model, which should contain a simple ProductSelectList property. The View will access this property for rendering.
Plausible argument: The Controller knows which parameters to provide to the Service method, so it should make the call. The Model should be a simple placeholder for data, filled by the Controller. The View's job is to simply render the data from the Model.
I have a feeling that the correct answer is Model, but the other two make some reasonable points. Perhaps I've muddied the waters by already having a Service class that's separate to the Model?
Would anybody care to share their opinion? Is this just a matter of taste?
I personally subscribe to the logic of Number 3, allowing the controller to populate the Model (or View Model as is sometimes differentiated).
I have my views dumb and only displaying data.
I have my View Models store the information that the View will need, occasionally exposing 'get only' properties that format other properties into a nicer format. If my model needs access to my services, then I feel I'm doing something wrong.
The controllers arrange and gather all the information together (but do no actual work, that is left for the services.
In your example, I would have my controller action similar to:
public ActionResult Index()
{
IndexViewModel viewModel = new IndexViewModel();
viewModel.ProductSelectList = new SelectList(Service.GetProducts(), "Value", "Name");
return View(viewModel);
}
and my view model similar to:
public class IndexViewModel()
{
public SelectList ProductSelectList { get; set; }
public int ProductID { get; set; }
}
With the appropriate part of the view looking like:
#Html.DropDownListFor(x => x.ProductID, Model.ProductSelectList);
This way I'm content that I know where to look if there is an issue with anything and everything has a very specific place.
However, there is no correct way as seems always to be the case with these things. Stephen Walther has a good blog series on MVC tips. In one he talks about the View Model emphasis and although not a SelectList he populates, the SelectList is still data in much the same way his list of products is.
In a classic MVC architecture your Model shouldn't be much more than a container for your view data hence the reason it's often called a ViewModel. A ViewModel is different from the Entity Model(s) that your service layer manages.
Your controller is then responsible for populating your ViewModel from the entity model(s) returned by your service layer.
Due to convenience some developers will use their service layer entities directly in their ViewModels but long term that can lead to headaches. One way around that is to use a tool such as AutoMapper to automate the shuffling of data to and from your ViewModel and entity models.
Here's what a controller might look like. Notice that data such as the SSN does not get exposed to the view since there is a mapping from your Entity Models to your View Model.
public class Customer : IEntity
{
public string CustomerID { get; set; }
public string SSN { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
public class CustomerEditViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Country { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public string PhoneNumber { get; set; }
}
public class CustomerController
{
[AcceptVerbs (HttpVerbs.Get)]
public ActionResult Edit ()
{
Customer customer = _customerService.GetCustomer (User.Identity.Name);
var model = new CustomerEditViewModel ()
{
FirstName = customer.FirstName,
LastName = customer.LastName,
Address1 = customer.Address.Address1,
Address2 = customer.Address.Address2,
Country = customer.Address.Country,
City = customer.Address.City,
State = customer.Address.State,
Zip = customer.Address.Zip,
PhoneNumber = customer.Address.PhoneNumber,
};
return View (model);
}
}
You're right that there are a number of ways to handle this, and that's even before considering variations like MVP, MVVM, et cetera. Since you're asking about ASP.Net MVC in particular, I will defer to Microsoft:
An MVC model contains all of your application logic that is not
contained in a view or a controller. The model should contain all of
your application business logic, validation logic, and database access
logic. For example, if you are using the Microsoft Entity Framework to
access your database, then you would create your Entity Framework
classes (your .edmx file) in the Models folder.
A view should contain only logic related to generating the user
interface. A controller should only contain the bare minimum of logic
required to return the right view or redirect the user to another
action (flow control). Everything else should be contained in the
model.
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.
Source
I would say your call belongs in the Model.
One thing to keep in mind is that the SelectList class is specific to MVC only. So in my opinion it shouldn't be included in any business logic, and model classes fall into that category. Therefore your select list should be a part of a view model class instead.
This is the way it works in my projects:
Controller method is called
Controller uses repository (business logic, in other words) to get model data
Controller converts the model data if necessary and creates a view model object
Controller passes the view model to the view
The view displays the data in the view model with limited logic to show or hide things, etc
I'd go with option 3. In general, I'll construct my MVC apps such that the controller makes a call to the service to return a model (or collection of models) which are then passed to the view.
I generally keep my models very thin. They are a flattened representation of the data with validation attributes and that's it. I use a service (or model builder) layer to construct the models and do business logic on them. Some folks embed that into the model, but I find that makes for a messy project.
You definitely don't want the view making any calls to your services.
Update...
I'm assuming that this SelectList is your model. If instead it's a part of your model, then you're right, you should put it in your model. I generally don't like to make it a method call, though. I'd have a property on my model:
public SelectList Products { get; set; }
And have my service or model builder class actually populate it. I don't usually have any data-oriented methods on my models.
I'm going with option 1.
Models are the place to make calls to business logic, et cetera.
View - Should display only what the ViewModel already has been populated with.
Controller - the job of the Controller is to direct the traffic coming in (from Web requests) to the Logic that is responsible for handling the request. Hence the term 'controller'.
There are always exceptions to these, but the best place (structurally) is the Model.
I had this problem when I started into MVC and came up with this solution.
The controller talks to a Service Layer. The service layer contains my Domain models and does all the processing for request from the Controllers. The service layer also returns ViewModels to satisfy requests from the controller.
The service layer calls a repository and gets the entities it will need to build the ViweModels. I often use Automapper to populate the ViewModel or collections within the view model.
So, my view models contain all that is needed by the View, and the Controller is doing nothing but handling request and forwarding them to the appropriate service handler.
I don't see a problem with having view specific items like SelectLists in the view Model either.
None of the above.
In my web layer I basically just have html and javascript views. The model shouldn't leak into the view and neither should the services.
I also have an Infrastructure layer which binds the services and model to the views. In this layer there are ViewModels, which are classes that represent what will be displayed on the screen, Mappers, which do the work getting data from services/model and mapping it to the view model, and Tasks, which perform tasks such as Saving, Updating and Deleting data.
It is possible to put a lot of this infrastructure in the Controllers, similar to the example Todd Smith has given above, but I find for anything other than trivial views the Controller becomes littered with code to load data and populate view models. I prefer a dedicated single responsibility mapper class for each view model. Then my controller will look something like
public class CustomerController
{
[AcceptVerbs (HttpVerbs.Get)]
public ActionResult Edit (int id)
{
return View (CustomerEditMapper.Map(id));
}
[AcceptVerbs (HttpVerbs.Post)]
public ActionResult Save(CustomerEditViewModel model)
{
var errors = CustomerEditUpdatorCommand.Execute(model);
ModelState.AddErrors(errors);
return View ();
}
}
I'm torn between option 1 and option 3. I've ruled option 2 out completely as to me that's polluting the view with procedure calls not just presentation layer work.
Personally I would do it in the model and the getter would call the Service layer but I also subscribe to the belief that the model should only contain the information the view needs to render the page, by not fully containing the data in the model at the time you pass it to the view you are breaking this.
Another option here though would be to avoid tightly coupling the view and model by putting a Dictionary of the Products into the view through a Service Call then using the view to transform the Dictionary to a SelectList but this also gives you the ability to just output the information as well.
I think this boils down to a preference as to where you are happy having your logic.

Using LLBL as Model in MVC

I have settled on trying to use ASP.NET MVC but the first part I want to replace is the Model. I am using LLBL Pro for the model.
I have a table called "Groups" that is a simple look up table. I want to take thhe results of the table and populate a list in MVC. Something that should be very simple... or so I thought.... I've tried all kinds of things as I was getting errors like:
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[glossary.EntityClasses.GroupEntity]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[glossary.CollectionClasses.GroupCollection]'.
private GroupCollection gc = new GroupCollection();
public ActionResult Index()
{
gc.GetMulti(null);
return View( gc.?????? );
}
This is all I am trying to do, I've tried lots of variations, but my goal is simply to take the data and display it.
Not sure if this would work, but you could try wrapping the EntityCollection into a ViewModel class and passing it to the View like so:
public class GroupsViewModel()
{
public GroupCollection Groups { get; set; }
// other items in your view model could go here
}
then convert your controller method to
public ActionResult Index()
{
GroupCollection gc = new GroupCollection();
gc.GetMulti(null);
GroupsViewModel vm = new GroupsViewModel();
vm.Groups = gc;
return View(vm);
}
I like this approach because each ViewModel is an object in-and-of itself.
You can use the AsEnumerable extension where your ????? are or change the type of your ViewUserControl(in the markup) to be of type System.Collections.Generic.List. Basically what you need to correct is the mismatch between the type of the View and the Model being passed in.
I'm not sure about your exact error, but I'd venture a guess that one of two things are happenging:
You are making some sort of invalid / illegal call on your LLBLGen object. If this is the case make sure you are setting it up right / calling right method / property etc.
The model you are passing to the veiw is too hairy for it to deal with. In this case, and in general, you should create a light 'View Model' class with just the data you want displayed and populate it from your LLBLGen object first then pass it to the view, which will be able to easily handle your view model class.
Here are some references:
http://stephenwalther.com/blog/archive/2009/04/13/asp.net-mvc-tip-50-ndash-create-view-models.aspx
http://nerddinnerbook.s3.amazonaws.com/Part6.htm
http://www.codinginstinct.com/2008/10/view-model-inheritance.html
Stemming off what Yuriy said, it looks like your view is strongly typed to a "collection" of a collection of your groupentity, and you are trying to pass just the collection of your groupentities. Make sure your "collection" type (IEnumerable, IList, etc) matches what type of collection you are sending in your controller, along with the type of the actual object in the collection.
View:
System.Collections.Generic.List1[glossary.EntityClasses.GroupEntity]
Controller:
System.Collections.Generic.List1[glossary.EntityClasses.GroupEntity]
Just a thought

ASP.NET MVC how to bind custom model to view

I would like bind an array data to view in ASP.NET MVC, how can I do that?
sorry for not clear about my question.
Right now, I creat a custom object(not array), I tried to pass it to View, but the error shows
"The model item passed into the dictionary is of type 'ContactView' but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable"
You can use the ViewData[], but the best way would be to actually create a view class and return that.
So let's say the view you want to send the data is called Contacts. Create a new View class and return that. so instead of this:
public ActionResult Contacts(){
ViewData["contacts"] = arrayOfContacts[];
...
return View();
}
You can get strongly-typed views by doing this:
public class ContactsView(){
Object[] ContactsList {get;set;}
}
public ActionResult Contacts(){
...
return View(new ContactsView(){
ContactsList = arrayOfContacts[];
});
}
Then in the actual view, you can have it be strongly typed by accepting objects of type ContactsView. That way in the actual View, have it inherit like so:
... Inherits="System.Web.Mvc.ViewPage<ContactsView>" ...
Which allows you to call your array like...
Model.ContactsList
as opposed to this:
object[] arrayOfItems = (Object[])ViewData["theContactsList"];
In which case you'd probably want to check if it's not null, etc. The benefit of this is that if you refactor it's much easier. Not to mention the ease and type security of use of strongly typed objects.
Put it in the ViewData, and use for..each to loop through it?
Look at this link: http://nerddinnerbook.s3.amazonaws.com/Part6.htm
Basically you could load the array into a viewdata object, and use that as you like.

Resources