How to set two values in View() - c#

How can set several objects in view?
public ActionResult Index()
{
var shops = this.context.shops.Select(q => new { q.id, q.name }).ToList();
var bikes = this.context.bikes.Select(q => new { q.id, q.name }).ToList();
return View(shops, bikes); // How to set two values in View()?
}
And parse in View()
#foreach (var r in Model.bikes)
{
<b>#r.name</b>
}

One way is to create a strong typed view model that contains both shops and bikes. Other option could be creating a Tuple and passing as a model to view. I would go first option.
Tuple
var tuple = new Tuple<shop, bike>(new shop(),new bike());
In you view
#Model Tuple<shop,bike>

You need create ViewModel
public class shopsAndbikes
{
public List<shop> shops {get;set;}
public List<bike> bikes {get;set;}
}
public ActionResult Index()
{
shopsAndbikes vm = new shopsAndbikes ()
{
var shops = this.context.shops.Select(q => new { q.id, q.name }).ToList();
var bikes = this.context.bikes.Select(q => new { q.id, q.name }).ToList();
}
return View(vm);
}
View:
#model shopsAndbikes
#foreach (var r in Model.bikes)
{
<b>#r.name</b>
}
#foreach (var r in Model.shops)
{
<b>#r.name</b>
}

Your Model-class should contain properties for both shops and bikes. That is if you use a strongly typed view, it looks that way. Otherwise you could add things to the ViewBag for use in the view.

Related

MVC Viewmodel partially null

My View is bound to this model
public class HomepageViewModel
{
public HomepageViewModel()
{
Regions = new List<TMRegion>();
}
public List<TMRegion> Regions { get; set; }
public int SelectedRegion { get; set; }
public SelectList SelectListRegions
{
get
{
List<SelectListItem> items = new List<SelectListItem>();
foreach (var tmRegion in Regions)
{
items.Add(new SelectListItem()
{
Value = tmRegion.Value.ToString(),
Text = tmRegion.Display
});
}
return new SelectList(items);
}
}
}
My view is like this -
#model ProSell.Admin.Models.ViewModels.HomepageViewModel
#using (Html.BeginForm("Index", "Search", FormMethod.Post, new { viewModel = Model }))
{
#Html.HiddenFor(m=>m.Regions)
#Html.DropDownListFor(model => model.SelectedRegion, Model.SelectListRegions.Items as List<SelectListItem>, "Select a region")
<input type="submit"/>
}
My controller populates Regions like this -
// GET: Search
public async Task<ViewResult> Index(HomepageViewModel viewModel)
{
if (viewModel.Regions.Count == 0)
{
viewModel = new HomepageViewModel();
JavaScriptSerializer js = new JavaScriptSerializer();
viewModel.Regions =
js.Deserialize<TMRegion[]>(
await _ApiConsumer.ExecuteGetMethod("myurlinhere"))
.ToList();
}
return View(viewModel);
}
The Drop down is populated in the view. When i select a region and submit the HomepageViewModel has the SelectedRegion correctly set to whatever id was selected, but the collection of Regions is empty.
How do I maintain the list in the model on submit?
Generally you should attempt to reduce the amount of data the client sends back to the server especially with collections since it's far more efficient for the server to make a database call to retrieve the collection than have it passed back with the form data.
As Stephen said you can re-populate the collections Regions from your controller or if you need it when returning the view due to ModelState error you can add the population code into your model's constructor.
Also you can clean up your collection property like this:
public IEnumerable<SelectListItem> SelectListRegions
{
get
{
return Regions.Select(x => new SelectListItem
{
Text = x.Display,
Value = x.Value.ToString()
});
}
}
and in your View:
#Html.DropDownListFor(model => model.SelectedRegion, Model.SelectListRegions, "Select a region")

Bind a Linq Lambda Select Many from Controller to view in MVC4? What are the Best ways to return in view

I am new to MVC by Linq. When I am working with Console application its working fine.
When i shift to Mvc Architecture, passing the values from controller to view i am getting error as
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[<>f__AnonymousType22[System.String,System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[MvcApplication2.Models.Teams]'.
I know i am passing Objects as stringName,String and its expecting 'System.Collections.Generic.IEnumerable how to resolve this kind of issues
This Scenario happen for Multiple groupby and Selectmany in Linq .how to pass the value and get into bind for View . what is the Best approach.
i have put a foreach in Controller and return or else do the foreach iterations in view for selectMany,Groupby,Lookup etc.
Model
public Class Product
{
public string CategoryName {get; set; }
public int Productid { get; set; }
public List<String> Productname { get; set; }
public static List<Product> GetAllProductName()
{
var ListofProducts = new List<Product>
{
new Product { CategoryName = "Choclateid", Productid = 1, Productname = new List<string> { "DairyMilkshots", "DairyMilk Silk", "DairyMilkFruitsNuts" }},
new Product { CategoryName = "Vegetables", Productid = 2, Productname = new List<string> { "Tomoto", "Pototo", "Onion"}},
new Product { CategoryName = "Fruits", Productid = 3, Productname = new List<string> {"Apple", "Orange", "Strawberry"}},
};
return ListofProducts;
}
}
Controller
public ActionResult Home()
{
var ny = Product.GetAllTeamMembers()
.SelectMany(x => x.Productname, (category, withProductlist) =>
new { cat = category.CategoryName, PN = Productname })
.ToList();
return View(ny);
}
View
#model IEnumerable< MvcApplication2.Models.Product>
#{
ViewBag.Title = "Selectmany";
}
<h2>#ViewBag.Message</h2>
<p>
To learn more about ASP.NET MVC visit http://asp.net/mvc.
</p>
#{
foreach(var k in Model)
{
#K.CategoryName<br/>
#k.Productname<br/>
}
}
Console
var ny = Product.GetAllTeamMembers().SelectMany(x => x.Productname,
(category, withProductlist) =>
new { cat = category.CategoryName, PN = Productname };
foreach(var n in ny)
{
Console.WriteLine(n.cat + "\t" + "-" + n.PN);
}
Output
Choclate -DairyMilkshots DairyMilk Silk DairyMilkFruitsNuts
Vegetables - Tomoto,Pototo,Onion
etc
The problem is that your view is set to handle an explicit type:
#model IEnumerable< MvcApplication2.Models.Product>
But the LINQ method does not return a type of Product. You're actually returning an anonymous type with this portion of the LINQ statement:
(category, withProductlist) => new { cat = category.CategoryName, PN = Productname })
The new keyword helps identify that. Your console application works b/c the anynomous object has properties for PN and CategoryName but does not explicitly need a certain type.
Does that make sense?
As has been suggested, you should just pass in the values from the call Product.GetAllTeamMembers() to your view. Your view should then assign the values for the type. For example,
Controller:
public ActionResult Home()
{
var ny = Product.GetAllTeamMembers();
return view(ny);
}
View
#model IEnumerable< MvcApplication2.Models.Product>
#{
foreach(var k in Model)
{
#K.CategoryName<br/>
#k.Productname<br/>
}
}
}
EDIT
The best way to do what you want is to create a view model to contain the flattened information. This gives you the shape of the data as you want and allows you to use the model in your controller.
New View Model
public class ProductViewModel
{
public string CategoryName { get; set; }
public string ProductName { get; set; }
}
Controller Logic
var ny = Product.GetAllProductName()
.SelectMany(x => x.Productname, (category, withProductlist) =>
new ProductViewModel
{
CategoryName = category.CategoryName,
ProductName = withProductlist
});
The View
#model IEnumerable<ProductViewModel>
The important part is in the select many clause, you're casting to a known type (ProductViewModel) instead of an anonymous type.
Just a fetch a list of Product and take it to view then use the joined table like Product.Cateogry and loop in inner table.

ASP.Net Passing ViewModel to View (Underlying entity framework)

I am having problems passing a ViewModel into a view.
My ViewModel:
namespace ImpactDBASPNet.Models
{
public class ComputerInfoViewModel
{
public List<string> CompanyList { get; set; }
public tbl_computerinfo entitymodeleffort { get; set; }
}
}
Controller:
public ActionResult Index()
{
var tbl_computerinfo = db.tbl_computerinfo.Include(t => t.tbl_equipment);
tbl_computerinfo = tbl_computerinfo.Where(c => c.Company == "Test Company");
List<string> companylist = new List<string>();
companylist.Add("Hello1");
companylist.Add("hello2");
ComputerInfoViewModel model = new ComputerInfoViewModel();
model.CompanyList = companylist;
model.entitymodeleffort = tbl_computerinfo;
return View(model);
}
I'm doing this primarily because I need to pass a list for a dropdownlist in my view, so I need to pass in the entity framework model AND the list. The error I am getting is:
Error 1 Cannot implicitly convert type 'System.Linq.IQueryable<ImpactDBASPNet.Models.tbl_computerinfo>' to 'ImpactDBASPNet.Models.tbl_computerinfo'. An explicit conversion exists (are you missing a cast?) c:\impactdbaspnet\controllers\tbl_computerinfocontroller.cs 31 39 ImpactPortal
Property entitymodeleffort is typeof tbl_computerinfo but you assigning IEnumerable<tbl_computerinfo> to it, resulting in the error. You need to use FirstOrDefault() (or one of the variants - Single() etc.) that returns a single tbl_computerinfo object.
Change the code to
public ActionResult Index()
{
var tbl_computerinfo = db.tbl_computerinfo
.Include(t => t.tbl_equipment)
.Where(c => c.Company == "Test Company")
.FirstOrDefault();
List<string> companylist = new List<string>() { "Hello1", "Hello2" }; // save a few lines of code
ComputerInfoViewModel model = new ComputerInfoViewModel();
model.CompanyList = companylist;
model.entitymodeleffort = tbl_computerinfo;
return View(model);
}
Side note: Since companylist is used for a dropdownlist, you can make the property SelectList
public SelectList CompanyList { get; set; }
and
model.CompanyList = new SelectList(companylist);
and in the view
#Html.DropDownListFor(m => m.entitymodeleffort.SomeProperty, Model.CompanyList, ...)

NullReferenceException was unhandled asp.net entity framework

I'm new to asp.net mvc and I'm doing this exercise for myself.
I created an edmx from Northwind Database.
I created a controller:
public ActionResult Index(int id)
{
var model = new IndexViewModel();
using (var db = new ProductDB())
{
model.Products = from p in db.Products
orderby p.ProductName
select new IndexViewModel.InfoProduct
{
ProductName = p.ProductName,
QuantityPerUnit = p.QuantityPerUnit,
UnitPrice = p.UnitPrice
};
}
return View();
}
...the view:
#model aspTest.Models.IndexViewModel
#{
Layout = null;
}
...
<div> <ul>
#foreach (var p in Model.Products){
<li>#p.ProductName</li>
}
</ul>
</div>
...and the ViewModel:
public class IndexViewModel
{
public IEnumerable<InfoProduct> Products { get; set; }
public class InfoProduct
{
public string ProductName { get; set; }
}
}
But this error keeps on appearing in this part:
#foreach (var p in Model.Products){#p.ProductName
Sorry, I know this might be noobish to most of you.
You are declaring in your model that it will work with the IndexViewModel class as:
#model aspTest.Models.IndexViewModel
but you are sending nothing to the View from Controller as :
return View();
Try using:
return View(model);
The error is quite true, you are trying to iterate on properties (Products) of an object (IndexViewModel) which you don't provide.
Besides the fact that you return no ViewModel to your view and shout use return View(model); there is something else fishy with your code:
public class InfoProduct
{
public string ProductName { get; set; }
}
Your class InfoProduct only contains a Productname, yet you also assign a Quantity and Price property in your select clause, this won't compile.
model.Products = from p in db.Products
orderby p.ProductName
select new IndexViewModel.InfoProduct
{
ProductName = p.ProductName,
};
Lastly, materialize your data using .ToList()
public ActionResult Index(int id)
{
var model = new IndexViewModel();
using (var db = new ProductDB())
{
model.Products = (from p in db.Products
orderby p.ProductName
select new IndexViewModel.InfoProduct
{
ProductName = p.ProductName,
}).ToList();
return View(model);
}
}

A better way than using ViewBag

I obtain a list of data through docs which has a list of every single department and function the currently logged in user has access to. I need to populate a distinct list of Departments for a DropDownList and a distinct list of Functions for a DropDownList on the View page. I am currently not even using docs to do this but a different LINQ query to acheive this. Is there a way I can use the current model I am passing?
var docs = (Long LINQ query that joins in four different tables and returns a model)
ViewBag.DepartmentList = db.Department.Where(x => (x.name != null)).Select(s => new SelectListItem
{
Value = s.name,
Text = s.name
})
.Distinct(); // Fill the viewbag with a unique list of 'Department's from the table.
ViewBag.FunctionList = db.Function.Where(x => (x.name != null)).Select(s => new SelectListItem
{
Value = s.name,
Text = s.name
})
.Distinct(); // Fill the viewbag with a unique list of 'Function's from the table.
Code on View: (Strongly Typed Model)
#model IEnumerable<DB.Models.MasterList>
#Html.DropDownList("DepartmentList", "Select a Department")
#Html.DropDownList("FunctionList", "Select a Function")
Define a model that will be used in your view.
public class MyViewModel
{
public string SelectedDepartment { get; set; }
public string SelectedFunction { get; set; }
public IEnumerable<SelectListItem> Departments { get; set; }
public IEnumerable<SelectListItem> Functions { get; set; }
// Your old model
public IEnumerable<MasterList> Master { get; set;}
}
In your controller, populate these collections and return your model to view.
[HttpGet]
public ActionResult ActionMethodName()
{
var model = new MyViewModel();
model.Departments = db.Departments.Where(x => (x.name != null))
.Select(s => new SelectListItem
{
Value = s.name,
Text = s.name
})
.Distinct();
model.Functions = db.Functions.Where(x => (x.name != null))
.Select(s => new SelectListItem
{
Value = s.name,
Text = s.name
})
.Distinct();
return View(model);
}
Inside your view, use strongly typed html helpers.
#model MyViewModel
#Html.DropDownListFor(m => m.SelectedDepartment, Model.Departments)
#Html.DropDownListFor(m => m.SelectedFunction, Model.Functions)
When you post back your form to server, SelectedDepartment and SelectedFunction should have the values selected in your view.
You could create a ViewModel and put all this data in this ViewModel:
ViewModel
public class MyViewModel{
public object DepartmentList{get; set;}
public object FunctionList{get; set;}
public IEnumerable<MasterList> Master {get; set;}
}
Controller
var docs = (Long LINQ query that joins in four different tables and returns a model)
MyViewModel vm = new MyViewModel();
vm.Master = docs; // I guess docs is a list of Masterlist
vm.DepartmentList = db.Department.Where(x => (x.name != null)).Select(s => new SelectListItem
{
Value = s.name,
Text = s.name
})
.Distinct(); // Fill the viewbag with a unique list of 'Department's from the table.
vm.FunctionList = db.Function.Where(x => (x.name != null)).Select(s => new SelectListItem
{
Value = s.name,
Text = s.name
})
.Distinct(); // Fill the viewbag with a unique list of 'Function's from the table.
return View(vm);
View
#model MyViewModel
#Html.DropDownList("DepartmentList", "Select a Department")
#Html.DropDownList("FunctionList", "Select a Function")
You can always create a ViewModel class for your view and put all the necessary view information in it.
You can use a framework like AutoMapper (https://github.com/AutoMapper/AutoMapper) to help you with the mapping between your database model and your view model (I belive it's best that the view won't know the database model at all), and beside the model information you can also add those lists (That's what I do, I have a property for the entity, and properties for those kinds of lists).
If you need this information in many of your views you can always create a BaseViewModel and polpulate that information in a BaseController.

Categories