Best programming practice of using DropDownList in ASP.Net MVC
You want to use option 1, mainly because you want to use Strongly Type as much as possible, and fix the error at compile time.
In contrast, ViewData and ViewBag are dynamic, and compile could not catch error until run-time.
Here is the sample code I used in many applications -
Model
public class SampleModel
{
public string SelectedColorId { get; set; }
public IList<SelectListItem> AvailableColors { get; set; }
public SampleModel()
{
AvailableColors = new List<SelectListItem>();
}
}
View
@model DemoMvc.Models.SampleModel
@using (Html.BeginForm("Index", "Home"))
{
@Html.DropDownListFor(m => m.SelectedColorId, Model.AvailableColors)
<input type="submit" value="Submit"/>
}
Controller
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new SampleModel
{
AvailableColors = GetColorListItems()
};
return View(model);
}
[HttpPost]
public ActionResult Index(SampleModel model)
{
if (ModelState.IsValid)
{
var colorId = model.SelectedColorId;
return View("Success");
}
// If we got this far, something failed, redisplay form
// ** IMPORTANT : Fill AvailableColors again; otherwise, DropDownList will be blank. **
model.AvailableColors = GetColorListItems();
return View(model);
}
private IList<SelectListItem> GetColorListItems()
{
// This could be from database.
return new List<SelectListItem>
{
new SelectListItem {Text = "Orange", Value = "1"},
new SelectListItem {Text = "Red", Value = "2"}
};
}
}
MVC4 best practice for DropDownListFor enum from database or code
I personally think that database-driven is the way to go. Mainly from experience, say you wanted to add a value into your lookup and you'd already deployed your application, you'd have to re-deploy the code after adding the new value to the Enum. With them being database driven you simply can run an insert query against the database and no re-deploy is required.
I wouldn't call your database in your view like that though, I wouldn't say that was best practice, as that's not the view's responsibility, it just needs to display data, not query for additional data.
First off, put your items you want in your dropdown list in your model, like so:
public class YourModel
{
public int WidgetTypeId { get; set; }
public SelectList WidgetTypes { get; set; }
//...rest of your model
}
Then, in your GET method in your controller (before returning your view, populate that list with the code you have in the view:
public ActionResult MyAction()
{
YourModel model = new YourModel();
model.WidgetTypes = Business.MySession.Current.WidgetTypes
.ToSelectList(d => d.TypeName, d => d.WidgetTypeID.ToString(), " - Select - ");
return View(model);
}
Then in your view just do:
@Html.DropDownListFor(model => model.WidgetTypeID, Model.WidgetTypes)
ASP.NET MVC ViewModel with SelectList(s) best practice
Personally I like to keep it simple:-
[HttpGet]
public Edit(int id) {
EditForm form = new EditForm();
// Populate from the db or whatever...
PopulateEditPageSelectLists(form);
return View(form);
}
[HttpPost]
public Edit(EditForm form) {
if (ModelState.IsValid) {
// Do stuff and redirect...
}
PopulateEditPageSelectLists(form);
return View(form);
}
public void PopulateEditPageSelectLists(form) {
// Get lookup data from the db or whatever.
}
If the logic to populate the select lists is all kinds crazy it might be worthwhile moving to a separate class or whatever it but as a first step this is the best place to start.
Populate DropDown List in MVC App that Consumes a Web API
In your Code, I noticed that you used @Html.DropDownList
to realzie the selector element, and using form submit to handle the data. So I did a test in my side:
@{
List<SelectListItem> listItems= new List<SelectListItem>();
listItems.Add(new SelectListItem
{
Text = "Exemplo1",
Value = "Exemplo1_v"
});
listItems.Add(new SelectListItem
{
Text = "Exemplo2",
Value = "Exemplo2_v",
Selected = true
});
listItems.Add(new SelectListItem
{
Text = "Exemplo3",
Value = "Exemplo3_v"
});
}
<form asp-action="Create">
<div class="form-group">
AuthorNames
<div class="col-md-10">
@Html.DropDownListFor(model => model.Author, listItems, "-- Select author --")
</div>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
My model contains a public string? Author { get; set; }
property, and when I click the submit button, the select value will be submitted, so when you want to pass the FullName
to your controller, you need to set it as the Value
of the SelectListItem
.
ASP MVC 5 C# Recursive Trees To Group and Indent A DropDownList
You can first select the parent categories (where ParentId
is null
) and then for each parent category, select its child categories.
public IEnumerable<SelectListItem> GetCategoriesSelectList()
{
var categories = _context.Category.ToList();
// Initialise list and add first "All" item
List<SelectListItem> options = new List<SelectListItem>
{
new SelectListItem(){ Value = "0", Text = "All" }
};
// Get the top level parents
var parents = categories.Where(x => x.ParentId == null);
foreach (var parent in parents)
{
// Add SelectListItem for the parent
options.Add(new SelectListItem()
{
Value = parent.Id.ToString(),
Text = parent.Name
});
// Get the child items associated with the parent
var children = categories.Where(x => x.ParentId == parent.Id);
// Add SelectListItem for each child
foreach (var child in children)
{
options.Add(new SelectListItem()
{
Value = child.Id.ToString(),
Text = string.Format("--{0}",child.Name)
});
}
}
return options;
}
Best Practice for adding Liststring to DropDownList
The only thing DropDownListFor
needs is an IEnumerable<SelectListItem>
(i.e., that could be a list/collection/queryable/etc.). The problem right now is that you simply have a list string
instead of SelectListItem
. That's easy remedied with a little LINQ-fu:
@Html.DropDownListFor(x => x.searchCategory, Model.AllCategories.Select(m => new SelectListItem { Value = m, Text = m }))
However, the better approach would be to simply have AllCategories
return a list of SelectListItem
s off-the-bat (assuming it's only being used for populating the dropdown list).
private IEnumerable<SelectListItem> allCategories;
public IEnumerable<SelectListItem> AllCategories
{
get
{
if (allCategories == null)
{
var _engine = new NopEngine();
var categoryService = _engine.Resolve<ICategoryService>();
allCategories = categoryService.GetAllCategories().Select(m =>
new SelectListItem { Value = m.Name, Text = m.Name });
}
return allCategories;
}
// You don't need a setter
}
The first time AllCategories
is accessed, the associated private variable, allCategories
, will be null, so your service spins up and the list of categories is fetched. Select
is used to cast the returned categories into a collection of SelectListItem
s. If you category has something like an Id
property, you should use that for Value
instead of Name
. Any subsequent accesses of AllCategories
will simply return the value stored in the private without hitting the database again.
Bonus Pro Tip
If you actually do need to use a for loop for something like this, you don't need to create a new list, add items to the list in the loop, and then return that list. It's easier to just use yield
. For example:
public IEnumerable<int> Numbers
{
for (int i = 0; i < 10; i++)
{
yield return i;
}
}
populate dropdownlistfor mvc
You are passing in a list of PartStructures
class objects to the Except
method. Except method uses the default equality comparer to compare the values.
If you are passing a custom class (not a simple value type like int
) , You should implement IEqualityComparer<T>
interface methods such as Equals
and GetHashCode
.
If you do not prefer to do that, You can get the Ids of your PartStructures collection and use that with the Contains
method.
var excludeIdList = db.PartStructures1.Where(p => p.mainPart_id == partID)
.Select(g=>g.Id).ToList();
var parts = db.Parts
.Where(c => !c.PartStructures_comp.Any(g=>excludeIdList.Contains(g.Id)))
.ToList();
Related Topics
JSON.Net - Serialize Property Name Without Quotes
What Is the Fastest Way to Create a Checksum for Large Files in C#
Deserializing Xml to Objects in C#
Alternatives to Thread.Sleep()
Is There Any Way in C# to Override a Class Method with an Extension Method
JSONserializersettings and ASP.NET Core
Why Does C# (4.0) Not Allow Co- and Contravariance in Generic Class Types
How to Create a Product Key for My C# Application
Httpclient Not Supporting Postasjsonasync Method C#
How to Access Configuration in Any Class in ASP.NET Core
Pulling Data from a Webpage, Parsing It for Specific Pieces, and Displaying It
Could Not Load File or Assembly 'Microsoft.Reportviewer.Common, Version=11.0.0.0
Can't Get SQL Server Compact 3.5/4 to Work with Asp .Net MVC 2