MVC creating multiple objects from single view - c#

Just to make it clear, my question is how do you CREATE multiple objects using a single view. My ViewModel works fine, I can display multiple objects no problem.
Its been a while between .NET coding (last time I was coding in 2.0). I have created an MVC 4 project and successfully created a ViewModel (displaying data on a single view from multiple objects).
However, I cheated. I populated the database directly. I now face the question in reverse, what is the best practice for creating multiple objects from a single view?
In my example, I have a User, who has a userId. The userId is a foreign key in UserDetails.
Just trying to get back into the swing of it and wondering what you guys do?

There are 6 ways to pass multiple object in MVC
ViewModel
Partial View
ViewBag
ViewData
TempData
Tuple
Each one have there own pros and cons.you have to decide base on your issue in hand.
For more information you can refer code project article on it: How to Choose the Best Way to Pass Multiple Models in ASP.NET MVC
Let me give advantage and disadvantage of View Model
ViewModel :
Advantages
ViewModel allows us to render multiple model types in a View as a
single model.
Great intellisense support and compile time error checking on View
page.
ViewModel is good for security purpose also as Views have only what
they exactly need. Core domain models are not exposed to user.
If there is any change in core domain model, you do not need to
change anywhere in View code, just you need to modify corresponding
ViewModel.
Disadvantages
ViewModels add another layer between Models and Views so it increases
the complexity a little bit. So for small and demo applications, we
can use tuple or other ways to keep the things simple for demo.

Option 1:
The best approach is to use strongly typed views with Model or ViewModel.
For Example, you have two classes User and Education, you want to display all education details of user in a view, you can create a custom view model and pass it to view, where you view is strongly typed view model:
public class User
{
public int UserId {get;set;}
public string UserName {get;set}
-------
------
}
public class Education
{
public int UserId {get;set;}
public int DegreeId {get;set;}
public long Marks {get;set;}
---------------
--------------
}
Now create a view Model like this:
public class EducationViewModel
{
public User user {get;set;}
public List<Education> educationList {get;set;}
}
now pass the ViewModel to View and do this in View:
#model AppNameSpace.ViewModels.EducationViewModel
Tip: Create a folder named ViewModels and put all the viewmodel classes in it.
Option2:
Option 2 is to user ViewBag and pass multiple object from control to your view, ViewBag is accessible when you set some value in it in controller, you can access in the view of that action, after that it is automatically washed out, and its null if you access again it.
you can use ViewBag like this:
ViewBag.Message = "Using ViewBag";
and read value like this in View:
string Message = ViewBag.Message as string;
Option 3:
Option 3 is to store data in TempData, its once read only, means you set value in it, and when you read it, its automatically removed, TempData internally uses Session Variables.You can use TempData like this:
TempData["Key"] = "value";
now you read it in view:
string val = TempData["Key"] as string;
after reading it, it will be automatically removed, but you can keep it if you need it further like this:
TempData.Keep("Key");

Related

Returning multiples of the same model to view [duplicate]

I've been able to successfully return a model to a view and display the results in a strongly-typed fashion.
I have never seen an example where multiple models get returned. How do I go about that?
I suppose the controller would have something like this:
return View(lemondb.Messages.Where(p => p.user == tmp_username).ToList(), lemondb.Lemons.Where(p => p.acidity >= 2).ToList());
Does MVC let you return multiple models like that?
And then in the view I have this line at the top of the file:
#model IEnumerable<ElkDogTrader.Models.Message>
And I frequently make calls to "model" in the view.
#foreach (var item in Model)
If there were 2 models, how would I refer to them separately?
Is this possible with multiple models, or is this why people use ViewBag and ViewData?
You can create a custom model representing the data needed for your view.
public class UserView
{
public User User{get;set;}
public List<Messages> Messages{get;set;}
}
And then,
return View(new UserView(){ User = user, Messages = message});
In the view:
Model.User;
Model.Messages;
The ViewBag is useful because it is dynamically typed, so you can reference members in it directly without casting. You do, however, then lose static type checking at compile time.
ViewData can be useful if you have a one-off on your view data types and know the type and will be doing a cast in the view anyway. Some people like to keep the actual typed view pure in a sense that it represents the primary model only, others like to take advantage of the type checking at compile time and therefore make custom models needed for the view.
I believe ViewModel should be the way to go. Within the customary ViewModel, you can reference other models or define all the related domain models in the viewModel itself.

Two ViewModels for one View

I am developing a Web-App using ASP.NET MVC and I've been trying to avoid using the ViewBag, therefore I created few viewmodels to populate my drop-downs and in general to pass the data I need in my views. At the same time I would like to keep the data binding clean and avoid properties that will not be bound to (without using include/exclude attributes) and I've been told that obviously returnmodels are great for that purpose.
So is creating two independent models for one view a bad idea? One with all the data that needs to be displayed and another one only with the fields from my form or is this an excess of form over substance and should I reconsider changing my design?
Edit: A quick example because I'm not too good at explaining
class ViewModelA{ // passed to the view and then bound to when form is submitted
List<KeyValuePair<int, string>> DropDownValues; // will be always empty while databinding
int SelectedValue; // will be always 0 when passed to the view
...
}
Should I replace ViewModelA with
class ViewModelB{ // contains data passed to the view
List<KeyValuePair<int, string>> DropDownValues;
...
}
class ReturnModel{ // contains data returned from the view
int SelectedValue;
...
}
Obviously here I could just bind directly to my model but let's assume it's more complex and the data has to be processed before saved.
I think I know what you are asking. You are saying you have a viewmodel with, lets say, these properties: Age, Name, CountryOfResidence (for dropdown), and a few more properties. But when you create a new person, you only post Age, Name, IdOfCountry to controller.
So your question is what is the point of posting the whole viewmodel, when it is not needed. Fair question.
There are many ways you can do this. Here is one way:
Create a base class with common properties (for posting)
Create a derived class with more properties for the view.
Some people will refer to 1 as Data Transfer Object (DTO). These DTO's will be shared for communication between presentation layer, service layer, business layer, data access layer etc.

ViewBag as a holder of session models

This is more of a high-level question than anything else.
I have a MVC project which, among other things, manages users.
I am currently sticking to a more strict approach that on my view pages I only use a model which is declared, meaning that I have a:
#model MVCApp.Models.SomeModel
At the top of each View.cshtml
There are some pages that require more than 1 model. At this point I consolidate the 2 models into 1, and send it to the view as one model.
Here comes the tricky part. Let's say I have some model which holds the user data. That user data is stored in the session cookies (typical Forms Authentication). It seems weird to me that I now have to wrap each and every model I use with my own model that holds both the User Model and the model which I want to use inside that View.
The question that I ask myself is why not pass the User Model to the ViewBag and use it inside the View. Why is that considered to be bad practice? It allows me to attach that model to every page without having to ultimately duplicate all my models.
I'd love to get some guidance. I might be looking at this the wrong way. Any help will be much obliged.
Thanks,
There are a couple of reasons why ViewBag should be avoided:
ViewBag is weakly typed
You don't get Intellisense in the view
Your view is a mixture of ViewBag and a view model and your view gets information from different places instead of centralizing everything into a strongly typed view model
ViewBag doesn't work with strongly typed helpers and expressions because dynamic types cannot be used with extension methods (that's not a limitation of ASP.NET MVC, it's .NET => you cannot dispatch extension methods on dynamic types)
Due to this weak typing nature of ViewBag you will have to cast in your views turning them into spaghetti code because HTML helpers expect specific types to be passed as arguments
... this list goes on (I really don't have time to fill it but it is very large list)
So now that we know that ViewBag is bad and shouldn't be used there are different ways you could solve this requirement by using view models.
One possibility is to use the Html.Action helper which allows you to insert some portion of HTML in the view by going through a full Controller/Model/View lifecycle. This way you could have a commonly used widget without interfering with your main view model.
Another possibility is to have a base view model which will contain a property representing user details and which will be populated by a custom global action filter that could executed everytime a controller action has finished executing and returned a view result. The action filter could intercept this view result, read the authentication cookie information and set the view model property. This assumes that all your view models derive from the common base view model. This obviously makes sense if you need to display this user information on each page.
For example:
public class UserInfoInjectorAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var result = filterContext.Result as ViewResultBase;
if (result == null)
{
// the controller action didn't return any view result => no need to continue
return;
}
var model = result.Model as BaseViewModel;
if (model == null)
{
// the controller action didn't pass a model or the model passed to the view
// doesn't derive from the common base view model that will contain
// the user info property => no need to continbue any further
return;
}
model.UserInfo = ... go ahead and read the forms authentication cookie
userData portion and extract the information
you are looking for
}
}
Now all that's left is to register this action filter as a global action filter and it will be applied on all controller actions.
Now if all your view models derive from this BaseViewModel you will know that once you arrive in the view the UserInfo property will be populated with the relevant information without polluting all your controller actions with code that does the fetching of this property. And still you get strong typing in the view => no ViewBag (youpeeee).
Of course depending on your specific scenario there might be other ways to achieve that (obviously not involving any ViewBag).
You can an ActionFilterAttribute and in those Actions that load views which needs specific ViewBag items, you initialize them.
I don't recommend it, as it will be harder to mantains, but will be a generic approach which may solve your problems.

Beginner mvc where to call methods

I am doing big project in Web Forms and entered a big mess of code(can be solved with little refactoring), so I decided to take a peek at mvc, seems like everyone favores it over web forms.
I have dll file with all LINQ to SQL classes and methods for existing sql db and I started teaching myself by reacreating this project in mvc.I first recreated my homepage from webforms to razor, so far so good and I recreated one of the user controls to partial view and looped it.
Partial view is strongly typed with one of L2S class, the thing is there is some raw data in it.Like for example My model for partial view is my L2S class PostDetails: it consist od some data ready from output like: Title, Permalink, ViewsNumber etc. but it also cointains some raw data like UserId(I need to call method from dll to get username),DateTimeCreated(on which I also need to call method to get time difference), In webforms I would do this in codebehind but I'm not sure where to do it in mvc, maybe in controller and pass it in ViewData.I am also asking this for future, not just this case.
You should perform those actions in the controller. The controller is exactly what it sounds like, it controls the data flow between the model and the view.
Here is an example using your PostDetails:
PostDetailsModel
String Title {get;set;}
String Permalink {get;set;}
Int ViewNumber {get;set}
Int UserId {get;set}
DateTime DateTimeCreated {get;set;}
GetDetailsView: this will be requested by your user, and will be a visual representation of the PostDetailsModel (however you want to format that). When this View is requested, a call is made to your controller....
PostDetailsController
//This method will (by default) come from calling [BASEURL]/PostDetails/GetDetails
public ActionResult GetDetails()
{
var details = new PostDetailsModel();
details.UserId = GetUserId();
details.ViewNumber = GetViewNumber();
....
//By default this looks for a view in the PostDetails folder
//by the name of your method (GetDetails)
return View(details);
}
Notice how the controller is the router between the model and the view, basically. A note, however, it would be better to fill your model from methods contained within some sort of business layer (however you implement that). Something like var details = BL.GetDetails();
Also, when the user makes requests to save data, then you can do that with another method that takes the data (whether it be the PostDetailsModel or an int or...) and does whatever it needs to do, then it can redirect back to the display action (or wherever you need it to go)
There is a wealth of information on MVC with a simple google search. Here is Microsoft's overview, but the wikipedia article is very succinct if you just want the basics
In MVC, All your requests will be handled by an action method in a controller. and then controller returns a view. So you can get the data in your controller (or a different layer which will be called from the controller) and pass that data to your view.
Strongly typed views are a clean way of doing things. Create a ViewModel for your scenario. Mostly ViewModels looks similar to the Entities. Ex : For Displaying the details about a customer, i will create a viewModel called "CustomerViewModel"
public class CustomerViewModel
{
public string CustomerId { set;get;}
public string FirstName { set;get;}
}
Then in my CustomerController, I will have a get method for the customer
public class CustomersController : Controller
{
public ActionResult Details(int id)
{
CustomerViewModel objCustomer=new CustomerViewModel;
objCustomer.FirstName="Samuel";
//Instead of hardcoding the values here , you can get it
// from the database using the id and assign to the properties
return View(objCustomer);
}
}
And you will have a view called "Details.chtml" in your Views\Customer
folder which is strongly typed to your CustomerViewModel
#model CustomerViewModel
<div>
<h2>#Model.FirstName</h2>
<p>#Model.CustomerId</h2>
</div>
This can be accessed like http://yourdomain.com/Customer/Details/25
Personally i prefer to keep my controller actions thin. so i write the GetFromDatabase code in a seperate service layer and i just call that method from my action method
I think that you'll find this article very useful:
MVC Overview
It explains in detail, as to what each component should be used for:
Models. Model objects are the parts of the application that implement
the logic for the application s data domain. Often, model objects
retrieve and store model state in a database. For example, a Product
object might retrieve information from a database, operate on it, and
then write updated information back to a Products table in SQL Server.
Views. Views are the components that display the application s user
interface (UI). Typically, this UI is created from the model data. An
example would be an edit view of a Products table that displays text
boxes, drop-down lists, and check boxes based on the current state of
a Products object.
Controllers. Controllers are the components that handle user
interaction, work with the model, and ultimately select a view to
render that displays UI. In an MVC application, the view only displays
information; the controller handles and responds to user input and
interaction. For example, the controller handles query-string values,
and passes these values to the model, which in turn queries the
database by using the values.

c# mvc model vs viewbag

Suppose you have a list of People A and a list of People B in a page. And these two are seperate classes in L2S, representing two different tables. Therefore, you cannot pass a single model as follows:
...
#model PeopleA
...
#foreach(var peopleA in Model.People) ...
#foreach(var peopleB in //what?)
Accordingly, I guess, I have three options to follow.
The first one is to devide the page into partial views so that I can pass a model through RenderAction helper. Since I will use these partial views only once this option does not seem attracting to me.
The second option would be to use ViewBags which I don't want to since I prefer strongly typed models.
The last one, finally, which I was about to use but wanted to ask before doing so, is to create a model as the following:
ModelMyPage.cs
public List<PeopleA> peopleA { get; set; }
public List<PeopleB> peopleB { get; set; }
MyController.cs
...
ModelMyPage m = new ModelMyPage();
m.peopleA = // query
m.peopleB = // another query
return(m);
And you got the idea. Is this the valid way to accomplish my task or is there a better c# way to do what I want?
Creating a ViewModel specific to the page, as your option 3 is the way I would do it.
I believe this is also the recommended approach.
No, there is not any better idea. In asp.net MVC, M stands for ViewModels, not the Business, Domain models. It is recommended to create ViewModels for your views and it's not reccomended to use Business Models. You should design your ViewModels to fit the need of controller interactions with Domain, and from controller to view interactions
Your first and third options seem both OK.
ad 1) "only using them once" is not a good argument-against. Use Partial views to organize views.
ad 2) Use the Viewbag to add small items like a lookup list.
ad 3) ViewModels are (becoming) common in MVC. This is probably the best approach.
I would do it the third way. Additionally, if you are going to render identical html for each person in both arrays, I would concat them before foreach:
var person in Model.PeopleA.Concat(Model.PeopleB)
I usually create a Model for the page, and name it as such, eg AccountDetailsPageModel. Then other models can be properies of this for complex pages.

Categories