Queries realted to Dropdown list in MVC - asp.net-mvc

I am a new to ASP.NET MVC, I am developing an application. I want to bind the data in the drop down list in create view.
How to bind the data in the drop down? I have go through many question and answers here...
I have seen usually everyone suggested to use List<SelectListItem> what is its purpose?
Do I need to use ViewModel while binding the data to drop down list?
Can I get simple example where data get bind in the dropdown using viewbag?
I have created a list in controller
List<string> items = new List<string>();
and I want to pass this list to view using viewbag and simply want to bind to drop down list.
How to do this ?

I'd suggest using a ViewModel as it makes interaction with user input so much easier. Here's an example of how you might bind data from your ViewModel to a drop down in your View. First, the ViewModel:
public class CrowdViewModel
{
public string SelectedPerson { get; set;}
public IEnumerable<SelectListItem> People { get; set; }
}
So yes, you're right - use a collection of SelectListItems. I'm guessing in your case, the SelectListItem's Value and Text property will be the same. You could turn your List into IEnumerable like this:
[HttpGet]
public ActionResult Home()
{
// get your list of strings somehow
// ...
var viewModel = new CrowdViewModel
{
People = items.Select(x => new SelectListItem { Text = x, Value = x })
}
return View(viewModel);
}
Now you need to bind that ViewModel's property to the DropDown on your view. If you're using the Razor ViewEngine, the code will look something like this:
#model MyApp.ViewModels.CrowdViewModel
#using (Html.BeginForm())
{
#Html.DropDownListFor(model => model.SelectedPerson, Model.People)
}
Now when you post that form, MVC will bind the selected value to the ViewModel's SelectedPerson property!
[HttpPost]
public ActionResult Home(CrowdViewModel viewModel)
{
// viewModel.SelectedPerson == whatever the user selected
// ...
}
Easy as that!
Update:
If you really want to use the ViewBag (don't do it), you can pass your list through from your Controller action like so:
[HttpGet]
public ActionResult Home()
{
ViewBag.People = new List<string> { "Bob", "Harry", "John" };
return View();
}
And then create a SelectList on your View:
#Html.DropDownList("SelectedPerson", new SelectList(ViewBag.People, Model))

Related

MVC: Best way to populate Html .DropDownList

I'm looking for a sound philosophy for bringing dynamic data into a view to populate a dropdownlist. Would it be a good idea to create a model object for dropdownlists and other "overhead" data or use a viewbag?
Thanks
Example for guidance:
I think the best way to achieve what you're after would be to use a ViewModel. You'd load the stuff you want to display in your View through this. So you'd create a dropdownlist with your accountlist which will be loaded in your controller. You'll also have your IEnumerable PErsoncontact in there which will also be loaded in your controller. Then your controller will pass the ViewModel to the View. You can use this as a guide.
ViewModel:
public class PersonViewModel
{
public int PersonID {get;set;}
public List<SelectListItem> PersonContactList {get;set;}
public IEnumerable<TypesAvail> TypesAvails{get;set;}
}
Dropdownlist in Razor View :
#Html.DropDownListFor(m => m.PersonID , Model.PersonContactList )
Edit:-
This is an example .Yes you can create a new class in same Model.
public class TypesAvail
{
public String TypeNme { get; set; }
public long TypeID { get; set; }
public int NumSelected { get; set; }
public int TypeCount { get; set; }
public IEnumerable<SelectListItem> CarsAvail
{
get
{
return new SelectList(
Enumerable.Range(0, TypeCount+1)
.OrderBy(typecount => typecount)
.Select(typecount => new SelectListItem
{
Value = typecount.ToString(),
Text = typecount.ToString()
}), "Value", "Text");
}
}
}
Dropdownlist in Razor View :
#Html.DropDownListFor(m=> m.NumSelected, Model.CarsAvail)
Using the ViewBag (as some have suggested in other answers/comments) to get data from your controller to view is generally seen as a code lack.
Your ViewModel should ideally contain all of the data you need for your view. So use your controller to populate this data on a property of your ViewModel:
Here is a simple example of how to create a drop down list in ASP.NET MVC using Html.DropDownListFor using model.
You can do it like this all inlined in your *.cshtml file like so:
#Html.DropDownListFor(model => model.Package.State, new SelectList(
new List<Object>{
new { value = 0 , text = "Red" },
new { value = 1 , text = "Blue" },
new { value = 2 , text = "Green"}
},
"value",
"text",
2))
which will create like this:
<select id="Package_State" name="Package.State"><option value="0">Red</option>
<option value="1">Blue</option>
<option value="2">Green</option>
</select>
Refer to this answer for more information
Including the data in the View's Model or in the ViewBag are both good options, the best one depends entirely on your specific use case.
If this dropdown should be included on only one (or just a few) pages, it makes sense to be part of the ViewModel.
If every page should have the dropdown (if it's part of the menu, or footer for instance) you could create a BaseController that supplies ViewBag data for the dropdown, and let your other controllers inherit from that:
BaseController.cs
public class BaseController : Controller
{
public BaseController() {
ViewBag.MyDroprown = ...
}
}
Any other controller
// inheriting from BaseController will make ViewBag.MyDroprown accessible in the View
public class HomeController : BaseController
{
// Any actions here
}
In my opinion View model should contain all the data that is needed for rendering the view and that is available on view creation.
Using ViewBag for me is like using dynamic type in code - it gives you some flexibility but comes with the price of possible errors, so i try to avoid as much as possibe

ASP.Net MVC Razor - Display Countries Gives Error in View

I am trying to list the contries in view. I have created a model called tbl_Countries and the code is below
public class tbl_Countries
{
public int ID { get; set; }
public string Country_Name { get; set; }
}
I have a Controller called Home with the following code. I have created an edmx file for TestDB database
public ActionResult Index()
{
TestDBEntities TestdbContext = new TestDBEntities();
var countries = TestdbContext.tbl_Countries.ToList();
return View(countries);
}
Below is my View code
#model IList
displaying the countries using ul li with foreach
If i run the application am getting this error:
The model item passed into the dictionary is of type 'System.Collections.Generic.List1[TestMVC.tbl_Countries]',
but this dictionary requires a model item of type 'System.Collections.Generic.IList1[TestMVC.Models.tbl_Countries]
I just want to show the list of countries in view and I would like to know
Without creating a model class is it possible to bind grid?
Is it mandatory to specify the model name using #model directive in view?
You got this error 'cause you specified in your view #model List, but pass to it List, try to change it in your view to List
Yes, you can delete #model at all, but in this case your view won't be strongly typed, so you won't be able to use intelli sense
create a list of country type in model
public List< tbl_Countries> country{get;set;}
In index page set the value of this List
public ActionResult Index()
{
TestDBEntities TestdbContext = new TestDBEntities();
tbl_Countries objModel=new tbl_Countries();
objModel.country = TestdbContext.tbl_Countries.ToList();
return View(objModel);
}
According to the error message you are expecting a model of the type List<TestMVC.Models.tbl_Countries> in the view which is different from the List<TestMVC.tbl_Countries> type your action method returns.
To resolve this issue, you could create a list your view expects and map the data you got from Entity Framework to it.
For example:
public ActionResult Index()
{
TestDBEntities TestdbContext = new TestDBEntities();
var countries = new List<TestMVC.Models.tbl_Countries>();
countries = (from country in TestdbContext.tbl_Countries
select new TestMVC.Models.tbl_Countries
{
Country_Name = country.Country_Name
}).toList();
return View(countries);
}
To seperate the logic of the view and data access it is a good practice to have models which are independent from your data models, from the EF models in your example.

What's the proper way to get values for a dropdown from a table?

Lets say I have a a table called... Person, I guess, and it has the columns Name, Email, AgeGroupId.
AgeGroupId is an int, which relates to the table AgeGroup.
Agegroup only has two columns: Id, and AgeGroupName.
Now, In my view, which is a page to edit a 'person', I want a dropdown box that has EVERY AgeGroupName as the text, and the Id as the value.
This way, later on, I can add a new 'age group' into my age group table, and all my drop down boxes will update. Or is there a better way I should be doing this?
I'm currently passing in my model, and doing this:
#Html.DropDownListFor(model => model.AgeGroupId, #agegroups)
and at the top of the view, i'm making a SelectList with hardcoded values. I don't want them hard-coded in, I don't think? What would I do instead of #agegroup to get the list from the AgeGroups table?
Thanks.
The proper way is using ViewModels. Basically you'll have to create a viewmodel for your view and not pass the db result directly to your view. Something like:
public class PersonViewModel
{
public Person Person {get ; set;}
public Dictionary<int, string> AgeGroups { get; set; }
public PersonViewModel() {}
public PersonViewModel(int personId)
{
var ctx = new Context();
this.Person = ctx.Persons.SingleOrDefault(p => p.Id == personId);
foreach(var ageGroup in ctx.AgeGroups)
{
this.AgeGroups.Add(ageGroup.Id, ageGroup.AgeGroupName);
}
}
Then your controller method will look like this:
public ActionResult Add(PersonViewModel vm)
{
var ctx = new Context();
if(ModelState.IsValid)
{
ctx.Persons.Add(vm.Person);
return View("Index");
}
return View(vm);
}
And in your view, simply:
#Html.DropDownListFor(model => model.Person.AgeGroupId,
new SelectList(model.AgeGroups, "Id", "AgeGroupName"))
Of course, your view's model is now PersonViewModel.
Update
seems like ASP.NET MVC 3 Tools update adds drop down for relations by default. More info here.
The correct way seems to be from Kamyars edit, on the msdn blog here:
http://blogs.msdn.com/b/joecar/archive/2011/04/15/asp-net-mvc-3-tools-update.aspx

Reusable DropDownList Content

I'm fairly new to ASP.NET MVC and am looking for help with the following issue.
I have a DropDownList control in a view. The selected value will be stored in an integer field of my model.
My preference is to not hard code the text and values in markup. In addition, I'd like to be able to use this same list of text and values in DropDownList controls in other views.
I'm not sure if I need to create a class that initializes these values somewhere, or perhaps I need an extension method. I could use some guidance on the best way to approach this.
This is a sample:
var apps = _webAppRepo.GetAll();
IList<SelectListItem> appSelectListItems = new List<SelectListItem>();
foreach (var item in apps) {
appSelectListItems.Add(new SelectListItem {
Text = item.ApplicationName,
Value = item.WebApplicationID.ToString()
});
}
ViewBag.AppSelectListItems = appSelectListItems;
And this is how you use it on you view:
#Html.DropDownListFor(model =>
model.WebApplicationID,
(IEnumerable<SelectListItem>)ViewBag.AppSelectListItems
)
If you would like to use it without a model, this is the way:
#Html.DropDownList("Foo",
(IEnumerable<SelectListItem>)ViewBag.AppSelectListItems
)
There are a number of ways of doing this, but you could do worse than storing these values in a view model, and rendering them on the page. I'm just using a Tuple here as an example:
public class MyViewModel
{
List<Tuple<int, string>> items_ = new List<Tuple<int, string>>();
public MyViewModel()
{
items_.Add(new Tuple<int, string>(1, "Item1"));
items_.Add(new Tuple<int, string>(2, "Item2"));
// etc
}
public List<Tuple<int, string>> Items { get { return items_; } }
}
Your controller:
public class MyController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel());
}
}
Your view:
#model MyNameSpace.MyViewModel
<select id="mySelect" name="mySelect>
#{foreach(Tuple<int, string> item in Model.Items){
<option value="#item.Item1">#item.Item2</option>
}}
</select>
Obviously, you can also make an extention method to create combo boxes in more interesting ways :)
You should populate your DropDownList from a database table, or from memory o reading from a xml file.
The you should be able to use the same data to populate any other ddl on your views.

ASP.NET MVC - drop down list selection - partial views and model binding

I'm fairly new to ASP.NET MVC and am trying to work out the best way to do this. It's probably simple but I just want to do things correctly so I thought I'd ask.
Lets say I have a model that is this:
Task - Id, Description, AssignedStaffMember
StaffMember - Id, FirstName, LastName
and in my view I want to create a new task. I make a strongly typed Razor view, and can use EditorFor to create textboxes for Description but what about AssignedStaffMember?
I want a drop down list of all current staff and have the option of selecting one, then this gets submitted to an action method which is
NewTask(string description, StaffMember assignedStaffMember)
either that or I could have an int for staffId instead of the StaffMember object and look it up in the action method.
What is the best way to do this? I need to go to the database to get the list off staff, so here's what I thought:
Make a partial view for the listing of staff drop down, which will be used a few times and use #Html.Action("ListStaff", "Staff") to call it. The action method then has
public ActionResult ListStaff()
{
IEnumerable<StaffMember> model = _serviceLayer.GetAllStaff();
return PartialView(model);
}
However I'm not sure on how this will work with model binding, my understanding is that it has to have the correct name for the form to submit it, I'd need to pass the name to the partial view to put on the element I guess?
Instead of having it call a controller to get the staff, make a ViewModel that contains my Task and a IEnumerable possibleStaff collection. possibly send this information to a partial view.
a Html Helper ?
EditorFor could somehow be used?
which one (or is there more) would be best? and how would I do the model binding?
Here is one way to do this. Create a TaskDetailsViewModel
public class TaskDetailsViewModel
{
public TaskDetailsViewModel()
{
this.Task = new Task();
this.StaffMembers = new List<StaffMember>();
}
public Task Task { get; set; }
public IEnumerable<StaffMember> StaffMembers { get; set; }
}
In Controller
public ActionResult Edit(int id)
{
var task = taskRepository.GetTaskByID(id);
var taskDetailsViewModel = new TaskDetailsViewModel();
// Populate taskDetailsViewModel from task and staff
return View(taskDetailsViewModel);
}
[HttpPost]
public ActionResult Edit(TaskDetailsViewModel taskDetailsViewModel)
{
if (ModelState.IsValid)
{
taskRepository.Save(taskDetailsViewModel.Task);
}
else
{
// Show Error
}
return View(taskDetailsViewModel);
}
In View (bound strongly to TaskDetailsViewModel)
#Html.DropDownListFor(model => model.Task.AssignedStaffMember, new SelectList(Model.StaffMembers, "ID", "FirstName", Model.Task.AssignedStaffMember))
#Html.ValidationMessageFor(model => model.Task.AssignedStaffMember)

Resources