MVC 4 Bind multiple model asp razor - c#

I develop an application who manages formations of employees, I use MVC4 Asp.net with Razor.
In my model I have tow class (who are table in my database) formation and formateur (trainers).
In my application i can create a “formation” and I want to add a list of “formative”(trainers) but I don’t know what I must do.
I think the best solution it’s a list of checkbox, I succeeded to display my list of checkbox with a foreach but I have no idea how I get the result of selected checkbox to pass into my controller.
I saw many tutorials where use “CheckBoxList” and I tried to use too, but I use a ViewBag to populate it and they don't explain how to use it with a viewbag.
Now I test a Dual listBox with tow buttons (Add and Remove) but this doesn't work.
So, somebody can help me to find, and explain how I must do, the good or the best solution ?
I'm sorry for my english, I'm a french girl.
One of my solutions look like this :
My controller :
public ActionResult Create()
{
ViewBag.formateurListe = (from unFormateur in db.salarie
where unFormateur.sFormateur == true
select unFormateur).AsEnumerable()
.Select(m => new SelectListItem
{
Text = m.sNom.ToString() + " " + m.sPrenom.ToString(),
Value = m.sId.ToString()
}).ToList();
return View();
}
[HttpPost]
public ActionResult Create(formation formation, IEnumerable<SelectList> formateurList)
{
if (ModelState.IsValid)
{
db.formation.Add(formation);
foreach (var unSal in formateurList)
{
formateur f = new formateur();
f.ftIdFormation = formation.fId;
f.ftIdSalarie = (int)unSal.SelectedValue;
db.formateur.Add(f);
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(formation);
}
In my view :
#model MvcAppGestionRH.Models.formation
#using (Html.BeginForm("Create", "Formation", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
#Html.Label("Libelle")
#Html.EditorFor(model => model.fLibelle)
#Html.ValidationMessageFor(model => model.fLibelle)
<label id="fFormateur">Formateur</label>
#Html.ListBox("formateurListe", ViewData["formateurListe"] as SelectListItem[], new {Multiple = "multiple"})
<input type="button" value="+" name="add" />
<select name="select" size="7" >
</select>
<input type="submit" value="Créer" />
}
With a script :
$(function () {
$("#Add").click(function () {
$("select").add($('fFormateurListe').selected);
});
});

Checkboxes can be tricky the first time - I googled that a long time, too.
My solution is a view model which looks like this:
It is intended for questions, where the crator can speciy items via checkboxes (e.g. a questions might have the answer "GOOD" and "BAD".
public class QuestionModel
{
public int QuestionID { get; set; }
public string QuestionText { get; set; }
/// <summary>
/// Gets or sets the selected items. Purely a helper List to display check boxes for the user
/// </summary>
/// <value>
/// The selected items.
/// </value>
[Display(Name = "Items", ResourceType = typeof(Domain.Resources.Question))]
public IEnumerable<SelectListItem> SelectedItems { get; set; }
/// <summary>
/// Gets or sets the selected ids. Populated by the user, when he checks / unchecks items. Later translated into QuestionItems
/// </summary>
/// <value>
/// The selected ids.
/// </value>
public int[] SelectedIds { get; set; }
}
This is populated like this in the QuestionController:
private async Task GetSelectedItems(QuestionModel sm, Item selectedItems)
{
var alreadySelected = new List<Scale>();
if (selectedScale != null)
{
alreadySelected.Add(selectedScale);
}
var itemList = (await this.uoW.ItemRepository.Get()).OrderBy(i => i.Name);
sm.SelectedItems = itemList.Select(x => new SelectListItem
{
Value = x.ScaleID.ToString(),
Text = x.NameOfScale.GetText(),
Selected = (from a in alreadySelected where a.ItemID == x.ItemID select x).Any()
});
}
What does this do? It gets a list of all avialable items in the database and populates the model with it. Furthermore, you can pass in a list of items, which are already selected - so you can edit an existing question and siplay all already checked Items.
And n the view I have used a DropDownList:
<div class="form-group">
#Html.LabelFor(model => model.SelectedItems, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.DropDownListFor(x => x.SelectedIds, Model.SelectedItems, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.SelectedItems, "", new { #class = "text-danger" })
</div>
</div>
</div>
If you want checkboxes, that looks like this(different controller, so dont be confused)
for (int i = 0; i < Model.SelectedItems.Count(); i++)
{
var currentElem = Model.SelectedItems[i];
//if this item is selected by the user, e.g. because he is editing the item, the item will be pre-selected
var selected = currentElem.Selected ? "checked=\"selected\"" : string.Empty;
// column for the questions. expected layout: list of all questions
<div class="col-md-6">
<div class="checkbox" id="SelectedIds">
<label>
<input type="checkbox" value="#currentElem.Value" #selected name="SelectedIds">
#Html.Encode(currentElem.Text)
</label>
</div>
</div>
}
and finally the create() method itself:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "QuestionText,SelectedItems, SelectedIds")] QuestionModel question)
{
if (ModelState.IsValid)
{
// I need only one Item, but if you want ore more change this line
if (question.SelectedIds.Count() == 1)
{
// better use Automapper here, this is unnecessary work
var newQuestion = new Question { QuestionText = question.QuestionText};
var ItemID = question.SelectedIds.First();
newQuestion.QuestionScale = await this.uoW.ItemRepository.GetRaw().Where(i => i.ItemID == ItemD).FirstAsync();
this.uoW.QuestionRepository.Insert(newQuestion);
await this.uoW.Save();
return this.RedirectToAction("Index");
}
else
{
this.logger.Warn("User {0} tried to insert more than one Itemin question {1}", User.Identity.Name, question.QuestionID);
ModelState.AddModelError(string.Empty, xyz.Areas.QuestionManagement.Resources.QuestionRes.ErrorTooManyScales);
}
}
else
{
// the SelectedItems are empty in the model - so if you have to redisplay it, repopulate it.
await this.GetSelectedItems(question, null);
}
return this.View(question);
}

Have you tried using a viewmodel to pass your two model in the view?
For example :
ViewModel
public class CreateFormationViewModel
{
public Formation formation{ get; set; }
public List<Formative> trainers {get;set;}
}
and then use this viewmodel in your view
An easy way to use this view model :
In your controller
public ActionResult CreateFormation()
{
//Get your data (formation and trainer)
CreateFormationViewModel createFormationVM = new CreateFormationViewModel();
createFormationVM.formation = YourFormationModel;
createFormationVM.trainers = YourtrainersModelasList;
//bind data to the view
return View(createFormationVM);
}
And in your View, you have :
#model [yournamespace].CreateFormationViewModel

Related

DropDownListFor has unique value for all items

I am using a razor helper DropDownListFor in order to have a dropdown list of Organizational Units from Active Directory (replicated in Database, it doesn't matter so much). The idea is you have a first list with all parent elements, and when clicking, I search my database to find the children elements, and so on until you reach a leaf (so to speak, last element). My problem is that when inspecting element in my browser I find that all value from the <option> markup are equal to the first id that I pass when clicking.
So here is my ViewModel:
public class SiteDirectionModel
{
public int id { get; set; }
public List<SelectListItem> Names { get; set; }
}
Then my first controller method (for parent elements) is the following :
public ActionResult CreateADUser()
{
List<SelectListItem> items = new List<SelectListItem>();
SiteDirectionModel sdM = new SiteDirectionModel();
//The below method gets all parent nodes from database
//_nonGenService is an instance of a service that can access my Repository
direction = _nonGenService.GetAllSiteDirection();
if (direction != null && direction.Count!=0)
{
items.Add(new SelectListItem
{
Text = dir.Name,
Value = dir.IDDirection.ToString()
});
}
sdM.Names = items;
return View(sdM);
}
else
return View("AccessError"); //A page in case of error
}
Then the second controller method to treat child elements:
public ActionResult GetSiteRF(SiteDirectionModel model)
{
SiteDirectionModel sdM = new SiteDirectionModel();
List<SelectListItem> items = new List<SelectListItem>();
//This method gets children elements from a specified id
//The table that looks has IDDirection as FK from first table
radioFrance = _nonGenService.GetSiteRFFromDirection(model.id);
direction = _nonGenService.GetAllSiteDirection();
int id;
string nameConcat = string.Empty;
//For loop to concatenate names
foreach(var dir in direction)
{
if (dir.IDDirection == model.id)
{
nameConcat = dir.Name + "-" + nameConcat;
break;
}
}
if (radioFrance.Count==1)
{//This condition would be to see if the name is equal to the current node so
//that we can exit the condition and access a form to create the user
Site_RadioFrance single = radioFrance.SingleOrDefault();
if (single.Name.Equals(nameConcat))
{
return View("CreateADForm", model);
}
}
else
{
foreach (var radio in radioFrance)
{
items.Add(new SelectListItem
{
Text = nameConcat+radio.Name,
Value = radio.IDDirection.ToString()
});
}
sdM.Names = items;
return View("CreateADUser",sdM);
}
return View("AccessError"); //Error treatement
}
My view loks like this :
#model MyProject.Models.SiteDirectionModel
<h2>Create an account in Active Directory</h2>
#using (Html.BeginForm("GetSiteRF", "Create", FormMethod.Post))
{
#Html.DropDownListFor(x => x.id, Model.Names);
<input type="submit" value="Selectionner" class="btn btn-primary"/>
}
Now say you have the item clicked with IDDirection=10 then all my child elements have
<option value=10>parent1-child1</option>
<option value=10>parent1-child2</option>
<option value=10>parent1-child3</option>
<option value=10>parent1-child4</option>
I don't know how to fix this, any ideas? because then my model id has this value, and I somehow thought that it would apply a value for each different option, I don't understand why it doesn't?
Thanks!

How do I get the correct radio button selected using MVC RadioButtonFor with float values?

I have an editor template Duration that holds four simple radio buttons.
I am using this template for a property on my class Test.
I cannot get this property to bind to the radio button list and select the correct radio button on load. Selecting a value and submitting will return the correct value.
I have tried changing the values of the radio buttons to a variety of different values, but to no avail.
What value should I pass to RadioButtonFor to get this to work?
Ideally this editor template takes in nullable float and still works.
Duration.cshtml
#model float
<h3>Model Value: #Model</h3>
#Html.RadioButtonFor(model => model, 0.25F, new { id = "btnQuarterDay" }) #(.25F)
#Html.RadioButtonFor(model => model, 0.5F, new { id = "btnHalfDay" }) #(.5F)
#Html.RadioButtonFor(model => model, 0.75F, new { id = "btnThreeQuarterDay" }) #(.75F)
#Html.RadioButtonFor(model => model, 1.0F, new { id = "btnOneDay" }) #(1.0F)
Test.cs
public class Test
{
[UIHint("Duration")]
[Display(Name = "Days")]
public float Duration { get; set; }
}
HomeController
public class HomeController : Controller
{
public ActionResult Index(float? duration = null)
{
var model = new Test
{
Duration = duration.GetValueOrDefault(1F)
};
return View(model);
}
[HttpPost]
public ActionResult Index(Test model)
{
ViewBag.Success = true;
ViewBag.ValueSelected = model.Duration;
return View(model);
}
}
Index.cshtml
#model RadioButtonForTest.Models.Test
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
<div class="row">
<div class="col-md-4">
#Html.EditorFor(model => model.Duration)
#Html.ValidationMessageFor(model => model.Duration)
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
if (ViewBag.Success ?? false)
{
<span>Value Selected:</span> #ViewBag.ValueSelected
}
}
UPDATE: Plot Thickener
I wired up the Index action to take in duration, so that I can pass it via the query string. If a value is not passed via the query string. It will select the radio button below:
#Html.RadioButton("", Model, Model.Equals(1.0F), new { id = "radbtnOneDay4" })
If I navigate to the query string /Home/Index?duration=.5
NOTHING is selected, but when debugging Duration.cshtml Model.Equals(.50F) reports TRUE. So I would expect this radio button to be selected:
#Html.RadioButton("", Model, Model.Equals(.50F), new { id = "radbtnHalfDay4" })
Is this not crazy? Why is it not checking this radio button??? Is this a bug? Is there a custom model binders I could add to handle floats?
UPDATE 2
The query string parameter duration matches the model name and the query string is overriding the model value.
When I changed the parameter to be dur it worked fine. Using the following URL it would use the value from the ViewModel.
/Home/Index?dur=.5
I know there is a solid reason behind this...but this has been exasperating.
The RadioButtonFor helper does not work in templates (edit: ... in cases like yours when using it to bind to simple member values as model => model expression will become an empty name). You need to change your template code to
#Html.RadioButton("", 0.25F, Model == 0.25F, new { id = "btnQuarterDay" }) #(.25F)
#Html.RadioButton("", 0.5F, Model == 0.5F, new { id = "btnHalfDay" }) #(.5F)
#Html.RadioButton("", 0.75F, Model == 0.75F, new { id = "btnThreeQuarterDay" }) #(.75F)
#Html.RadioButton("", 1.0F, Model == 1.0F, new { id = "btnOneDay" }) #(1.0F)
Edit#2: another alternative would be to use a more complex model:
public class DurationContainer {
public float Duration { get; set; }
}
public class Test2 {
[UIHint("Duration2")]
public DurationContainer Container { get; set; }
}
Index.cshtml:
#Html.EditorFor(model => model.Container)
And then as Duration2.cshtml template:
#Html.RadioButtonFor(model => model.Duration, 0.25F, new { id = "btnQuarterDay" }) #(.25F)
#Html.RadioButtonFor(model => model.Duration, 0.5F, new { id = "btnHalfDay" }) #(.5F)
#Html.RadioButtonFor(model => model.Duration, 0.75F, new { id = "btnThreeQuarterDay" }) #(.75F)
#Html.RadioButtonFor(model => model.Duration, 1.0F, new { id = "btnOneDay" }) #(1.0F)
Your editor template is not working because the first argument of is supposed to be a member expression to models property and not a model itself so model => model is what's wrong. You can easily fix it by using Html.RadioButton instead of `Html.RadioButtonFor. Notice that instead of specifying a property name we simply passing an empty string. The reason for that is that EditorTemplates generate are generating correct property names by appending prefixes form parrent model. So your template should look like that:
#model float
<h3>Model Value: #Model</h3>
#Html.RadioButton("", 0.25F, new { id = "btnQuarterDay" }) #(.25F)
#Html.RadioButton("", 0.5F, new { id = "btnHalfDay" }) #(.5F)
#Html.RadioButton("", 0.75F, new { id = "btnThreeQuarterDay" }) #(.75F)
#Html.RadioButton("", 1.0F, new { id = "btnOneDay" }) #(1.0F)

Dynamic checkboxes - Error: Collection is read-only

I'm quite new to MVC4 and my past experience with asp.net has been working with Webforms, so I think I need some careful hand holding. Thank you in advance!
I'm creating a simple web application that is similar to choosing lotto numbers. At the moment the user chooses whichever numbers they want (no limit, starting with "1") and posts it to the next page where I continue to do something with the numbers the user has chosen. The number of numbers - to choose from is dynamic and represented by checkboxes.
The problem is that when the view is submitted, I get the error page "Collection is read-only."
Model - LottoNumbers.cs
bool[] numbers is to store which numbers the user has checked.
namespace Lotto.Models
{
public class LottoNumbers
{
public string name { get; set; }
public bool[] numbers { get; set; }
public LottoNumbers() {
numbers = new bool[49];
}
public LottoNumbers(int limit)
{
numbers = new bool[limit];
}
}
}
in the HomeController.cs ...
I declared LottoNumbers ln, and
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Lotto.Models;
namespace Lotto.Controllers
{
public class HomeController : Controller
{
public LottoNumbers ln;
public ActionResult Index()
{
return View();
}
public ActionResult SetNumbers()
{
ln = new LottoNumbers(30);
// 30 checkboxes will be generated on the view
return View(ln);
}
[HttpPost]
public ViewResult SetNumbers(LottoNumbers l)
{
// get checkbox values
return View();
}
}
}
View - SetNumbers.cshtml
#model Lotto.Models.LottoNumbers
#{
ViewBag.Title = "SetNumbers";
}
<h2>SetNumbers</h2>
#using (Html.BeginForm()) {
<div>
#Html.LabelFor(m => m.name)
#Html.EditorFor(m => m.name)
</div>
<div id="numberlist">
#for (int i = 0; i < Model.numbers.Length; i++)
{
<div class="item-number" style="">
#Html.EditorFor(m => m.numbers[i])
<label class="lbl-number" for="numbers[#i]">#(i+1)</label>
</div>
}
</div>
<div style="clear:both;">
<input type="reset" value="Reset everything" />
<input type="submit" value="Submit" />
</div>
}
Change your array to a list.
public string Name { get; set; }
public List<bool> Numbers { get; set; }
public LottoNumbers()
{
Numbers = new List<bool>();
for (var i = 0; i < 40; i++)
{
Numbers.Add(false);
}
}
public LottoNumbers(int limit)
{
Numbers = new List<bool>();
for (var i = 0; i < limit; i ++)
{
Numbers.Add(false);
}
}
then your view would be
#using (Html.BeginForm())
{
<div>
#Html.LabelFor(m => m.Name)
#Html.EditorFor(m => m.Name)
</div>
<div id="numberlist">
#for (var i = 0; i < Model.Numbers.Count; i++)
{
<div class="item-number" style="">
#Html.CheckBox("Numbers[" + i.ToString() + "]")
<label class="lbl-number" for="numbers[#(i + 1)]">#(i + 1)</label>
</div>
}
</div>
<div style="clear:both;">
<input type="reset" value="Reset everything" />
<input type="submit" value="Submit" />
</div>
}
Null Reference Exception
You are most likely getting the null reference exception after submitting because you are not passing a model back to the view. You set up your page to expect a LottoNumbers model.
[HttpPost]
public ViewResult SetNumbers(LottoNumbers l)
{
// get checkbox values
return View(); //Nothing being passed to the view
}
so after post when your code gets to here
#foreach (var numberBool in Model.Numbers)
it blows up as the Model is null. You can fix this in several ways depending on how you want your app to run. If you want the user to see a blank list of numbers after submit simply do this and add some sort of success message on post back
[HttpPost]
public ViewResult SetNumbers(LottoNumbers l)
{
//process stuff
ln = new LottoNumbers(30);
return View(ln);
}
you can also simply redirect the user back to the index page. Either way the error is caused because you are not passing in a model with numbers back to the view.
If you look at the stack trace of your "Collection is read only" error, you can see that it's happening during Model Binding, which is when it tried to recreate your LottoNumbers object from the data passed back from the form post.
You're getting the error because you're initialising your object with an array size using you're constructor that takes a parameter, but when it posts back the data, it doesn't know what size the array needs to be when it recreates the object.
To solve this, it would be better to use a List instead, and have the size as a property of your LottoNumbers object.
Using a List means you don't have to pre-initialise the array with a size. And having the size as a property means you can embed the size in a hidden input variable, so that it can be passed back to the controller, and it should correctly do the model binding.

How Do I carry dropdown value selected in Asp.net MVC

Hi I have Dropdown in Index page where user needs to select lists. Values are coming from Database. I took this dropdown value into session so I can carry this to Httppost.
Below is my code in Index page :
var activitydropdown = orderdata.uspApp_ActivityPageReportname(Convert.ToInt32(newid)).ToList();
List<SelectListItem> activitypage = new List<SelectListItem>();
if (activitydropdown != null && activitydropdown.Count > 0)
{
foreach (var activityresults in activitydropdown)
{
activitypage.Add(new SelectListItem
{
Text = activityresults.name,
Value = activityresults.id.ToString(),
});
}
}
ViewData["activitydropdown"] = activitypage;
Session["activitydropdown"] = activitypage;
And this is my code in view :
#using (Html.BeginForm("Index", "Automation", new { step = "2" }, FormMethod.Post, new { id = "frmIndex" }))
{
#Html.DropDownList("DrpaActivity", ViewData["activitydropdown"] as List<SelectListItem>, "All", new { style = "margin-left:694px;margin-bottom:20px;", onchange = "submit();" })
Now when user selects list from dropdown, i need to carry that text to my httpost index. Now in httpost index, in debug mode if i see this code :
var sessionlistautomation = Session["activitydropdown"];
I can see text and value and selected is false for every item. So how can i carry text here selected from Index to httpost, so when user selects list from dropdown, it stores that text value.
It will be available in your Request i.e.
Request["DrpaActivity"]
However I would strongly advise using ViewModels instead as they're typesafe, less room for error and easier to use.
If you create a view model, like below:
public class AViewModel
{
public string DrpaActivity { get; set; }
public List<SelectListItem> ActivitySelectList { get; set; }
}
In your Index you can return it like this:
public ActionResult Index()
{
var model = new AViewModel();
// set the select list i.e.
model.ActivitySelectList = // get from db etc
return View(model);
}
Then in your view declare the model at the top
#model AViewModel
...
Set your dropdown like this:
#Html.DropDownListFor(m => m.DrpaActivity, Model.ActivitySelectList as List<SelectListItem>, "All", new { style = "margin-left:694px;margin-bottom:20px;", onchange = "submit();" })
You can then get your selected drop-down in your post as follows:
[HttpPost]
public ActionResult Index(AViewModel model)
{
var isValid = model.DrpaActivity;
return View(model);
}

Create DropDownListFor from SelectList with default value

I have a dropdownlistfor:
#Html.DropDownListFor(model => model.Item.Item.Status, new SelectList(#Model.AllStatus, "id", "Description"), new { id = "statusDropdown" })
#Html.ValidationMessageFor(model => model.Item.Item.Status)
HTML output:
<select id="statusDropdown" class="valid" name="Item.Item.Status" data-val-required="The Status field is required." data-val-number="The field Status must be a number." data-val="true">
<option value="2">Completed by Admin</option>
<option value="3">General Error</option>
<option value="4">New</option>
</select>
How can I update this code to set a default selected option? E.G.
<option value="4" selected>New</option>
I tried:
#Html.DropDownListFor(model => model.Item.Item.Status, new SelectList(#Model.AllStatus, "id", "Description",#Model.SelectedStatusIndex), new { id = "statusDropdown" })
#Model.SelectedStatusIndex has a value of 4, but does not change the default option to New.
I also tried:
#Html.DropDownListFor(model => model.SelectedStatusIndex, new SelectList(#Model.AllStatus, "id", "Description"), new { id = "statusDropdown" })
#Html.ValidationMessageFor(model => model.Item.Item.Status)
This selects the default option "New", but model.Item.Item.Status is not set by the dropdown on HTTP POST.
Other Detail:
model.Item.Item.Status is an int. #Model.AllStatus is a SQL table that lists all available status options.
There exist already some discussions about that here or there. One of the problems might be using a different type than string for the key value. I had similar problems in past and I know that i solved it like this - explicitly setting the Selected property when preparing the list (in your case, AlLStatus).
Would mean, for your case (in controller action):
IEnumerable<SelectListItem> selectList =
from s in allStatus // where ever you get this from, database etc.
select new SelectListItem
{
Selected = (s.id == model.Item.Item.Status),
Text = cs.Description,
Value = s.id.ToString()
};
model.AllStatus = selectList;
This is in addition to the answers above. This is how I would have done it.
The view model is there to represent your data. So for a single drop down list I would have the following:
public class MyViewModel
{
public int StatusId { get; set; }
public IEnumerable<Status> Statuses { get; set; }
}
And the Status class would look like this:
public class Status
{
public int Id { get; set; }
public string Description { get; set; }
}
The controller's action method to handle the view:
public class MyController
{
private readonly IStatusService statusService;
public MyController(IStatusService statusService)
{
this.statusService = statusService;
}
public ActionResult MyActionMethod()
{
MyViewModel viewModel = new MyViewModel
{
Statuses = statusService.GetAll(),
StatusId = 4 // Set the default value
};
return View(viewModel);
}
}
The view will look like this:
#model MyProject.ViewModels.MyViewModel
#Html.DropDownListFor(
x => x.StatusId,
new SelectList(Model.Statuses, "Id", "Description", Model.StatusId),
"-- Select --"
)
#Html.ValidationMessageFor(x => x.StatusId)
There you go.
I ended up using a variant of thomasjaworski's answer.
View:
#Html.DropDownListFor(model => model.SelectedStatusIndex, new SelectList(#Model.StatusSelectList, "Value", "Text"), new { id = "statusDropdown" })
ViewModel constructor
StatusSelectList = AllStatus.Select(x =>
new StatusSelectListItem
{
Text = x.Description,
Value = x.id.ToString()
}).ToList();
this.SelectedStatusIndex = 2;//Default Status is New
Controller on HTTP POST
I set model.Item.Item.Status seperately from the dropdown itself:
model.Item.Item.Status = model.SelectedStatusIndex;
because the dropdown set's the value of the expression passed as the first argument:
#Html.DropDownListFor(model => model.SelectedStatusIndex, new SelectList(#Model.StatusSelectList, "Value", "Text"), new { id = "statusDropdown" })
In this case model.SelectedStatusIndex is what is set by the dropdown. This controller implementation is what I found to be tricky.
You can use "Insert" for adding default value of Dropdown and add it to your Dynamic list :
By this way you don't need to use Razor in your View.
List<Y> m = X.GetList();
m.Insert(0, new Y{ Name = "--Select--" });
SelectList ProductSizeList = new SelectList(_context.Sizes, "SizeId", "SizeName");
//after you create the selectList you have to create the default select list item
SelectListItem AllSize = new SelectListItem("All Size", "0");
// and after this you add this item to the begin of the selectlist
ViewData["SizeId"] = ProductSizeList.Prepend(AllSize);
I assign DropDownListFor's expression with value which is already defined in List. It works for me. I use List<SelectListItem> Model.IncidentPriorityList for ddwn's selectlist.
Model.incident.INCIDENT_PRIORITY_ID = Model.DefaultParameterId;
#Html.DropDownListFor(m => m.incident.INCIDENT_PRIORITY_ID, Model.IncidentPriorityList, "Select", new { #class = "form-control selectpicker", id = "drpPriority", #required = true })

Categories