1

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!

  • "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` as a view-model object (for other reasons I won't go into). – Dai Aug 03 '21 at 12:35

2 Answers2

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