I am doing Web project with MVC 5 . I need pass to some data to layout page (data as Category_id or Category_Name). I read some answers that say I need to make View Model , but my project must be in MVC and not in MVVM, Do you any ideas? Thanks!
Asked
Active
Viewed 339 times
1
-
"I read some answers that say I need to make View Model , but my project must be in MVC and not in MVVM" - I don't think you truly understand how those design-patterns work: The `Model` object you pass into an ASP.NET View **is** a "View-model". However "MVVM" itself only applies to WPF which has long-life'd _interactive_ viewmodels, whereas ASP.NET MVC uses short-lived (ideally immutable) view-models. The property is called `Model` because calling it `ViewModel` would be unnecessarily verbose. – Dai Aug 03 '21 at 08:17
-
We need more detail: please tell us **what** data you want to pass into your layout page? Ideally layout-pages shouldn't need any data in the first place (at least, not like that). Have you read this? https://stackoverflow.com/questions/4154407/asp-net-mvc-razor-pass-model-to-layout – Dai Aug 03 '21 at 08:22
-
My layout is probably not orginaized proparly. I'll think about it more, thanks! – Ortal Cohen Aug 03 '21 at 08:32
-
The layout can access the Model property by default, no need for additional setup. https://stackoverflow.com/a/46783375/5519026 – LazZiya Aug 03 '21 at 08:49
-
When I declare model IEnumerable
for example at the top of layout.cshtml I recieve an unhandled exception. And as you mentiond, when I'm doing Category.xxxx I get only two options - Equals and Reference equals, but I need the id.. thank you for you answer @LazZiya – Ortal Cohen Aug 03 '21 at 09:03 -
@OrtalCohen You need to define a dedicated view-model class for that page which then contains a `List
`. You should never pass `IEnumerable – Dai Aug 03 '21 at 12:35` as a view-model object (for other reasons I won't go into).
2 Answers
1
you have to create a base view model that you will have to use for ALL your views
using Microsoft.AspNetCore.Mvc.Rendering;
public interface IBaseViewModel
{
public int CategoryId { get; set; }
public List<SelectListItem> CategoryList { get; set; }
}
public class BaseViewModel : IBaseViewModel
{
public int CategoryId { get; set; }
public List<SelectListItem> CategoryList { get; set; }
}
action
public IActionResult Index()
{
var baseViewModel=new BaseViewModel();
InitBaseViewModel(baseViewModel);
return View(baseViewModel);
}
private void InitBaseViewModel(IBaseViewModel baseViewModel)
{
//this is for test
// in the real code you can use context.Categories.Select ....
var items = new List<SelectListItem> {
new SelectListItem {Text = "Category1", Value = "1"},
new SelectListItem {Text = "Category2", Value = "2"},
new SelectListItem {Text = "Category3", Value = "3"}
};
baseViewModel.CategoryList= items;
}
layout
@model IBaseViewModel // you can omit it but I like to have it explicitly
@if(Model!=null && Model.CategoryList!=null && Model.CategoryList.Count > 0)
{
<select class="form-control" style="width:450px" asp-for="CategoryId" asp-items="CategoryList">
}
for another view you can create this action code
public IActionResult MyAction()
var myActionViewModel= new MyActionViewModel {
..... your init code
}
InitBaseViewModel(myActionViewModel);
return View(myActionViewModel)
}
public class MyActionViewModel : BaseViewModel
//or
public class MyActionViewModel : IBaseViewModel
{
public .... {get; set;}
}

Serge
- 40,935
- 4
- 18
- 45
-
"that you will have to use for ALL your views" - not necessarily - you can use optional interfaces combined with pattern-matching types in the layout file for cases when the data isn't going to appear on every page - you could also have the Layout get its data from its own injected DI service if the data isn't dependent upon the main page's viewmodel, ofc. – Dai Aug 04 '21 at 02:43
-1
You can pass directly a obj to View if you want in this way:
public virtual async Task<IActionResult> Index()
{
var model = await MethodThatRedurnModel();
return View(model);
}

tartarismo
- 194
- 1
- 10