How to pass generic parameter to partial view [duplicate] - c#

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)

Related

How to pass a list of ViewModels to a View?

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
}

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

Razor. How to use partial view with IQueryable?

I'm completely new to Razor engine, so may be my question look silly. Anyway. I need to use partial view in main view and I'm passing my model that inherited IQueryable interface.
This look like that:
#{Html.RenderPartial("~/Views/comments/Details.cshtml", new IQueryable<BlogAspNetMVC.Models.comments>);}
Partial view model:
#model IQueryable<BlogAspNetMVC.Models.comments>
How should I change RenderPartial to be able accept this model as argument?
P.S.
Here is comments model:
public partial class comments
{
public int ID { get; set; }
public string Comment { get; set; }
public Nullable<int> Author { get; set; }
public Nullable<System.DateTime> Posted { get; set; }
public Nullable<int> PostID { get; set; }
public virtual blog_post blog_post { get; set; }
}
Here is Icomments interface:
public interface IComments : IDisposable
{
IQueryable<comments> GetPostComments(int postid);
//void Add(comments comment);
//void Update(comments comment);
//void Remove(int id);
}
This how implemented in repository:
public IQueryable<comments> GetPostComments(int postid)
{
var all = from a in db.comments
orderby a.Posted descending
where a.PostID == postid
select a;
return all.AsQueryable();
}
According to what you've posted this should pass the correct type:
#Html.RenderPartial("~/Views/comments/Details.cshtml",
new List<BlogAspNetMVC.Models.comments>().AsQueryable());
Although, you're just passing an empty collection. I suspect you are missing some data from the model from your parent view that you should really be passing to RenderPartial.
This is what i tried and it worked for me.
The Controller should pass the IQueriable object to the view
IQueryable<comments> commentsList = commentsRepository.GetPostComments(1);
return View(commentsList);
In the parent view (which renders the partial view) should use the #model directive as,
#model IQueryable<WebApplication1.Models.comments>
I modified #model directive in the partial view as,
#model IQueryable<WebApplication1.Models.comments>
Try once and it should work.

Pass a viewModel to the layout

I have this viewmodel that has some properties and stuff that i would like to apply
to the layoutpage:
public class BasicViewModel
{
public Page Page { get; set; }
public List<Settings> Settings { get; set; }
}
From other threads here have i understood that this is possible but i dont really understand how.
From what I understand I somehow need to modify a controller and this is where I get confused. How do I know what controller that has to be modified and how?
Any help appreciated.
In controller, Prepare an action like
public ActionResult BasicViewModelDemo
{
BasicViewModel obj=new BasicViewModel()
// assign properties
return View(obj);
}
and view write some jquery. (Here i am using knockout to make view model)
<script>
var model='#Html.Raw(Json.Encode(Model))';
var viewmodel = ko.mapping.fromJSON(model);
</script>
Here goes my solution -
Lets say you have a model of this way -
public class BasicViewModel
{
public Page Page { get; set; }
public List<Settings> Settings { get; set; }
}
public class Page
{
public string PageName { get; set; }
}
public class Settings
{
public string SettingName { get; set; }
}
Then in the controller you should initiate the model in this way -
public class HomeController : Controller
{
BasicViewModel model;
public HomeController()
{
model = new BasicViewModel();
model.Page = new Page();
model.Settings = new List<Settings>();
}
public ActionResult Index()
{
model.Page.PageName = "My Page";
ViewBag.LayoutModel = model;
return View();
}
}
So basically we used Constructor to initiate the model and then we assign proper values in the controller action.
Then in the Layout, we can use the Model property as shown below -
<div> #ViewBag.LayoutModel.Page.PageName </div>

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