MVC Passing Model of Tuple Item1 to Partial [duplicate] - c#

This question already has answers here:
The model item passed into the dictionary is of type .. but this dictionary requires a model item of type
(7 answers)
Closed 5 years ago.
I have a controller that takes in an instance of getbldgaddr_Result. I am trying to create a view that uses partials to put two separate viewmodels on the page. Below is the "Parent View"
#using DirectoryMVC.Models
#model Tuple<getbldgaddr_Result,getadministrators_Result>
#{
ViewBag.Title = "Central Office";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Central Office</h2>
<div class="row">
#*Display the getAddress view*#
#Html.Partial("_BuildingAddress", Model.Item1)
</div>
So above I am using Item1 from the model that is a getbldgaddr_Result. I have tried casting it to getbldgaddr_Result as well, but I get the below error.
The model item passed into the dictionary is of type 'System.Tuple`2[DirectoryMVC.Models.getbldgaddr_Result,DirectoryMVC.Models.getadministrators_Result]', but this dictionary requires a model item of type 'DirectoryMVC.Models.getbldgaddr_Result'.
The actual controller is...
public class BuildingAddressController : Controller
{
private DirectoryEntities de;
public BuildingAddressController()
{
de = new DirectoryEntities();
}
// GET: BldgAddr
public ActionResult BldgAddr(getbldgaddr_Result bldgres)
{
//getbldgaddr_Result bldgResult = de.getbldgaddr(district, bldg_no, null).FirstOrDefault();
return View(bldgres);
}
}
My guess is, I can have it take a tuple object as the parameter, but this seems counter intuitive. the Building Address, does not need anything in regards to administration.
Any thoughts?

Why send a Tuple back to the view? Just create a parent viewmodel having two child viewmodels—i.e. one for each item of the tuple—and return that from the controller instead.
Assuming a Tuple<Class1, Class2>, you could structure your viewmodel like this:
public class ParentViewModel
{
public Class1 ChildViewModel1 { get; set; }
public Class2 ChildViewModel2 { get; set; }
}
On the controller side, you'd simply do:
var parentViewModel = new ParentViewModel
{
ChildViewModel1 = Tuple.Item1,
ChildViewModel2 = Tuple.Item2
};
return View(parentViewModel);
Your view would then be:
#model ParentViewModel
// ...
#Html.Partial("_Partial1", Model.ChildViewModel1)
#Html.Partial("_Partial2", Model.ChildViewModel2)

Make sure that the Model.Item1 is not null. When the member/property you're passing in is null, MVC reverts back to the parent type.

Related

Accessing model properties in Razor-4 view

I have the following EF generated data model:
public partial class PrinterMapping
{
public string MTPrinterID { get; set; }
public string NTPrinterID { get; set; }
public string Active { get; set; }
}
I then have the following view model:
public class PrinterViewModel
{
public PrinterMapping PrinterMapping;
public Exceptions Exceptions;
public IEnumerable<PrinterMapping> Printers;
}
In my Index Action in HomeController I am passing my view model to the Index view.
private eFormsEntities db = new eFormsEntities();
public ActionResult Index()
{
PrinterViewModel printerModel = new PrinterViewModel();
printerModel.Printers = from pt in db.PrinterMapping select pt;
return View(printerModel);
}
My Index view is calling a partial view in the following manner towards the end (probably wrong):
#Html.Partial("~/Views/Home/GridView.cshtml")
My GridView.cshtml looks like:
#model AccessPrinterMapping.Models.PrinterViewModel
<h2> This is Where the Grid Will Show</h2>
#{
new WebGrid(#model.Printers, "");
}
#grid.GetHtml()
I learned about the WebGrid method from http://msdn.microsoft.com/en-us/magazine/hh288075.aspx.
My WebGrid line isn't happy at all since it doesn't recognize #model within that line.
How do I access the Printers in the view model that I passed in? Is this even possible?
Thanks very much to you all.
Theres two issues with your code.
First, you should explicitly pass your model in like this:
#Html.Partial("~/Views/Home/GridView.cshtml", Model) #* explicitly pass the model in *#
Then, because you are already in a code block in your partial view.. you don't need the # symbol.. and Model has an uppercase M.
new WebGrid(Model.Printers, "");
#model is a directive for your views/partial views. Think of it as a "configuration" command. Model is an actual property. It is the object that is passed into the view.. and is of the type you specified with the #model directive.
#{
new WebGrid(Model.Printers, "");
}
and also you have to pass your model into partial view in
#Html.Partial("~/Views/Home/GridView.cshtml")
in second parameter. I guess this call should be
#Html.Partial("~/Views/Home/GridView.cshtml", Model)

MVC 4 how pass data correctly from controller to view

I currently have a controller with a LINQ statement that i am passing data from to my view. I am trying to find a more efficient and better coding method to do this.
My home controller statement is as follows.
Var Melt
Furnace1 =
(from item in db.tbl_dppITHr
where item.ProductionHour >= StartShift && item.ProductionHour <= EndDate
select item).Sum(x => x.Furnace1Total),
ViewData["Furnace1Total"] = Melt.Furnace1;
In my view i then reference the ViewData To show this. Using
#model dynamic
Now i have quite alot of linq statements inside the Index method. And for each one i am doing the ViewData[]
I am hoping that someone can show how i pass more than one var from a controller across to a view without the ViewData or ViewBag methods. And how i would get access to this within my view.
You should create a ViewModel with all of your data needed and then pass that down to the view.
public class ViewModel
{
public List<int> Melt1 { get; set; }
public void LoadMeltProperties()
{
if (Melt1 == null)
{
Melt1 = new List<int>();
}
Melt1 = (from item in db.tbl_dppITHr
where item.ProductionHour >= StartShift && item.ProductionHour <= EndDate
select item).Sum(x => x.Furnace1Total).ToList();
}
public ViewModel Load()
{
LoadMeltProperties();
return this;
}
}
public ActionResult YourControllerAction()
{
var vm = new ViewModel().Load();
return View("ViewName", vm);
}
Then in your View you can use a strongly typed model rather than dynamic
#model ViewModel
You can then iterate over your ViewModel properties via:
foreach(var melt in Model.Melt1) {
// do what you require
}
IMHO, you should create a ViewModel an pass data using it.
Create a class
public class MyViewModel
{
public <MeltFurnace1Type> MeltFurnace1{get;set;}
}
In Action Method
public ActionResult Action()
{
MyViewModel vm = new MyViewModel();
vm.MeltFurnace1 = something;
return View("YourViewName", vm);
}
In View
#model MyViewModel
//You can access your property using
Model.MeltFurnace1
If you need to pass data actually from the controller and its data is depend on internal state or input controller parameters or has other properties of "business data" you should use Model part from MVC pattern:
Model objects are the parts of the application that implement the
logic for the application's data domain. Often, model objects retrieve
and store model state in a database. For example, a Product object
might retrieve information from a database, operate on it, and then
write updated information back to a Products table in a SQL Server
database.
You can see details here or look to the Models and Validation in ASP.NET MVC part of Microsoft tutorial.
Add model class:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string City { get; set; }
}
Pass model object to the view:
public ActionResult Index()
{
var model = GetModel();
return View(model);
}
Add strongly typed View via define model type:
#model Person
Use Model variable in your view:
#Model.City
Use models instead
var Melt
Furnace1 =
(from item in db.tbl_dppITHr
where item.ProductionHour >= StartShift && item.ProductionHour <= EndDate
select item).Sum(x => x.Furnace1Total),
return View("SomeVIew",MeltFurnace1)
In view#model "TypeOfMeltFurnace1"
You can reference model in view by property Model
If someone is still looking for options…
You also can pass object from Controller to View, if you don’t use any particular Model for the View. To pass just a single (or maybe few) parameter from the Controller to the View, you can do it inside View() Method.
In the Controller:
public async Task<IActionResult> Update(int id)
{
return View(new { Id = id });
}
Then in the View you can access your parameter like this (assuming you don’t use any other Model inside your View):
<div>
#Html.ActionLink("Link name", "ControllerMethod", "ControllerName", new { id = (int)Model.Id })
</div>
Otherwise, like already mentioned, pass your model inside View() Method.

Render multiple strongly typed partial views inside a view?

I have this Index.cshtml class:
#model ProOptInteractive.ViewModels.InvoicePageViewModel
#{
ViewBag.Title = "Index";
}
<div>#Html.Partial("ListServices", Model.Services)</div>
<div>#Html.Partial("ListProducts", Model.Products)</div>
<div>#Html.Partial("Invoice", Model.InvoiceViewModel)</div>
And this is my InvoicePageViewModel:
namespace ProOptInteractive.ViewModels
{
public class InvoicePageViewModel
{
public InvoiceViewModel InvoiceViewModel { get; set; }
public IEnumerable<Service> Services { get; set; }
public IEnumerable<Product> Products { get; set; }
}
}
The issue is that whenever I load this view, I get an error saying that I have passed the wrong model to the dictionary, and it doesn't specify which one of the partial views is causing the problem. Each partial has a different model type, one IEnumerable called Product, another IEnumerable called Service, and the Invoice partial view having a viewmodel called InvoiceViewModel.
Can anybody explain how to go about making this work? I'm a bit noob at Razor and MVC by the way.
UPDATE
I get this error message:
The model item passed into the dictionary is of type 'ProOptInteractive.ViewModels.InvoiceViewModel', but this dictionary requires a model item of type 'ProOptInteractive.ViewModels.InvoicePageViewModel'.
The error is because you have set your Invoice partial view to have a model of type InvoicePageViewModel, yet you are passing it a model of type InvoiceViewModel.
Either update your InvoiceViewModel property to be of type InvoicePageViewModel, or change the Invoice view to use a model of type InvoiceViewModel.
Error is in line <div>#Html.Partial("Invoice", Model.InvoiceViewModel)</div>
Your view Invoice is accepting model of type
InvoicePageViewModel and you are passing InvoiceViewModel
Change your code to <div>#Html.Partial("Invoice", Model)</div>
or modify your Invoice view to accept InvoiceViewModel as
#model ProOptInteractive.ViewModels.InvoiceViewModel
Invoice.cshtml likely starts with:
#model ProOptInteractive.ViewModels.InvoicePageViewModel
replace it with:
#model ProOptInteractive.ViewModels.InvoiceViewModel
You can pass model to your partial view like this:
#Html.Partial("Invoice", Model.InvoiceViewModel)
or something similar.
Model for main view:
class InvoicePageViewModel {
...
public InvoiceViewModel InvoiceViewModel { get; set; }
public IEnumerable<Service> Services { get; set; }
public IEnumerable<Product> Products { get; set; }
...
}
Then update your partial view to accept view model like this:
#model InvoiceViewModel
...
I discovered the error. It was lying in the controller method. When I called the Index view (which corresponds to the ActionResult Index method) I was returning the viewmodel InvoiceViewModel to the Index page, even though it was strongly typed to InvoicePageViewModel. I changed it to this, which works:
public ActionResult Index()
{
var invoice = InvoiceLogic.GetInvoice(this.HttpContext);
// Set up our ViewModel
var pageViewModel = new InvoicePageViewModel
{
Products = proent.Products.ToList(),
Services = proent.Services.ToList(),
InvoiceViewModel = new InvoiceViewModel
{
InvoiceItems = invoice.GetInvoiceItems(),
Clients = proent.Clients.ToList(),
InvoiceTotal = invoice.GetTotal()
}
};
// Return the view
return View(pageViewModel);
}
Thanks to everyone for all the help and suggestions.

Can't display Viewmodel from EF

I'm trying to get a agrip on MVC3 but im failing on a Viewmodel which is supposed to display a List but constantly running into an dictionary error.
The model item passed into the dictionary is of type
"marc_bew_online.ViewModels.StellenlisteViewModel", but this dictionary requires a model item of type "System.Collections.Generic.IEnumerable`1[marc_bew_online.ViewModels.StellenlisteViewModel]".
Here's the code to my repository:
public class Stellenbeschr_Repo : IStellenBeschrRepository
{
marc_bew_entities db = new marc_bew_entities();
public IEnumerable<STELLENBESCHREIBUNGEN> ListAktuell()
{
DateTime dt1 = new DateTime(2011, 1, 1);
var stelleBeschreibungAbDatum = (from stellebeschreibung in db.STELLENBESCHREIBUNGEN
where DateTime.Compare((DateTime)stellebeschreibung.VON_DATUM, dt1) >= 0
select stellebeschreibung).ToList();
return stelleBeschreibungAbDatum;
}
}
Controller + ViewModel:
private IStellenBeschrRepository _repository;
public Default1Controller()
: this(new Stellenbeschr_Repo())
{
}
public Default1Controller(IStellenBeschrRepository repository)
{
_repository = repository;
}
#endregion
public ActionResult Index()
{
return View(_repository.ListAktuell());
}
public ActionResult Stellenliste()
{
var viewModels = new StellenlisteViewModel { StellenListe = _repository.ListAktuell() };
return View(viewModels);
}
public class StellenlisteViewModel
{
public IEnumerable<STELLENBESCHREIBUNGEN> StellenListe { get; set; }
}
Viewpage extract:
#foreach(var item in Model.StellenListe)
{
<tr>
<td>
#Html.Display(item.STELLENBESCHREIBUNG);
</td>
</tr>
}
The Viewpage is currently displaying ";" for every item the LINQ expression has found
I just cant find a solution to get the list displayed in my view.
The problem is most likely your view code.
Make sure your model is declared as:
#model StellenlisteViewModel
and not:
#model IEnumerable<StellenlisteViewModel>
EDIT
From the sounds of it you may be confusing a few things.
Your page will have a single view model. On this view model will be a list of STELLENBESCHREIBUNGEN which you are wanting to display.
To do this, first make sure your view page accepts a single view model:
#model StellenlisteViewModel
Secondly, you want to add a ToList() call in your repository:
var stelleBeschreibungAbDatum = (from stellebeschreibung in db.STELLENBESCHREIBUNGEN
where DateTime.Compare((DateTime)stellebeschreibung.VON_DATUM, dt1) >= 0
select stellebeschreibung).ToList();
Thirdly, your view page will look something like this:
#model StellenlisteViewModel
foreach(var item in Model.StellenListe)
{
// output each individual item to the page
// here you can access the individual properties on your STELLENBESCHREIBUNGEN, e.g.:
<span>#item.Description</span>
}
Sorry, I don't have access to MVC3 currently, so I can't check the syntax.
EDIT#2
You are using Display incorrectly. You may wish to check the documentation for it.
It is also like DisplayFor() is what you are looking for.
Your are returning a single item rather than a list of items. You either need to declare the view to take marc_bew_online.ViewModels.StellenlisteViewModel (rather than an IEnumerable) or return a list of the viewmodel items.

Passing object to view error

I am getting this error when trying to pass my object to the view. I am new to MVC so please forgive me.
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[<>f__AnonymousType13[System.Int32,System.String,System.Nullable1[System.DateTime]]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable1[MvcApplication1.Models.storageProperty]'
I am trying to pass a list for a table that will show objects from the storageProperty table with the last date (if there is one) from the expenses table. Most properties have had at least one expense audit, some have had many, and others have had none.
Here is the code from the controller:
var viewModel = db.storageProperties.Select(s => new
{
s.storagePropertyId,
s.BuildName,
latestExpenseSurvey = (DateTime?)s.expenses.Max(e => e.expenseDate)
}).ToList();
return View(viewModel);
}
and the #model statement in the view calls for a storageproperty object. I am using mvc3 with the entity framework. It appears obvious that I cannot pass this list object in place of the storageproperty object, but I can't figure out what to do instead, how should I do this?
Thanks in advance.
Never pass anonymous objects to views. You should always pass view models.
So as always in an ASP.NET MVC application you start by defining a view model which will reflect the requirements of your view:
public class MyViewModel
{
public int StoragePropertyId { get; set; }
public string BuildName { get; set; }
public DateTime? latestExpenseSurvey { get; set; }
}
Then in your controller return an IEnumerable<MyViewModel>:
public ActionResult Index()
{
var viewModel = db.storageProperties.Select(s => new MyViewModel
{
StoragePropertyId = s.storagePropertyId,
BuildName = s.BuildName,
LatestExpenseSurvey = (DateTime?)s.expenses.Max(e => e.expenseDate)
}).ToList();
return View(viewModel);
}
and finally strongly type your view to a collection of this view model:
#model IEnumerable<MyViewModel>
<div>
#Html.EditorForModel()
</div>
Your Linq query projects to an anonymous type. You need to create a named type for this projection in order to refer to it from the view.

Categories