Dropdownlist with MVC (Asp.net website) [duplicate] - c#

This question already has answers here:
DropDownList in MVC 4 with Razor
(13 answers)
Closed 7 years ago.
I have some trouble creating an dropdownlist correctly in MVC. I'm not sure how to link the dropdownlist with the model, and create values for it. Right now I have the following code that creates 2x dropdownlists:
<div class="form-group">
Outward route<br />
<select class="dropdown" id="Dropdown-outward">
<option>Copenhagen</option>
<option>Oslo</option>
<option>Stockholm</option>
</select>
</div>
<div class="form-group">
Return route<br />
<select class="dropdown" id="Dropdown-return">
<option>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
</select>
</div>
I used the select & option command to create values as you see in the code. I know you can use some razor syntax like.
#Html. something
but I can't seem to do it right. Have created an model (Booking) which look like this:
namespace Project.Models
{
public class Booking
{
public int ID { get; set; }
public string Departure { get; set; }
public string Return { get; set; }
public DateTime DepartureDate { get; set; }
public DateTime ReturnDate { get; set; }
public int Adults { get; set; }
public int Childrens { get; set; }
}
}
If I use the Html helper like this:
#Html.DropDownList( )
What should i write insite the braces? and how do i add values to it, so you can select, lets say the cities Oslo, Copenhagen & Stockholm?

If you just need the values you can simply use razor, create your model and iterate over a collection of your model like:
<select class="dropdown" id="Dropdown-outward">
#foreach(var m in Model.Items)
{
<option value="#m.ID">#m.ID</option>
}
</select>
This is a possible solution. You have your dropdown and can identify selected values with your model.

If all you want is a simple dropdown list bound to a specific property of your model then you can use the Html.DropdownListFor helper. And it's always a good practice to use a viewmodel with properties that your view needs. So in this case
public class BookingViewModel
{
public Booking Booking { get; set; }
public IEnumerable<SelectListItem> Cities { get; set; } // <-- for your dropdown
}
Controller:
[HttpGet]
public ActionResult Index()
{
var vm = new BookingViewModel();
var citiesList = new List<SelectListItem>
{
new SelectListItem { Value = "Oslo", Text = "Oslo" },
new SelectListItem { Value = "Copenhagen", Text = "Copenhagen" },
new SelectListItem { Value = "Stockholm", Text = "Stockholm" }
};
vm.Cities = citiesList;
return View(vm);
}
View:
#using (Html.BeginForm())
{
#Html.DropDownListFor(s => s.Booking.Departure, Model.Cities)
<button type="submit">Submit</button>
}
Renders a <select id="Booking_Departure" name="Booking.Departure"> ... and <options> that you specified as SelectListItems.
Lastly your post Action:
[HttpPost]
public ActionResult Index(BookingViewModel vm)
// the `ViewModels` -> Booking -> Departure prop will be pupulated with the value from the selection in the dropdown
{
return View(vm);
}

Related

<select> tag helper not marking options as "selected" in multiple select

Take the following model:
public class SomeModel
{
public ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public int Id { get; set; }
public string Value { get; set; }
}
The model is some kind of object (e.g., a blog entry), that features a list of tags or keywords.
I have a Razor view showing a form to edit a SomeModel object:
#model SomeModel
#{
// List of available tags is passed by controller
var tags = (List<Tag>)ViewData["Tags"];
}
<label asp-for="Tags">Tags</label>
<select asp-for="Tags"
asp-items="#(new SelectList(tags, nameof(Tag.Id), nameof(Tag.Value)))">
</select>
As expected, this generates a multiple select showing the available tags:
<label for="Tags">Tags</label>
<select class="input-validation-error"
data-val="true" data-val-required="The Tags field is required."
id="Tags" multiple="multiple" name="Tags">
<option value="1">tag1</option>
<option value="2">tag2</option>
</select>
#Model.Tags correctly contains the currently assigned tags; however, the corresponding options are not marked as selected.
How do I fix this behavior?
You need to create a property to pass the selected datas and bind it to the asp-for attribute of select tag.
Index.cshtml.cs :
public class IndexModel : PageModel
{
[BindProperty]
public List<int> SelectedTags { get; set; } = new List<int>{ 2, 3 };
[BindProperty]
public List<Tag> Tags { get; set; }
public void OnGet()
{
Tags = new List<Tag> {
new Tag { Id = 1, Value="Mike" },
new Tag { Id = 2, Value="Pete" },
new Tag { Id = 3, Value="Katy" },
new Tag { Id = 4, Value="Carl" } };
}
}
Index.cshtml:
#page
#model WebApplication1_rzaor_page.IndexModel
#{
ViewData["Title"] = "SelectTag";
Layout = "~/Pages/Shared/_Layout.cshtml";
}
<h1>SelectTag</h1>
<label asp-for="Tags">Tags</label>
<select asp-for="SelectedTags"
asp-items="#(new SelectList(Model.Tags, "Id","Value"))">
</select>
Result of this demo
You can refer to this link :Setting Selected Item
Table column width where we store selected value must have the same length with reference table column width from where we retrieve the list value.
If the two columns have different length, the comparison will be false, and no option value will be selected.

Creating a form and binding to a class without a datatabase

I'm new to learning MVC and could really use some help- as I'm trying to move on from ASP.NET Web Forms. I have a custom web API for all my database transactions that is very efficient and reliable. I've recoded it in .NET Core.
My problem is that I'm finding most of the model binding examples pertaining to MVC are composed of Entity Framework examples. I'm looking for help showing how to link a ViewModel to a Controller with get() post(form) actions. I need to see how to bind to a radio button list, etc...
I'm working with the class below, which has removed the database connections to simplify the answers/suggestions.
public class BuildSearch
{
//Bootstrap date entry
public DateTime StartDate { get; set; }
//Bootstrap date entry
public DateTime EndDate { get; set; }
//Need this bound to a radio button list
public List<GeoArea> GeoAreas { get; set; }
public BuildSearch()
{
GeoAreas = new List<GeoArea>();
// StartDate = DateTime.Parse(DateTime.Now.AddDays(-31).ToShortDateString());
// EndDate = DateTime.Parse(DateTime.Now.ToShortDateString());
GeoAreas.Add(new GeoArea { GeoAreaItem = "Region", Id = 0 });
GeoAreas.Add(new GeoArea { GeoAreaItem = "Manager1", Id = 1 });
GeoAreas.Add(new GeoArea { GeoAreaItem = "Manager2", Id = 2 });
}
}
public class GeoArea
{
public int Id { get; set; }
public string GeoAreaItem { get; set; }
}
I'm trying to create a view, that will display this data, and then allow for me to post back the user edits. I'm purposely looking to keep the example simple as once I figure out how to post back, with the updated data I can handle the pass off to a web API to do the work I need to be done. Just frustrated trying to figure out how I bind to this type of class.
For the radio buttons I would add a property to your BuildSearch class called GeoAreaId. The radio button selection will be model bound to this property on post back. Your BuildSearch class therefore becomes
public class BuildSearch
{
//Bootstrap date entry
public DateTime StartDate { get; set; }
//Bootstrap date entry
public DateTime EndDate { get; set; }
public int GeoAreaId { get; set; } //added field
//Need this bound to a radio button list
public List<GeoArea> GeoAreas { get; set; }
public BuildSearch()
{
GeoAreas = new List<GeoArea>();
// StartDate = DateTime.Parse(DateTime.Now.AddDays(-31).ToShortDateString());
// EndDate = DateTime.Parse(DateTime.Now.ToShortDateString());
GeoAreas.Add(new GeoArea { GeoAreaItem = "Region", Id = 0 });
GeoAreas.Add(new GeoArea { GeoAreaItem = "Manager1", Id = 1 });
GeoAreas.Add(new GeoArea { GeoAreaItem = "Manager2", Id = 2 });
}
public class GeoArea
{
public int Id { get; set; }
public string GeoAreaItem { get; set; }
}
}
Your get method in your controller will look something like this
public IActionResult Search()
{
var buildSearch = new BuildSearch();
return View(buildSearch);
}
Your view will need to look something like this
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#model BuildSearch
<form asp-controller="Home" asp-action="Search" method="post">
<label asp-for="StartDate">Start date</label>
<input asp-for="StartDate" />
<label asp-for="EndDate">End date</label>
<input asp-for="EndDate" />
<fieldset>
<legend>
GeoArea
</legend>
#foreach (var item in Model.GeoAreas)
{
<input type="radio" name="GeoAreaId" value="#item.Id" />
#item.GeoAreaItem
}
</fieldset>
<input type="submit" />
</form>
For the radio buttons note how the name attribute matches the new property GeoAreaId that I added to your BuildSearch class. This is important for the model binding to work.
Then your post method in your controller will need to look like this
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Search(BuildSearch buildSearch)
{
//...
}
To see what happens set a break point inside this method. Run the code, enter some values into the form and click submit. When the code has stopped inside hover over buildSearch and you will see the model binding has worked. The properties StartDate, EndDate and GeoAreaId will contain the values that you need from the form.
Here is an radio button example:
https://www.c-sharpcorner.com/article/radiobutton-in-asp-net-mvc/
here is a good example of getting your form data from the html form into the controller.
https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/controller-methods-views?view=aspnetcore-2.2
Getting the data into the viewmodel you will do something like this
public async Task<IActionResult> Index()
{
var movies = await _context.Movies.ToList();
if (movies == null)
{
return NotFound();
}
return View(movies);
}
You will then need the form to have a post action to you Action e.g.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
if (ModelState.IsValid)
{
//post to api here
return RedirectToAction(nameof(Index));
}
return View(movie);
}
You will have to pass the model or view model into the html class as
#model MvcMovie.Models.Movie
#{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Movie</h4> etc etc

How to pass collection from view to controller in asp.net MVC4

I want to pass a collection of skills id from my view to controller action, i have a dropdownlist of SKILLS :
<select name="skills">
<option value="0">Java</option>
<option value="1">C++</option>
<option value="2">Fortran</option>
<option value="3">ASP</option>
</select>
i want that user can select many skills from dropdown and store their value in a collection ,i.e an array, and then post that array to action in controller as follow [employee and skills have a manytomany relationship]:
[HttpPost]
public ActionResult AddEmp(Employee emp ,IEnumerable<Skills> skills )
{
DBCtx db=new DbCtx();
db.employees.Add(emp);
var emp_id=db.SaveChanges();
var employee=db.employees.Find(emp_id);
foreach(item in skills)
{
var skill = db.skills.Find(item);
employee.skills.Add(skill);
}
db.SaveChanges();
return View();
}
How can i achieve this ,thanks in advance ....
You have quite few options on front end . Razor, Angular, Jquery... To simplfy things in following example i have used Razor view. I dont think you need to pass Skills as a strongly type object as you only need Id of selected Skills . Also in the example i have the skills list static / hard coded into razor view, ideally it should be bound from backend.
Saying that lets assume our Employee View Model as it follows
public class EmployeeViewModel
{
public EmployeeViewModel()
{
SelectedSkills=new List<int>();
}
public int Id { get; set; }
public string Name { get; set; }
public List<int> SelectedSkills { get; set; }
}
public class Skills
{
public int Id { get; set; }
public string Name { get; set; }
}
Then our Controller (EmployeeController.cs) would be .(please ignore the EF logic after data is bound to class)
public class EmployeeController : Controller
{
public ActionResult Index()
{
return View("Employee",new EmployeeViewModel());
}
[HttpPost]
public ActionResult AddEmp(EmployeeViewModel employee)
{
var idOfEmployee=AddEmployee(employee);
foreach (var item in employee.SelectedSkills)
{
AddSkill(idOfEmployee,item);
}
return View("Employee");
}
private void AddSkill(int idOfEmployee, int skillId)
{
// your EF logic
}
private int AddEmployee(EmployeeViewModel emp)
{
// your EF logic, get your id of the inserted employee
return 0;
}
}
Then our Employee.cshtml view could be
#using System.Web.UI.WebControls
#using WebApplication4.Controllers
#model WebApplication4.Controllers.EmployeeViewModel
#{
ViewBag.Title = "Employee";
}
<h2>Employee</h2>
#{var listItems = new List<Skills>
{
new Skills { Id = 0,Name="Java" },
new Skills { Id = 1,Name="C++" },
new Skills { Id = 2,Name="Fortran" }
};
}
#using (Html.BeginForm("AddEmp", "Employee"))
{
#Html.TextBoxFor(m => m.Name, new { autofocus = "New Employee" })
<br/>
#Html.ListBoxFor(m => m.SelectedSkills,
new MultiSelectList(listItems, "Id", "Name",#Model.SelectedSkills)
, new { Multiple = "multiple" })
<input type="submit" value="Submit" class="submit"/>
}

MVC Dropdown option displayed as 'null' in debug mode

Afternoon Folks,
Im new to MVC 5 and C# and have a simple form with several fields and a dropdown box. I have used the CRUD method for entity framework and can successfully view and create new records in the system.
The only issue that I have is I have a 'Title' dropdown that links to the entity framework and populates these titles into a list. when I load my web page I can now see the titles available in the dropdown list, but when submitting the form, all the values but the 'Title' field are submitted into the database.
When I debug my program, this field regardless of what I select displays null.
I have followed the following tutorial to get this wo work and looked around the net but im struggeling to find a solution.
Link to tutorial
I have two tables in my model, one named 'Title' and the other named 'Client Record'.
As I have used the database first approach and not code first I have combined these two database models into one:
namespace EDT_Test.Models.ViewModels
{
public partial class Marie_Testing
{
[Display(Name = "Client Ref:")]
public int id { get; set; }
[Display(Name = "Created By:")]
public string CreatedBy { get; set; }
public List<Title> allTitles { get; set; }
[Required]
[Display(Name = "Surname:")]
public string Surname { get; set; }
[Display(Name = "Additional Surname:")]
public string Surname2 { get; set; }
[Required]
[Display(Name = "Forename:")]
public string Forename1 { get; set; }
[Display(Name = "Additional Forename:")]
public string Forename2 { get; set; }
The generated Entity Framework model looks like this:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace EDT_Test.Models
{
using System;
using System.Collections.Generic;
public partial class ClientRecord
{
public int id { get; set; }
public string CreatedBy { get; set; }
public string Title { get; set; }
public string Surname { get; set; }
public string Surname2 { get; set; }
public string Forename1 { get; set; }
public string Forename2 { get; set; }
}
}
The only difference for the Title field between the auto created model and Marie_Testing model is I have changed the Title field from a string to a list item.
My Create.cshtml holds a div for the Title dropdown that looks like this (This links to my model named Marie_Testing and not the auto generated ones created by the Entity Framework:
<div class="form-group">
#Html.LabelFor(model => model.allTitles, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<select id="titleid" name="titlename" class="form-control">
#foreach (var item in Model.allTitles)
{
<option value="#item.id">#item.Title1</option>
}
</select>
</div>
</div>
My code for the ClientRecordsController is:
// GET: ClientRecords/Create
public ActionResult Create()
{
////set the defaults (dropdown) of the page for the ceaton of a new record.
Marie_Testing vmPopulateData = new Marie_Testing();
List<Title> titles = (from t in db.Titles select t).ToList();
//List<Title> titles = Title.Select(t => new{t.id, t.Title}.ToString.ToList());
vmPopulateData.allTitles = titles;
return View(vmPopulateData);
}
// POST: ClientRecords/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,CreatedBy,Title,Surname,Surname2,Forename1,Forename2")] ClientRecord clientRecord)
{
if (ModelState.IsValid)
{
db.ClientRecords.Add(clientRecord);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(clientRecord);
}
Any help is much appreciated as I don't understand how can see the dropdown list in the web page but cannot seem to grab the selected value and post this to the database.
Regards
Betty B
Why not try the #Html.DropDownListFor?
Instead of this:
<select id="titleid" name="titlename" class="form-control">
#foreach (var item in Model.allTitles)
{
<option value="#item.id">#item.Title1</option>
}
</select>
try:
#Html.DropDownListFor(x => x.PropertyToBindTo, new SelectList(Model.allTitles, "id", "Title1"), new { #class = "form-control", id = "Title", name = "Title" })
Where x.PropertyToBindTo is whatever value that you need to get from that select list. Try it out... you may have to play with it a little in order to really understand how you need to work it.
You need to have a string field to hold the value of the selected from the dropdown so your view would change from
<select id="titleid" name="titlename" class="form-control">
to
<select id="Title" name="Title" class="form-control">
And you will also have a Title property on your view model like this
public string Title{get;set;}
You need to have a read on how MVC binds forms to models to get an understanding of why this happens.
Hope this helps..
well I prefer to use this
C#
List<Titles> oTitlesList = TitlesService.getTitles();
ViewBag.DropDownListBag = new SelectList(oTitlesList , "Id", "Name");
Razor
#Html.DropDownListFor(model => model.yourModelAtt, #ViewBag.DropDownListBag as SelectList, "Select.....", new { #class = "form-control" })

HTML.DropDownListFor DropDownList

I'm trying to retrieve data from my Database to an HTML instead of retrieving to the Html.DropDownListFor but I'm unable to retrieve to tag.
NewCustomerViewModel
public class NewCustomerViewModel
{
public int CustId { get; set; }
[Required]
public string CustFirstName { get; set; }
[Required]
public string CustLastName { get; set; }
[Required]
public int StId { get; set; }
public IEnumerable<State> States { get; set; }
}
CustomerController
public class CustomerController : Controller
{
private CustomerDbContext _context;
public CustomerController(CustomerDbContext context)
{
_context = context;
}
// GET: /<controller>/
public IActionResult Index()
{
return View(_context.Customers.ToList());
}
public IActionResult Create()
{
var stateNames = _context.States.ToList();
var viewModel = new NewCustomerViewModel
{
States = stateNames
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Customer customer)
{
if (ModelState.IsValid)
{
_context.Customers.Add(customer);
_context.SaveChanges();
return RedirectToAction("Index");
}
return View(customer);
}
}
Create View
The HTML DropDownListFor below works fine:
#Html.DropDownListFor(m => m.StId, new SelectList(Model.States, "StId", "StName"))
I'm unable to get the select tag to work though.
<select asp-for="StId" asp-items="#Model.States" class="form-control">
<option>Select State</option>
</select>
All of my HTML in my Create view using and rather than the HTML Helpers which is what I'm trying to avoid. I would just like to be able to retrieve the data to the tag instead.
For the select tag helper, asp-items expects SelectListItem collection\SelectList, and each item in that has a Value and Text property. The Value properties value will be used for the option's value and Text propertiesvalue will be used for the display text of the option in the UI.
Items in your States collection does not have a Value and Text property, but has StId and StName property. So we need to convert this type to SelectListItem type.
So your code should be
<select asp-for="StId" asp-items="#(new SelectList(Model.States,"StId","StName"))">
<option>Please select one</option>
</select>
Additional reference
Select Tag Helper in MVC 6

Categories