I want to get dropdown list with values from table. I'm have model:
namespace MobileService.Models
{
public class Mobile
{
public int Id { get; set; }
public string Model { get; set;}
Public string EMEI { get; set ;}
public int MasterId { get; set; }
public List<Master> MasterList { get; set; }
}
public class Master
{
public int Id { get; set; }
public string Name { get; set; }
}
}
In controller I creat action for this model:
public ActionResult Create()
{
return View();
}
In view:
#model MobileService.Models.Mobile
#using (Html.BeginForm()) {
#Html.EditorFor(model => model.Model)
#Html.EditorFor(model => model.EMEI )
// And here i want to display a dropdown list with all available masters
<button type="submit" class="btn btn-primary">Creat</button>
}
But it always tell me that Model.MasterList is null . But why? In model i told to get list from another model (public List MasterList { get; set; }). Why is it null?
This code is in VB. In the beginning even i looked for a lot of time this is the simple solution i found.
Convert the model into list of selectListItems
Dim lstEmpTypes As New List(Of SelectListItem)
lstTicketWrTypes.Add(New SelectListItem With {.Text = row("Something"), .Value = row("Something")})
'Then load it into a ViewBag
ViewBag.EmpTypes = lstEmpTypes
'And in you View
#Html.DropDownList("selectWrType", New SelectList(ViewBag.EmpTypes , "Value", "Text"), New With {.class = "span3"})
When you query for Mobile you need to Include("MasterList"), or turn lazy loading on on your context (not recommended)
The answer for me was to add this to controller:
public ActionResult Create()
{
ViewBag.MasterId = new SelectList(db.Masters, "Id", "Name");
return View();
}
Then in view to show droplist:
#Html.DropDownList("MasterId", null, htmlAttributes: new { #class = "form-control" })
Thnx ZikO who let me now that list didn't loaded automatical.
Related
I’m trying to create a team of players, there are 4 players per team so I have 4 select lists that contain and populate the players in the league. When I go to save the team the error:
"There is no ViewData item of type 'IEnumerable' that has the key 'Skip'`
The CreateTeam controller:
public ActionResult CreateLeagueTeam(int? id)
{
int leagueId = id.Value;
League league = db.Leagues.Include(x=>x.Members).First(l=> l.Id == leagueId);
var leagueMemberList = league.Members.ToList();
var leagueMemberSelectListItems = new List<SelectListItem>();
foreach(Member m in leagueMemberList)
{
leagueMemberSelectListItems.Add(new SelectListItem() { Text = m.FirstName + " " + m.LastName, Value = m.Id.ToString() });
}
ViewData["leagueMemberList"] = leagueMemberSelectListItems;
return View();
}
the HTTP POST ActionResult:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateLeagueTeam([Bind(Include = "skip")] Team team)
{
team.IsBonspiel = false;
team.IsLeague = true;
// team.Name = team.Skip.LastName;
team.YearActive = games.getSeasonYear();
//finds and sets the league ID for the team
int leagueId = (int)Session["leagueId"];
League league = db.Leagues.Find(leagueId);
team.League = league;
if (ModelState.IsValid)
{
db.Teams.Add(team);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(team);
}
Finally the view where the Error is getting thrown:
<div class="form-group">
#Html.Label("Skip", null, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Skip, (IEnumerable<SelectListItem>)ViewBag.leagueMemberList, htmlAttributes: new { #class = "control-label col-md-2" })
</div>
</div>
Also the Team Model:
public class Team: Entity
{
[Required]
public bool IsBonspiel { get; set; }
[Required]
public bool IsLeague { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int YearActive { get; set; }
public int? SkipId { get; set; }
public Member Skip { get; set; }
public string BonspielSkip { get; set; }
public List<BonspielTeamMember> BonspielMembers { get; set; }
public List<Member> Members { get; set; }
public List<Game> Games { get; set; }
public Bonspiel Bonspiel { get; set; }
public League League { get; set; }
}
The are multiple errors with your code.
Skip is a complex object and you cannot bind a <select> to a
complex object. Based on your view, it should be
#Html.DropDownListFor(m => m.SkipId, ...)
You do not have a ViewBag property named leagueMemberList
(change the controller code to ViewBag.leagueMemberList =
leagueMemberSelectListItems; or the view code to
#Html.DropDownListFor(m => m.SkipId,
(IEnumerable<SelectListItem>)ViewData["leagueMemberList"], ...)
You do not reassign the value of ViewData["leagueMemberList"] (or
ViewBag.leagueMemberList) in the POST method if ModelState is
invalid and you return the view, which will result in a different
exception because it will be null (Refer this
question/answer
Your [Bind(Include = "skip")] code in the POST method means that
ModelState will always be invalid because you exclude every
property of the model from binding (except Skip and you dont post
any values for Skip)
You added data to "ViewData" but you try to access from ViewBag.
You should know ViewData is different with ViewBag.
Therefore you try to change this line:
ViewData["leagueMemberList"] = leagueMemberSelectListItems;
to => ViewBag.leagueMemberList = leagueMemberSelectListItems;
I'm trying to get an integer out of a listitem.
i first collected the items to put in the dropdownlist and then i try to take the integer out of the items
It worked before(got a nice string with interests in database), but more often than not, i get an error for trying to make an integer out of a listitem
I would like to solve this so it works 100% of the time so it doesn't look like an incomplete project when i present this.
<div class="form-group">
#Html.LabelFor(m => m.InteresseLijst1, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.Interesse1, Model.InteresseLijst1)
</div>
</div>
these are the used properties from my viewmodel
[Display(Name = "Interesse 1")]
public SelectList InteresseLijst1 { get; set; }
[Display(Name = "Interesse 2")]
public SelectList InteresseLijst2 { get; set; }
public int Interesse1 { get; set; }
public int Interesse2 { get; set; }
public string Interesses { get; set; }
this is my Get-action to register where i make my selectlists
public ActionResult Register()
{
RegisterViewModel rvm = new RegisterViewModel();
List<Categorie> categorielijst = CategoryRepository.GetCategories();
rvm.InteresseLijst1 = new SelectList(categorielijst, "CategoryId", "CategoryName");
rvm.InteresseLijst2 = new SelectList(categorielijst, "CategoryId", "CategoryName");
return View(rvm);
}
and this is my post where i use the integers collected from the selectlist.
I convert to json to keep it in my database for further comparison on other parts of the site.
#region verschillend
if(model.Interesse1 != model.Interesse2)
{
int[] interesses = new int[2] { model.Interesse1, model.Interesse2 };
string sInteresses = JsonConvert.SerializeObject(interesses);
model.Interesses = sInteresses;
//other code
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
#endregion
With a bit of a workaround, i managed to get rid of the error. I changed the way the items are displayed by adding properties to items in a list. Then i collect the values of the properties in my controller with Request.Form["propertyname"] and it worked
As a developer asp.net web site I've created project. And Scaffold it for controller creation with DataBase First approach.
There are two EF data model objects: Personal and PersonalDetails.
using System;
using System.Collections.Generic;
public partial class personalDetails
{
public int personID { get; set; }
public Nullable<bool> rehber { get; set; }
//many others, removed for easy to understand
}
public partial class personal
{
public personal()
{
this.passportDetails = new HashSet<passportDetails>();
}
public string name { get; set; }
public string surname { get; set; }
public int ID { get; set; }
public Nullable<short> politicalPartyID { get; set; }
public Nullable<short> familyStatusID { get; set; }
public virtual familyStatus familyStatus { get; set; }
public virtual politicalParties politicalParties { get; set; }
}
For a business logic it's necessary to create viewModel, because on view there are some fields from personal and some fields from personalDetils object. And I added viewModel class.
public class SocialViewModels
{
public personalDetails personalDetails { get; private set; }
public personal personal { get; private set; }
public SelectList marriageStatus { get; private set; }
public SelectList partyList { get; private set; }
public SocialViewModels()
{
}
public SocialViewModels(personalDetails _personalDetails, personal _personal, IEnumerable _marriageStatus, IEnumerable _partyList)
{
personalDetails = _personalDetails;
personal=_personal;
marriageStatus = new SelectList(_marriageStatus, "ID", "familyStatusName", personal.familyStatusID);
partyList = new SelectList(_partyList, "ID", "partyName", personal.politicalPartyID);
}
}
This ViewModel works well for get Details operation. Controller and View below:
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
personalDetails personalDetails = db.personalDetails.Find(id);
SocialViewModels svm = new SocialViewModels(personalDetails, personalDetails.personal, db.familyStatus, db.politicalParties);
if (personalDetails == null)
{
return HttpNotFound();
}
return View(svm);
}
Details view:
#model kadrws.ViewModels.SocialViewModels
#Html.DisplayFor(model => model.personal.familyStatus.familyStatusName)
#Html.DisplayFor(model => model.personal.politicalParties.partyName)
#Html.DisplayFor(model => model.personalDetails.rehber)
<p>
#Html.ActionLink("Redaktə et", "Edit", new { id = Model.personal.ID })
</p>
But problem with Edit post method:
// GET: personalDetails/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
personalDetails personalDetails = db.personalDetails.Find(id);
SocialViewModels svm = new SocialViewModels(personalDetails, personalDetails.personal, db.familyStatus, db.politicalParties);
if (personalDetails == null)
{
return HttpNotFound();
}
return View(svm);
}
// POST: personalDetails/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "personID,rehber, partyID, familyStatusID")] SocialViewModels scm )
{
if (ModelState.IsValid)
{
//do
}
ViewBag.personID = new SelectList(db.personal, "ID", "name", scm.personal.ID);
return View(scm);
}
Edit view :
#model kadrws.ViewModels.SocialViewModels
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.personalDetails.personID)
#Html.DropDownList("personal_familyStatusID", Model.marriageStatus)
#Html.DropDownList("personal_politicalPartyID", Model.partyList)
#Html.EditorFor(model => model.personalDetails.rehber)
<input type="submit" value="Save" class="btn btn-default" />
}
Problem is that, SocialViewModels is null.
I also search similar behaviors in Google. Dozen this like problems. Please, help to understand where is problem in this code...
Firstly, properties marriageStatus and partyList will be null because they are typeof SelectList (and you don't generate forms controls for each property of each SelectListItem in the collection - and nor should you). You do however generate <select> elements with names personal_familyStatusID and personal_politicalPartyID but your model does not include properties with those names.
Secondly, properties personal and personalDetails are null because you have include a [Bind] attribute which specifically excludes then (it would need to be Bind(Include = "personal, personalDetails")].
However your misunderstanding what a view model is and how to use it. It is not just a class that holds multiple instances of data models, it should contain only those properties you display/edit in the view. Based on the 4 controls you have included in your form, your view model should be
public class SocialViewModels
{
public int ID { get; set; }
public Nullable<bool> Rehber { get; set; }
public int MarriageStatus { get; set; }
public int Party { get; set; }
public SelectList MarriageStatusList { get; set; }
public SelectList partyList { get; set; }
}
Side note: Do not use private set on your SelectList properties. If you needed to return the view because ModelState was invalid, then you could never repopulate them
Then in the GET method, initialize a new instance of the view model, set its properties from the data models and return it to the view
public ActionResult Details(int? id)
{
....
personalDetails personalDetails = db.personalDetails.Find(id);
....
SocialViewModels model = new SocialViewModels()
{
ID = personalDetails.personID,
Rehber = personalDetails.rehber,
MarriageStatus = personalDetails.personal.familyStatusID,
....
MarriageStatusList = new SelectList(db.familyStatus, "ID", "familyStatusName"),
....
};
return View(model);
}
Side note: Your naming is extremely confusing (one minute its familystatus, then next its marriagestatus) so not sure if I have interpreted it correctly.
Then in the view
#model kadrws.ViewModels.SocialViewModels
#using (Html.BeginForm())
{
..
#Html.HiddenFor(m => m.ID)
#Html.DropDownListFor(m => m.MarriageStatus, Model.MarriageStatusList)
....
#Html.EditorFor(m=> m.Rehber)
<input type="submit" value="Save" class="btn btn-default" />
}
And in the POST method
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(SocialViewModels model)
{
if (!ModelState.IsValid)
{
// repopulate your select lists
return View(model);
}
// Get your data models, map the view model properties it
// Save and redirect
}
I have found a little edge case for when the DropDownListFor will not bind the value in the viewmodel to the list.
The below code will NOT bind the value.
ViewModel
public class PersonViewModel
{
[Required]
public Title? Title { get; set; }
public IEnumerable<SelectListItem> TitleSelectList { get; set; }
}
Controller
public ActionResult Person()
{
return View(
new PersonViewModel
{
Title = Title.Mrs,
TitleSelectList = EnumHelper.GetSelectList(typeof(Title)),
});
}
View
#Html.DropDownListFor(model => model.Title, Model.TitleSelectList, "Please select...", new { #class = "form-control" })
Changing the property name fixes this.
Change the viewmodel to public Title? TitleTesting { get; set; } and update the rest of the code to match it will work.
I would be interested to know if this is a bug or a reserved word.
Which I'd expect to be implemented in .NET MVC, but trying to figure out how to actually do it. Currently on my ViewModel, I have (for example):
public class GroupPolicyViewModel
{
public int PolicyId { get; set; }
public int HistoryId{ get; set; }
public SelectList ProductList { get; set; } // tried this
public List<Product> ProductList1 { get; set; } // tried this
}
Whenever I try and auto-generate my View from this ViewModel, the ProductList gets ignored. Is there any way to auto-generate a DropDownList at all from the ViewModel?
With model
public class GroupPolicyViewModel
{
public int PolicyId { get; set; }
public int HistoryId{ get; set; }
public int SelectedProductId{ get; set; }
public List<Product> ProductList { get; set; }
}
You can create DropDownList
#Html.DropDownListFor(m => m.SelectedProductId,
new SelectList(Model.ProductList, "ProductId", "ProductName"))
Or if you have SelectList of products in your model
#Html.DropDownListFor(m => m.SelectedProductId, Model.ProductSelectList)
If you want some generated code, you need to use scaffolding option with providing data context class. Here is nice tutorial MVC Music Store
You can (from VS2010) when creating a new Controller and using Entity Framework. Specify in the wizard to include Entity Framework and Read/Write ops and the wizard will create both the controller and the views.
It'll generate code like this [there is more] in the controller:
public ActionResult Create()
{
ViewBag.CostCentre_ID = new SelectList(db.CostCentres, "ID", "Name");
ViewBag.Location_ID = new SelectList(db.Locations, "ID", "Name");
ViewBag.User_ID = new SelectList(db.UCMUsers, "User_ID", "EmployeeNo");
return View();
}
and this in the view:
<div class="editor-field">
#Html.DropDownList("User_ID", String.Empty)
#Html.ValidationMessageFor(model => model.User_ID)
</div>