Passing multiple dropdownlist items between pages - asp.net

I use Asp.Net MVC. I have 4 dropdownlist in my page.
1- Car Company (40 items)
2- Model (30 items)
3- Year (20 items)
4- Engine(20 items)
when user select this item go to details page.In details page i want fill ddl and select item user was selected.
I have some ideas about this but i am not sure its right way.
1- post dropdownlist to controller and return back to detail page
2- write dropdownlist to cookie
or any other ideas ?

Create a view model like this
public class FilterVM
{
public List<SelectListItem> Makes{ set;get;}
public int SelectedMake { set;get;}
public List<SelectListItem> Models { set;get;}
public int SelectedModel { set;get;}
public List<SelectListItem> Years{ set;get;}
public int SelectedYear { set;get;}
public List<SelectListItem> Engines{ set;get;}
public int SelectedEngine { set;get;}
public FilterVM()
{
Makes=new List<SelectListItem>();
Models=new List<SelectListItem>();
Years=new List<SelectListItem>();.
Engines=new List<SelectListItem>();
}
}
Now in your GET action
public ActionResult Search()
{
var vm=new FilterVM();
vm.Makes=LoadMakesFromSomewhere();
return View(vm);
}
private List<SelectListItem> LoadMakesFromSomewhere()
{
var lst=new List<SelectListItem>();
lst.Add(new SelectListItem { Value="1", Text="Ford"});
lst.Add(new SelectListItem { Value="2", Text="Honda"});
return lst;
}
And in your view which is strongly typed to your FilterVM. We will write some javascript to handle the change event of the dropdowns so that it will read the selected item value and send an ajax request to get the content for the next dropdown .
#model FilterVM
#using(Html.BeginForm())
{
<label>Make</label>
#Html.DropDownListFor(s=>s.SelectedMake,Model.Makes,"Select")
<label>Make</label>
#Html.DropDownListFor(s=>s.SelectedModel,Model.Models,"Select")
<label>Make</label>
#Html.DropDownListFor(s=>s.SelectedYear,Model.Years,"Select")
<label>Make</label>
#Html.DropDownListFor(s=>s.SelectedEngine,Model.Engines,"Select")
<input type="submit" />
}
<script type="text/javascript">
$(function(){
//code to load Models dropdown when user selects Make
$("#SelectedMake").change(function(){
var items="";
$.getJSON("#Url.Action("GetModels","Car")/"+$(this).val(),function(res){
$.each(function(index,item){
items+="<option value='"+item.ID+'>"+item.Name+"</option>";
});
$("#SelectedModel").html(items);
});
});
//Write other dropdown filling code like above
});
</script>
Now you should have a GetModels method which accepts the Selected Make's ID and returns the models in JSON format.
public ActionResult GetModels(int id)
{
var modelList=repositary.GetModelsFromMakeID(id);
return Json(modelList,JsonRequestBehaviour.AllowGet);
}
Your JSON which you are returning should look something like this (and ID and Name in each item.
[
{
"ID": 4,
"Name": "Accord"
},
{
"ID": 5,
"Name": "CRV"
}
]
Write the change event handler for other dropdowns also. Finally when the user posts the form, you can check the SelectedMake,SelectedModel,SelectedYear property values.
[HttpPost]
public ActionResult Search(FilterVM model)
{
check for model.SelectedMake, model.SelectedYear etc..
//to do : Get result and show in a view/redirect.
}

You can use ViewBag,ViewData or TempData object to hold such values

Related

Populate a select list ASP.NET Core MVC

I'm busy with an ASP.NET Core MVC application, and I'm trying to populate a drop down list. I've created a view model and I have added a method to my StoresController that returns a list of stores that I want to display in a dropdown. I've been working off some online tutorials as I'm very new to asp.
View model:
public class StoreListViewModel
{
public List<StoreList> StoreList { get; set; } = new List<StoreList>();
}
public class StoreList
{
public string StoreId { get; set; } = null!;
public string StoreName { get; set; } = null!;
}
StoresController:
public IActionResult LoadStoreList()
{
if (ModelState.IsValid)
{
var storeList = new StoreListViewModel().StoreList.Select
(x => new SelectListItem { Value = x.StoreId, Text = x.StoreName }).ToList();
ViewBag.Stores = storeList;
}
return NotFound();
}
I'm trying to use ViewBag to call my LoadStoreList() method.
<select name="storeList" class="form-control" asp-items="#(new SelectList(ViewBag.Stores, "Value", "Text"))"></select>
When I load my page I get the following error
Value cannot be null. (Parameter 'items')
The page I need the dropdown list on is my CreateUser.cshtml which is bound to my UserModel and has a UsersController. The method I have created for listing the stores is in my StoresController which is bound to my StoresModel. So I'm not sure if that's causing the issue.
I've been battling with this for days, if someone could help me get this working or show me a better method, that would be great.
*Edit
The UserIndex() method is the first method that fires when my users page opens, do I call the LoadStoreList() method from there ?
UserController
public async Task<IActionResult> UsersIndex()
{
return _context.UsersView != null ?
View(await _context.UsersView.ToListAsync()) :
Problem("Entity set 'ApplicationDbContext.Users' is null.");
}
I'm trying to use ViewBag to call my LoadStoreList() method.
ViewBag cannot be used to call any method. You just need set value for ViewBag in the method which renders your show dropdownlist's page.
From your description, you said the page you need the dropdown list on is CreateUser.cshtml. Assume that you render the CreateUser.cshtml page by using CreateUser action.
CreateUser.cshtml:
<select name="storeList" class="form-control" asp-items="#(new SelectList(ViewBag.Stores, "Value", "Text"))"></select>
Controller:
public class YourController : Controller
{
private readonly YourDbcontext _context;
public YourController(YourDbcontext context)
{
_context = context;
}
[HttpGet]
public IActionResult CreateUser()
{
var storeList = _context.StoreLists.Select
(x => new SelectListItem { Value = x.StoreId , Text = x.StoreName }).ToList();
ViewBag.Stores = storeList;
return View();
}
}
YourDbcontext should be something like:
public class YourDbcontext: DbContext
{
public YourDbcontext(DbContextOptions<MvcProjContext> options)
: base(options)
{
}
public DbSet<StoreList> StoreLists{ get; set; }
}
Dont use viewbag for storing list data. Make your view page model including List, for example:
public class UserCreationViewModel{
public int Id{ get; set; }
public string Name { get; set; }
// Any other properties....
public List<StoreList> StoreList { get; set; }
}
in your controller YourController:
[HttpGet]
public IActionResult CreateUser()
{
var storeList = new StoreListViewModel().StoreList.Select
(x => new SelectListItem { Value = x.StoreId, Text = x.StoreName }).ToList();
UserCreationViewModel model=new UserCreationViewModel{
StoreList = storeList
};
return View("createUserViewName", model);
}
in createUserViewName:
#Html.DropDownList("StoreId", new SelectList(Model.StoreList, "StoreId", "StoreName"), "Select", new { #class = "form-control" })
or
<select class="form-control" asp-for="#Model.StoreId" asp-items="#(new SelectList(Model.StoreList, "StoreId", "StoreName"))">
<option value="-1">Select</option>
</select>

Problem with checkbox helper returning null values ASP.NET MVC

Model:
public class ItemModel
{
public bool IsChecked { get; set; }
}
ViewModel:
public class CategoryItemViewModel
{
public List<ItemModel> Item { get; set; }
}
Index Controller:
public List<ItemModel> GetItemModel()
{
//Get fie path
var ItemFile = Server.MapPath("~/App_Data/Items.txt");
//Read from the Categories.txt file and display the contents in the List view
List<ItemModel> item = new List<ItemModel>();
//Read the contents of Category.txt file
string txtData = System.IO.File.ReadAllText(ItemFile);
//Execute a loop over the rows.
foreach (string row in txtData.Split('\n'))
{
if (!string.IsNullOrEmpty(row))
{
item.Add(new ItemModel
{
IsChecked = Convert.ToBoolean(row.Split(',')[0])
});
}
}
return item;
}
The code above is basically reading items in a text file and then setting them to the model.
I am having an issue when wanting to change the checked value of a checkbox, as the actual checkbox is returning a null value when I try check it, Problem code is below.
Controller to add a new line item with a checkbox:
[HttpPost]
public ActionResult Item(bool ItemCheck)
{
//Get file path of Categories.txt
var ItemFile = Server.MapPath("~/App_Data/Items.txt");
var ItemData = ItemCheck + Environment.NewLine;
System.IO.File.AppendAllText(ItemFile, ItemData);
return View();
}
bool ItemCheck is returning a null value.
Index View code:
foreach (var item in Model.Item)
{
#using (Html.BeginForm("Item", "Item", FormMethod.Post))
{
#Html.CheckBoxFor(ItemModel => ItemModel.IsChecked)
}
}
It is saying that ItemModel does not contain a definition for IsChecked.
This could be due to the following reasons
Referring wrong namespace for model, ItemModel. To ensure that you are using correct model use #model yourNamespace.ItemModel
Build issue. clean and build the project.

ASP.NET MVC ListBox does not show the selected list items

I am in a big trouble. I read 4 stackoverflow question and one blogpost. I have tried 5 different approach to view the selected items in a multiple selectlist.
I have no success.
The multiple selectlist is generated, but it does not select the items. I have no more idea.
Model:
public class EditableModel
{
public IList<Company> SelectedCompanies { get; set; }
public IList<SelectListItem> SelectListCompanies { get; set; }
}
Controller:
public ActionResult Edit(int id)
{
var service = _serviceDAL.GetEditableModel(id);
if (service!= null)
{
service.SelectListCompanies = GetSelectListCompanies(service.SelectedCompanies);
return View(service);
}
}
private IList<SelectListItem> GetSelectListCompanies(IList<Company> selectedCompanies)
{
List<SelectListItem> items = new List<SelectListItem>();
foreach (Companycompany in _companyService.GetCompanies())
{
items.Add(new SelectListItem
{
Value = company.CompanyId.ToString(),
Text = company.Name,
Selected = selectedCompanies.Any(x => x.CompanyId == company.CompanyId)
});
}
return items;
}
View
#Html.ListBox("SelectedCompanies", Model.SelectListCompanies, Model.SelectedCompanies.Select(x => x.CompanyId.ToString()) )
And nothing. The items in the select list is not selected...
I have tried this Multiselect, the same result, or this one as the current solution.
You cannot bind a <select multiple> to a collection of complex objects. It binds to, and posts back an array of simple values (the values of the selected options).
Your SelectedCompanies property needs to be IEnumerable<int> (assuming the CompanyId of Company is also int). Note also the Selected property of SelectListItem is ignored when binding to a property.
Your also using the same collection for the selected Companies and the list of all Companies which makes no sense. Your SelectListCompanies should be generated from your table of Company.
Model
public class MyViewModel
{
public IEnumerable<int> SelectedCompanies { get; set; }
public IEnumerable<SelectListItem> SelectListCompanies { get; set; }
}
Base on your current code for EditableModel, your code should be
public ActionResult Edit(int id)
{
var service = _serviceDAL.GetEditableModel(id);
....
MyViewModel model = new MyViewModel
{
SelectedCompanies = service.SelectedCompanies.Select(x => x.CompanyId),
SelectListCompanies = GetSelectListCompanies()
};
return View(model);
private IEnumerable<SelectListItem> GetSelectListCompanies()
{
var all companies = ... // call method to get all Companies
return companies.Select(x => new SelectListItem
{
Value = x.CompanyId.ToString(),
Text = x.Name
});
}
However, it look like you should be modifying your EditableModel and the GetEditableModel() code to return the correct data in the first place.

ASP.NET MVC Razor post form containing partial view

I have a ASP.NET view containing a partial view. I reuse the partial view in several other views with different models. The important part of the view looks like this:
#Html.EditorFor(model => model.Title)
//TextArea inserted by partial view
#Html.TextArea("content", new { id = "mycontent" })
//Submit button here
The corresponding model:
public class Entry {
public int ID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
And controller method:
public ActionResult Create([Bind(Include = "ID,Title,Content")] Entry entry) {
if (ModelState.IsValid) {
db.Entries.Add(entry);
db.SaveChanges();
...
}
}
How can I submit this form posting the content of the TextArea to the "Content" of the model without using code like #Html.TextArea(model => model.Content)? Do I have to use AJAX?
In your partial view instead of using
#Html.TextArea("content", new { id = "mycontent" })
use this :
#Html.TextArea("Content", new { id = "mycontent" })
and without using #Html.TextAreaFor() data will be bind to model property Content and you can get its value in Controller.

ASP.NET MVC passing query result from controller to view

How to print the result of query in View page for ASP.NET MVC?
My code is:
public ActionResult Index()
{
var list = from m in db.MenuTables
select m.MenuName;
return View(list);
}
Now what should i write to print the result of this query in View Page?
Personally, I would get in the habit of having ViewModels and then strongly typing your View, to that model.
The model will expose ONLY THE DATA you want to display. Nothing more, nothing less. So let's assume you want to display the Name, Price and some other meta data.
Pseudo-code:
//View Model
public class MenuItem
{
public string Name { get; set; }
public decimal Price { get; set; }
public bool IsVegetarian { get; set; ]
}
public class IndexViewModel
{
public IList<MenuItem> MenuItems { get; set; }
public string MaybeSomeMessage { get; set; }
}
//in Controller
public ActionResult Index()
{
// This gets the menu items from your db, or cache or whatever.
var menuItemsFromDb = GetMenuItems();
// Let's start populating the view model.
IndexViewModel model = new IndexViewModel();
// Project the results to your model.
IList<MenuItems> menuItems = null;
if (menuItemsFromDb != null)
{
model.MenuItems = (from menuItem in menuItemsFromDb
select new MenuItem() {
Name = menuItem.Name,
Price = menuItem.Price,
IsVegetarian = menuItem.IsVegetarian
}).ToList();
}
// Anything else...
model.MaybeSomeMessage = "Hi There!";
return View(model);
}
//in View
#model IndexViewModel
<h3>#Model.MaybeSomeMessage</h3>
<ul>
#foreach(var item in Model.MenuItems)
{
<li>#item.Name - $ #item.Price</li>
}
</ul>
etc..
Note I've skipped some error checking, etc.
The point: only pass what you need.
At first, you may think this is much more code than is necessary. The best answer I can suggest to that thought, is that in the long run, you'll thank yourself for getting in the habit of this because the view should only ever know about the exact data it requires.
Nothing more, nothing less. Sending the least amount of data means you have a very light and simple view which will make your support/debugging much better. Next, you'll be able to unit test your controllers with a lot more intelligence and smarts, when you get to that.
Assuming that list is an IEnumerable of strings (i.e. that MenuName is a string).
In your view, accept the model IEnumerable<string>
#model IEnumerable<string>
and then enumerate it
#foreach( string s in Model )
{
<div>
#s
</div>
}
The first thing you want to do is call ToList() or else you could possibly be executing the same SQL query multiple times.
public ActionResult Index()
{
var list = (from m in db.MenuTables
select m.MenuName).ToList();
return View(list);
}
Secondly, I wouldn't just pass up a full list like that. You should create a ViewModel. That will allow you to pass up more data later on with a smaller effort.
public ActionResult Index()
{
var model = new IndexModel();
model.Tables = db.MenuTables.ToList();
model.AnotherValue = "MENUS";
return View(model);
}
Now we are on the view, you will need to set the model and iterate the table.
#model IndexModel
<h3>#Model.AnotherValue</h3>
<ul>
#foreach( var table in Model.Tables) {
<li>#table.Name<li>
}
</ul>
public ActionResult Index()
{
var list = from m in db.MenuTables
select m.MenuName;
return View(list);
}
//In View
#model IEnumerable<ProjectName.models.MenuTables>
#foreach(var item in Model)
{
#item.Field_Name
}

Resources