How to pass a list of ViewModels to a View? - c#

I am quite new to C# and asp.net mvc and I have been trying to find an answer to my question here and in other foras but have not succeeded. However if this question has been asked and answered before then I apologize and could you please link to that post.
I am trying to create a treeview where I pass a list of ViewModels to my View.
I use code-first approach and have added a migration between my model and the database.
My problem is how to pass a list of objects of the ViewModel to the View?
I can pass a list of objects of the model from the controller but how to pass a list of objects of the ViewModel? Is that possible?
Maybe there is a simple solution to this that I have not found yet and maybe I am doing this all wrong. Anyway I really need some help.
public class MyClass
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
}
public class MyClassViewModel
{
public MyClass Parent { get; set; }
public List<MyClass> Children
{
get { return GetChildren(); }
}
public List<MyClass> GetChildren()
{
var listOfChildren = new List<MyClass>().Where(c => c.ParentId ==
Parent.Id).ToList();
return listOfChildren;
}
}
public ActionResult CreateTree()
{
var viewModel = new MyClassViewModel();
//This only returns one instance of an object, how to return a list?
return View("CreateTree", viewModel);
}

It is very simple, you just pass the list of your view model to the view:
[HttpGet()]
public IActionResult CreateTree()
{
List<MyViewModel> viewModelList = MyViewModel.GetList();
return View("CreateTree", viewModelList);
}
On the view, you set the expected type for the model via the #model directive.
#model List<MyViewModel>
#{
//stuff
}
Now you can just iterate through your list of viewmodel.
#foreach (MyViewModel item in Model)
{
//stuff
}

You could create a class, containing a list of your ViewModels
public class ModelWithListOfViewModels
{
public List<ViewModel> ViewModels { get; set; }
}
Add your ViewModels to the list in the controller
public ModelWithListOfViewModels model { get; set; }
[HttpGet()]
public ActionResult FillList()
{
model = new ModelWithListOfViewModels();
//Here you fill the list with the ViewModels you want to pass to the View
model.ViewModels.Add(/** ViewModel here **/);
return View("CreateTree", model);
}
Then simply loop over the list to get your model in the View
#model ModelWithListOfViewModels
#foreach (var vm in Model.ViewModels)
{
//use vm to get access to a ViewModel added in the list
}

Related

Passing more multiple queries in a View ASP.NET

In my Repository class I have this two queries that I want it to appear in just one view:
public ClassXXXX GetxxxoList(string Name)
{
return context.ClassXXXX.Where(v => v.Name == Name).Single();
}
And the second query in Repository class I have:
public IEnumerable<ClassXXXX> List()
{
return context.ClassXXXX.ToList();
}
Then in my view I am doing this:
#model IEnumerable<Namespace.Models.ClassXXXX>
#model Namespace.Models.ClassXXXX
To return the two queries in my view respectively.
But ASP.NET throws exception on using #model twice in just one view.
instead of:
#model IEnumerable<Namespace.Models.ClassXXXX>
#model Namespace.Models.ClassXXXX
You can create an ViewModel class, that contains all your needed data:
public class YourContextViewModel
{
public List<Person> Person { get; set; }
public string UserName{get;set;}
...
}
It's a good idea to create an ViewModel object to populate your views.
I would suggest:
Create a new model that encapsulates both models. Create the model ModelXXXX in the Models namespace
public class ModelXXXX
{
public ModelXXXX(ClassXXXX singleXXXX, List<SingleXXXX> listXXXX)
{
SingleXXXX = singleXXXX;
ListXXXX = listXXXX;
}
public ClassXXXX SingleXXXX { get; set; };
public IList<ClassXXXX> ListXXXX { get; set; }
}
Then in the controller you would have something like:
public virtual ActionResult Index()
{
[...]
string name = "name";
ModelXXXX model = new ModelXXXX(GetxxxoList(name), List());
return View("..Views/Index.cshtml", model)
}
And finally in the view you would have:
#model Namespace.Models.ModelXXXX
[...]
#Model.SingleXXXX
#Model.ListXXXX
The first one (#Model.SingleXXXX) will have the value of #model Namespace.Models.ClassXXXX
And the second one (#Model.SingleXXXX) will have the value of #model IEnumerable

Access Generics List in ASP.NET MVC 5 View

I am getting started with MVC and I have the following Model
public class FormControls
{
//Properties of the FormControls object
public string formCName { get; set; }
public string formCType { get; set; }
public string formCCss { get; set; }
public string formCEnabled { get; set; }
public string formCDefaultVal { get; set; }
}
I also created the following control and I am querying a database using linq to select records. Each record will then have to be added to a list.
public ActionResult Index()
{
var DataContext = new EditProfileFormFieldsDataContext();
var controls = from c in DataContext.Controls
select c;
List<FormControls> Fields = new List<FormControls>();
foreach(var fc in controls)
{
//Create Object for Generic List
FormControls epc = new FormControls();
epc.formCName = fc.Control_Name;
epc.formCType = fc.Control_Type;
epc.formCCss = fc.Control_CSS;
epc.formCEnabled = fc.Control_Enabled;
epc.formCDefaultVal = fc.Control_DefaultVal;
//Add Object to FormControls Generic List
Fields.Add(epc);
}
return View("EditProfile");
}
My question is how would I access the list using RAZOR in the view? I am trying to loop through the list I created in the view. I am fairly new to MVC and I think I am over thinking a lot of this :) Thanks!
You can make the model of your view a List. Put this at the top of your view:
#model List<FormControls>
Change the return of your Index() method:
return View("EditProfile", Fields);
Then you can access it from the view by using #Model. For example, to iterate through it:
#foreach (var field in Model)
{
<p>#field.formCName</p>
}
Btw, there is a more direct way to implement the controller.
public ActionResult Index()
{
var DataContext = new EditProfileFormFieldsDataContext();
return View("EditProfile", DataContext.Controls.ToList());
}
or if you rename the view to "index.cshtml", you can do it like this:
public ActionResult Index()
{
var DataContext = new EditProfileFormFieldsDataContext();
return View(DataContext.Controls.ToList());
}
Suppose you do not have the index.cshtml yet, right click the "View(" and select "Add View", in the pop-up wizard, select "list view" and FormControls, there will be an auto-generated view with #model defined and a well done table demoing how to use it.

How to pass generic parameter to partial view [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Generic partial view: how to set a generic class as model?
I am trying to build common functionality using generic types but got stuck with below scenario.
View Model
public class DeleteForm<T>
{
public LogInfo Ticket { get; set; }
public string Id { get; set; }
public DeleteForm() {
Ticket = new LogInfo();
}
public DeleteForm(T viewModel) : this() {
ViewModel = viewModel;
}
public T ViewModel { get; set; }
}
Controller
public ActionResult Index(string name)
{
return View("index", new DeleteForm<List<Users>>(new List<Users>());
}
List Screen
#model DeleteForm<List<Users>>
//gridview displays list of users
#Html.Partial("revisionwindow", Model)
Partial View
#model DeleteForm<T> <---Its not working
#Html.EditorFor(o=>o.Ticket)
#Html.EditorFor(o=>o.Id)
use dynamic model instead.
your partial view can look something like this :
#model dynamic
#{
var myModel = (DeleteForm<List<Users>>) Model;
}
#Html.EditorFor(o=>myModel.Ticket)
#Html.EditorFor(o=>myModel.Id)
hope this help.
If you pass a model to view, it has to be strongly-typed (particular type).
So SomeClass<T> type won't work. Instead of generic type a base class could fill
your requirements. What I mean is:
View Model
public abstract class Form
{
public Form()
{
Ticket = new LogInfo();
}
public LogInfo Ticket {get; set;}
public int Id {get; set;}
}
public class DeleteUsersForm: Form
{
public DeleteUsersForm(IEnumerable<Users> users):base()
{
this.ViewModel = users;
}
public IEnumerable<Users> ViewModel {get; set;}
}
Controller
public ActionResult Index(string name)
{
return View(new DeleteUsersForm(new List<Users>()));
}
List Screen
#model DeleteUsersForm
//displays list
#Html.Partial("revisionwindow", Model)
Partial View
#model Form
#Html.EditorFor(o=>o.Ticket)
#Html.EditorFor(o=>o.Id)

Controller using multiple models?

Untill now in C# MVC3 i only had to use one controller which used only one model.
But now i think i need access to two models in my controller. I'm wondering if this is allowed in the MVC pattern?
I have a ProfileController. The ProfileController shows the profile info of a user obviously. But there's also some other data that i wish to show, like the groups a user created. For that i also have a GroupsModel.
How am i supposed to get both data from one controller?
How am i supposed to get both data from one controller?
By using a view model:
public class MyViewModel
{
public ProfileModel Profile { get; set; }
public GroupsModel Groups { get; set; }
}
and then passing this view model to the view:
public ActionResult ShowProfile()
{
var model = new MyViewModel();
model.Profile = ...
model.Groups = ...
return View(model);
}
And now your view will be strongly typed to the view model:
#model MyViewModel
and you can display information:
#Html.DisplayFor(x => x.Profile.SomeProperty)
Assuming that you aren't putting too much into a single view/controller, why not compose a simple view model which has the data you need?
public class ProfileInfo
{
public Person Person
{
get;
set;
}
public List<Group> Groups
{
get;
set;
}
}

Model validation with viewModel don't works

I use viewModels to communicate between my controller and my view.
To get model validation, i use a partial class like this :
[MetadataType(typeof(EvaluationValidation))]
public partial class Evaluation
{
public class EvaluationValidation
{
[DisplayName("Title of evaluation")]
[Required( ErrorMessage="Please give a title")]
public string Title { get; set; }
}
}
The Displayname is binded to view with no problem but when i try to submit the view, i get this error :
The model item passed into the
dictionary is of type
'FOOBAR.Models.Evaluation',
but this dictionary requires a model
item of type
'FOOBAR.Areas.Evaluation.ViewModels.EvaluationFormViewModel'.
This is the code used in my controller
[HttpPost]
public ActionResult Create(FormCollection formValues)
{
Models.Evaluation data = new Models.Evaluation();
if (TryUpdateModel(data, "evaluations"))
{
this.daoe.Create(data);
return RedirectToAction("Index");
}
return View(data);
}
And this is my viewModel
public class EvaluationFormViewModel
{
public FOOBAR.Models.Evaluation evaluations;
public SelectList selectlist_evaluationtypes { get; set; }
public SelectList selectlist_evaluationstatus { get; set; }
}
Have you got an idea ?
Thank's by advance
You are passing a Models.Evaluation instance to your view, which is bound to a model of another type.
Models.Evaluation data = new Models.Evaluation();
if (TryUpdateModel(data, "evaluations"))
{
// ...
}
return View(data);
If TryUpdateModel returns false (which happens when the form does not pass validation, for example), you are effectively passing data to the View, which is of type Models.Evaluation.
Try mapping it to type FOOBAR.Areas.Evaluation.ViewModels.EvaluationFormViewModel before passing it to the view.

Categories