MVC SelectLists using ViewBag SelectedItem not being set - c#

I have the following code:
public class OrganisationController : Controller
{
//
// GET: /Organisation/
public ActionResult Update()
{
var fisherman = new RoleType {Id = 1, Name = "Fisherman"};
var manager = new RoleType {Id = 2, Name = "Manager"};
var deckhand = new RoleType {Id = 3, Name = "Deckhand"};
var roleTypes = new List<RoleType>
{
fisherman, manager, deckhand
};
ViewBag.Roles = new SelectList(roleTypes, "Id", "Name");
return View(
new Organisation
{
Name = "Fish Co.",
People = new List<Person>
{
new Person
{
Name = "Squid",
RoleType = fisherman
},
new Person
{
Name = "Michael",
RoleType = manager
},
new Person
{
Name = "John",
RoleType = deckhand
}
}
});
}
[HttpPost]
public ActionResult Update(Organisation org)
{
return View();
}
}
public class Organisation
{
public string Name { get; set; }
public IList<Person> People { get; set; }
}
public class Person
{
public string Name { get; set; }
public RoleType RoleType { get; set; }
}
public class RoleType
{
public int Id { get; set; }
public string Name { get; set; }
}
In Update.cshtml
#model Models.Organisation
<form action="" method="post" enctype="multipart/form-data">
#Html.EditorFor(x => x.Name)
#Html.EditorFor(x => x.People)
<input type="submit"/>
</form>
In the EditorTemplates Person.cshtml:
#model Models.Person
#Html.EditorFor(x => x.Name)
#if(Model != null)
{
#Html.DropDownListFor( x => x.RoleType.Id, (SelectList)ViewBag.Roles)
}
I was expecting to be able to get to a page where I can update the organisation name, the people names and their roles. The trouble is that I can't get the selected item to be set for the dropdowns. I thought x => x.RoleType.Id would do this for me.
Does anyone know how I can get this to work?

Try this constructor: SelectList Constructor (IEnumerable, String, String, Object)
public SelectList(
IEnumerable items,
string dataValueField,
string dataTextField,
Object selectedValue
)
Something like this:
#Html.DropDownListFor( x => x.RoleType.Id, new SelectList((List<RoleType>)ViewBag.Roles, "Id", "Name", Model.RoleType.Id))

Related

In a HTML helper dropdownlist, how to get foreign key data?

I am new to ASP.NET. My form look like this
This code display role in Form
#Html.DropDownList("id", (IEnumerable<SelectListItem>)ViewBag.lis, null, new { #class = "form-control" })
in Controller
public ActionResult register()
{ //
ViewBag.lis = new SelectList(new dbdemoEntities().Roles, "id", "name");
return View();
}
ROLE CLASS
public partial class Role
{
public int Id { get; set; }
public string name { get; set; }
public virtual Register Register { get; set; }
}
Register class
public partial class Register
{
public int Id { get; set; }
public string name { get; set; }
public string email { get; set; }
public string password { get; set; }
public Nullable<int> phone_no { get; set; }
public virtual Role Role { get; set; }
}
The problem is that I can get all data except for Role. The role is null. How do I get the Role ID?
[HttpPost]
public ActionResult register(Register obj)
{
using(var db = new dbdemoEntities())
{
var data = new Register()
{
email = obj.email,
name = obj.name,
password = obj.password,
phone_no = obj.phone_no,
Role = obj.Role
};
db.Registers.Add(data);
db.SaveChanges();
ViewBag.register = "Your account has been registered!";
}
return PartialView();
}
I think the problem is that I should write model => model.role like the example of the name here.
#Html.EditorFor(model => model.name, new { htmlAttributes = new { #class = "form-control" } })
here is what I updated now
ViewBag.lis = new SelectList(new dbdemoEntities().Roles, "Id", "name");
In HTML
Problem after update:
After changing
Role = db.Roles.Single(r => r.Id == obj.Role.Id)
Here is another error
Try this:
Change: ViewBag.lis = new SelectList(new dbdemoEntities().Roles, "id", "name");
to
ViewBag.lis = new SelectList(new dbdemoEntities().Roles, "Id", "name");
and then:
#Html.DropDownList(model => model.Role.Id, (IEnumerable<SelectListItem>)ViewBag.lis, null, new { #class = "form-control" })
and also make a constructor for Register class:
public partial class Register
{
public Register()
{
this.Role = new Role();
}
public int Id { get; set; }
public string name { get; set; }
public string email { get; set; }
public string password { get; set; }
public Nullable<int> phone_no { get; set; }
public virtual Role Role { get; set; }
}
====== Update =======
Change the action like this:
[HttpPost]
public ActionResult register(Register obj)
{
using(var db = new dbdemoEntities())
{
var data = new Register()
{
email = obj.email,
name = obj.name,
password = obj.password,
phone_no = obj.phone_no,
Role = db.Roles.Single(r=> r.Id == obj.Role.Id)
};
db.Registers.Add(data);
db.SaveChanges();
ViewBag.register = "Your account has been registered!";
}
return PartialView();
}
Change to this this if you want to post Register.Id property:
#Html.DropDownListFor(model => model.Id,(SelectList) ViewBag.list,new { #class="form-control"})

Enter data in a view using the dynamic model

In view I want display data from list ucz and insert data to listaOcen. display the list of ucz works but I have no idea to input data into list listaOcen
#using biblioteka;
#model dynamic
<tr>
#for (int i = 0; i < Model.dl;i++ )
{
td>#Model.Uczniowie[i]</td>
<td>
#Html.DropDownList(Model.listaOcen[i], new[] { //doesnt work
new SelectListItem() { Text = "5", Value = "5" },
new SelectListItem() { Text = "4+", Value = "4.75" },
}, "Select option")
<td>
</tr>
}
Controller:
public ActionResult Add(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var dataContext = db.Uczniowie;
var ucz = dataContext.Where(m => m.KlasaId == id)
.Select(m => m.Nazwisko + " " + m.Imie);
List<double> listOfOcena = new List<double>();
dynamic mymodel = new ExpandoObject();
mymodel.Uczniowie = ucz.ToList();
mymodel.dl = ucz.ToList().Count;
mymodel.listaOcen = listOfOcena;// enter the data from DropDownLists
return View(mymodel);
It is model.
public class Ocena
{
public string IdUcznia { get; set; }
public string Id { get; set; }
public string Przedmiot { get; set; }
public double Wartosc { get; set; }
public double waga { get; set; }
public DateTime? Data { get; set; }
public string Rodzaj { get; set; }
public string Opis { get; set; }
}
Please help :)
Robert, first of all try to avoid dynamic model. Create a viemodel for your action. e.g.
public class StudentMarkAssignViewModel
{
public long StudentId { get; set; }
public string FullName { get; set; }
public double Mark { get; set; }
}
then fill it in your action
[HttpGet]
public ActionResult Add(string id)
{
var model = new StudentMarkAssignViewModel[]
{
new StudentMarkAssignViewModel {StudentId = 1, FullName = "Martin", Mark = 0 },
new StudentMarkAssignViewModel {StudentId = 2, FullName = "Robert", Mark = 5 }
};
//here i use hardcoded valuse, but you should get them from your db
return View(model);
}
after that you can render list of your students and assign them marks and submit it to the server
#using WebApplication100.Models
#model StudentMarkAssignViewModel[]
#using (Html.BeginForm("Add", "StudentMarks", FormMethod.Post))
{
<table>
#for (var index = 0; index < Model.Length; index++)
{
<tr>
#Html.HiddenFor(x => Model[index].StudentId)
#Html.HiddenFor(x => Model[index].FullName)
<td>#Model[index].FullName</td>
<td>
#Html.DropDownListFor(x => Model[index].Mark, new SelectListItem[]{
new SelectListItem{ Value = "0", Text = "Not Rated", Selected = Model[index].Mark == 0 } ,
new SelectListItem{ Value = "5", Text = "5" , Selected = Model[index].Mark == 5 } ,
new SelectListItem{ Value = "4.75", Text = "4+" , Selected = Model[index].Mark == 4.75 }
})
</td>
</tr>
}
</table>
<button type="submit">submit</button>
}
after you submit the form, you'll get list of students and their marks on the server
[HttpPost]
public ActionResult Add(StudentMarkAssignViewModel[] marksModel)
{
/* do whatever you need with your model*/
return RedirectToAction("Index");
}
that's all. I hope you'll get the point.

DropDownListFor not pre-selecting value from model

Controller Code:
AccountsDetailsViewModel vOwnerVM = Mapper.Map<VehicleOwner, AccountsDetailsViewModel>(vOwner);
AccountsDetailsAccountViewModel vOwnerDetailsVM = Mapper.Map<VehicleOwner, AccountsDetailsAccountViewModel>(vOwner);
ViewBag.FleetType = new SelectList(VehicleOwnerFleetTypeFactory.GetTypes().OrderBy(l => l.Type), "Id", "Type");
vOwnerVM.AccountDetails = vOwnerDetailsVM;
Main ViewModel Code:
public class AccountsDetailsViewModel
{
public AccountsDetailsAccountViewModel AccountDetails { get; set; }
}
Main View Code
#model X.Views.Accounts.ViewModels.AccountsDetailsViewModel
#Html.Partial("DetailsAccount", #Model.AccountDetails)
Partial ViewModel Code:
[DisplayName("Fleet Type")]
public int FleetType { get; set; }
Partial View Code
#model X.Views.Accounts.ViewModels.AccountsDetailsAccountViewModel
#Html.DropDownListFor(model => model.FleetType,
(IEnumerable<SelectListItem>)ViewBag.FleetType)
#Html.DisplayFor(model => model.FleetType) (FOR DEBUG)
VehicleOwnerFleetType class
public class VehicleOwnerFleetType
{
public int Id { get; set; }
public string Type { get; set; }
}
public class VehicleOwnerFleetTypeFactory
{
static readonly VehicleOwnerFleetType[] Types = new VehicleOwnerFleetType[] {
new VehicleOwnerFleetType() {Id = 0, Type = "Unknown"},
new VehicleOwnerFleetType() {Id = 1, Type = "HGV"},
new VehicleOwnerFleetType() {Id = 2, Type = "Car"},
new VehicleOwnerFleetType() {Id = 3, Type = "Van"},
new VehicleOwnerFleetType() {Id = 4, Type = "Mixed"}
};
public static VehicleOwnerFleetType[] GetTypes()
{
return Types;
}
public static VehicleOwnerFleetType GetType(int id)
{
return Types.FirstOrDefault(m => m.Id == id);
}
}
Regardless of what the database shows, the dropdown does not display the correct value from the model, only ever the top value in the list.
However if I select a value and then submit the form to save the changes to the database, it does submit the correct value.
When returning the view of the viewmodel in the controller, the values mirror the database exactly, I cannot figure out why it is doing this.
Edit: The 'Sectors' dropdown is the ONLY one that auto-selects the correct value.
The problem is likely caused by the fact that your selectlist, and your VM's member variable have the same names.
model.FleetType
and
(IEnumerable<SelectListItem>)ViewBag.FleetType
Try to rename the select list to FleetTypeList or similar
Works fine for me. Check if you pass the model to the view.
#using WebApplication2.Controllers
#model WebApplication2.Controllers.MyModel
#{
ViewBag.Title = "Home Page";
ViewBag.FleetType = new SelectList(
VehicleOwnerFleetTypeFactory.GetTypes().OrderBy(l => l.Type),
"Id",
"Type");
}
<div>
<h2>---------------------------</h2>
#Html.DropDownListFor(model => model.FleetType,
(SelectList)ViewBag.FleetType)
<h2>---------------------------</h2>
</div>
and
using System.Web.Mvc;
namespace WebApplication2.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyModel { FleetType = 2 });
}
}
public class MyModel
{
public int FleetType { get; set; }
}
public class VehicleOwnerFleetTypeFactory
{
public static FleetType[] GetTypes()
{
return new[]
{
new FleetType {Id = 1, Type = "Type 1"},
new FleetType {Id = 2, Type = "Type 2"},
new FleetType {Id = 3, Type = "Type 3"}
};
}
}
public class FleetType
{
public int Id { get; set; }
public string Type { get; set; }
}
}

Html.ListBoxFor not selecting Items

Firstly I'm using MVC 2.0. I am having trouble getting a selection with a Multiselect listbox on the postback to my controller. Here is my Code:
Model
public class TestModel
{
public MultiSelectList AvailableTestTypes { get; set; }
public List<TestType> SelectedTestTypes { get; set; }
}
public class TestType
{
public long Id { get; set; }
public string Name { get; set; }
public bool isActive { get; set; }
}
Controller
public ActionResult Index(TestModel model)
{
if (model == null) model = new TestModel();
List<TestType> testList = new List<TestType>()
{
new TestType() { Id = 1, Name = "TESTING", isActive = true },
new TestType() { Id = 2, Name = "TESTING2", isActive = true },
new TestType() { Id = 3, Name = "TESTING3", isActive = true }
};
model.AvailableTestTypes = testList; //TODO: Fetch From Repository
return View(model);
}
[HttpPost]
public ActionResult PostForm(TestModel model)
{
List<long> act = model.SelectedTestTypes != null ? model.SelectedTestTypes.Select(x => x.Id).ToList() : new List<long>();
View
<%= Model != null && Model.AvailableTestTypes != null ?
Html.ListBoxFor(x => x.SelectedTestTypes,
new MultiSelectList(Model.AvailableTestTypes, "Id", "Name", Model.SelectedTestTypes),
new { #id = "testListboxId", #class = "blah", #title = "title" }) : null%>
After the Post to the Controller my Selected List count is 0 no matter how many I choose...
What am I getting wrong here?
I tried a few different solutions such as
Challenges with selecting values in ListBoxFor
but nothing worked :(
The difference between your script and the example in the other script, is the fact that you're trying to bind to a List, instead of a int[].
When you want to populate a Multiselect Listbox, you will have to set a DataValueField and a DataTextfield, otherwise no value is set.
model.AvailableTestTypes = new MultiSelectList(testList, "Id", "Name);
Then try using this class:
public class TestModel
{
public MultiSelectList AvailableTestTypes { get; set; }
public int[] SelectedTestTypes { get; set; }
}
In your PostForm action, you can use the Ids to retrieve the TestTypes.

Html.DropDownlistFor selectedValue

Having a hard time getting this dropDownList to Bind. This is simply a list of states. The Model.State is "TX", but my dropdownlist is showing "AK", which is the first value in the list. Any thoughts?
<%: Html.DropDownListFor(
model => model.State,
new SelectList(
muniSynd.getStatecodesDropDown(),
"Value",
"Text",
Model.State.ToString().Trim()
)
)
%>
In my muniSynd class, which is a wrapper of my dataContext.....
public IList<StateCodeViewModel> getStatecodesDropDown()
{
var states = from p in this._MuniDc.Statecodes
select new StateCodeViewModel
{
Value = p.Statecode1.ToString().Trim(),
Text = p.Statecode1.ToString().Trim()
};
return states.ToList();
}
public class StateCodeViewModel
{
public string Value{get;set;}
public string Text{get;set;}
}
Im using LinqToSQL, here is the object
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Statecodes")]
public partial class Statecode
{
private string _Statecode1;
public Statecode()
{
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Name="Statecode", Storage="_Statecode1", DbType="NVarChar(3)")]
public string Statecode1
{
get
{
return this._Statecode1;
}
set
{
if ((this._Statecode1 != value))
{
this._Statecode1 = value;
}
}
}
}
I've tried to replicate your problem, but my example below works fine:
public class HomeController : Controller
{
public ActionResult Index()
{
var viewModel = new IndexViewModel();
viewModel.State = "TX";
return this.View(viewModel);
}
public static IList<StateCodeViewModel> getStatecodesDropDown()
{
var stateCodes = new List<string> { "AX", "GH", "TX" };
var states = from p in stateCodes
select new StateCodeViewModel
{
Value = p,
Text = p
};
return states.ToList();
}
}
public class IndexViewModel
{
public string State { get; set; }
}
public class StateCodeViewModel
{
public string Value { get; set; }
public string Text { get; set; }
}
View
#using MVCWorkbench.Controllers
#model IndexViewModel
#{
ViewBag.Title = "title";
}
#Html.DropDownListFor(model => model.State,
new SelectList(HomeController.getStatecodesDropDown(),
"Value",
"Text",
Model.State.ToString().Trim()
)
)
Not sure what to suggest other then check that the State value is in the dropdown list. Also this could be a case-sensitivity issue perhaps?

Categories