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.
Related
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
}
I would like to know if I am doing something wrong or it is not possible to post only part of view model using default model binder. Let's say I have a complex viewmodel that only small part it should be posted. I would like to achieve something like this:
public class ComplexViewModel
{
public object FirstNotPostedData { get; set; }
public object SecondNotPostedData { get; set; }
//......
public object NthNotPostedData { get; set; }
public InnerModelToPost InnerModelToPost { get; set; }
}
public class InnerModelToPost
{
public string FirstProperty { get; set; }
public string SecondProperty { get; set; }
public string ThirdProperty { get; set; }
}
In view I would like to display part of model and post the other part:
#model ComplexViewModel
#* DISPLAYING DATA *#
<form>
#Html.HiddenFor( m => m.InnerModelToPost.FirstProperty )
#Html.HiddenFor( m => m.InnerModelToPost.SecondProperty )
#Html.HiddenFor( m => m.InnerModelToPost.ThirdProperty )
<button type="submit">Submit button</button>
</form>
And then I would like to be able to pass this model to my controller in this way using default model binder:
public ActionResult GetOnlyImportantPartOfModel( InnerModelToPost innermodel)
{
//I'm getting empty model when I' doing like this
return View();
}
You may ask why not to pass entire model as parameter to this action method. So the answer is: code readablity. I store ComplexViewModel in session and I read it in first line of my action method. I would like to pass only this data that I want to update my model with.
Your need to use the Prefix property of [Bind] attribute to strip the InnerModelToPost prefix from your form values.
public ActionResult GetOnlyImportantPartOfModel([Bind(Prefix = "InnerModelToPost")] InnerModelToPost innermodel)
{
....
}
Having said that, if your only using properties of InnerModelToPost, then in your GET method, you can read the parent class (ComplexViewModel) from Session, but pass only the InnerModelToPost property to the view
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>
I have a model:
public class DataModel
{
public GridSortOptions SortOptions { get; set; }
public string Term { get; set; }
public int? Page { get; set; }
...
}
public class GridSortOptions
{
public string Column { get; set; }
public SortDirection Direction { get; set; }
}
And a http request: ?Column=LastName&Direction=Descending
That request will not work, i need to update it as follow: ?SortOptions.Column=LastName&SortOptions.Direction=Descending
Is it possible to teach ASP.NET to understand the original request without changing the model?
PS. I know that I could create a custom binder but I feel that there is a much simple way exist...
Thanks in advance!
I have mine structured slightly differently, as I came across the same problem (in MVC1 and still have it now - mvc4) . I have often found that having nested models tend to cause headaches and unnecessary complexity, so I try to flatten my view models as much as possible, just to simplify things, so don't have to write custom model binders, saves a lot of time and code.
My action typically looks method looks like this
//...snip
public ActionResult List(int? page, GridSortOptions sortOptions, string keyword) {
var model = new UserGridViewModel();
IQueryable<User> users = new UserRepository(Session).List();
if (sortOptions.Column != null) {
users = users.OrderBy(sortOptions.Column, sortOptions.Direction);
}
if (keyword != null) {
users = users.Where(x => x.Name.Contains(keyword))
}
model.SortOptions = sortOptions;
//using MvcContrib.Pagination.PaginationHelper here
model.Results = users.AsPagination(page ?? 1, 20);
return View(model);
}
//.....
My view logic is simply:
#using MvcContrib.UI.Grid
#using MvcContrib.UI.Pager
#model UsersGridViewModel
#Html.Grid(Model.Results).Columns(cols => {
cols.For(col => col.Id).Sortable(true);
cols.For(col => col.Name).Sortable(true);
//...etc
}).Sort(Model.SortOptions)
My grid view models are normally like this:
public class UserGridViewModel
{
public IPagination<User> Results { get; set; }
public GridSortOptions SortOptions { get; set; }
}
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)