Dropdownlist in MVC with Where cluase in entities - asp.net-mvc

I am new to MVC. I want to fill Dropdownlist only where Account_Type = "D".
Here is my Edit.cshtml
<div class="form-group">
#Html.LabelFor(model => model.Account_Code, "Account_Code", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("Account_Code", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Account_Code, "", new { #class = "text-danger" })
</div>
</div>
And here is my Edit Controller
public ActionResult Edit(int? id)
{
ViewBag.Account_Code = new SelectList(db.Chart_Of_Account, "Account_Code", "Account_Desc", student.Account_Code);
}

Use a .Where() clause to filter your data
public ActionResult Edit(int? id)
{
var accountCodes = db.Chart_Of_Account.Where(a => a.Account_Type == "D");
ViewBag.AccountCodeList = new SelectList(accountCodes , "Account_Code", "Account_Desc");
}
Note I have changed the name of the ViewBag property and removed the 3rd parameter of the SelectList contructor (its ignored when binding to a property)
Your view should be
#Html.DropDownListFor(m => m.Account_Code, (SelectList)ViewBag.AccountCodeList)

Related

DropDownListFor - need help defining "SelectedValue" property

I need help understanding how to set the SelectedValue property in HTML.DropDownListFor.
Here's what I have so far:
In another part of the model, MA is an int that is stored on the database.
In the Model:
public IList<SelectListItem> SelectListMA(int MA)
{
IList < SelectListItem > List = new List<SelectListItem>();
SelectListItem Item;
for(int i = 1; i <= 9; i++)
{
Item = new SelectListItem
{
Value = i.ToString(),
Text = i.ToString(),
Selected = i == MA
};
List.Add(Item);
}
return List;
}
In the controller:
ViewBag.MA = _Repository.SelectListMA(5);
And finally, in the View:
#Html.DropDownListFor(model => model.MA, new SelectList(ViewBag.MA, dataValueField: "Value", dataTextField: "Text"))
In the View the dropdown displays fine, however the default value is not being set and I am using the model to pass the original model for editing to View hence using ViewBag
Edit: Further details Requested - this is the full Controller that this belongs to.
private readonly IRacesRepos _RaceRepository;
public BaseTeamsController(IRacesRepos _Repository)
{
_RaceRepository = _Repository;
}
//sets the Model to the repository
public BaseTeamsController() : this(new ModelRaces()) { }
public ActionResult BEditPlayer(int ID)
{
Races_Players SelectedPlayer = _RaceRepository.GetPlayerBase(ID);
ViewBag.MA = _RaceRepository.SelectListMA(SelectedPlayer.MA);
ViewBag.ST = _RaceRepository.SelectListST(SelectedPlayer.ST);
ViewBag.AG = _RaceRepository.SelectListAG(SelectedPlayer.AG);
ViewBag.PA = _RaceRepository.SelectListPA((int)SelectedPlayer.PA);
ViewBag.AV = _RaceRepository.SelectListAV(SelectedPlayer.AV);
ViewBag.Race = _RaceRepository.GetRaceBase(SelectedPlayer.RaceID);
return View(SelectedPlayer);
}
And I am using MVC version 5, and ModelRaces is the name of the model that contains the code, MA is an int in the model from the database.
Full View
#model BB2020MVC.Models.Races_Players
#{
ViewBag.Title = "Add Player to " + ViewBag.RaceName;
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Add Player to #ViewBag.RaceName</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.PlayerID)
#Html.HiddenFor(model => model.RaceID)
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10 focus">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.MA, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.MA, new SelectList(ViewBag.MA, dataTextField: "Text", dataValueField:"Value") , new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.MA, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ST, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.ST, new SelectList(ViewBag.ST, dataTextField: "Text", dataValueField: "Value"), new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ST, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.AG, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.AG, new SelectList(ViewBag.AG, dataTextField: "Text", dataValueField: "Value"), new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.AG, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PA, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.PA, new SelectList(ViewBag.PA, dataTextField: "Text", dataValueField: "Value") ,new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PA, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.AV, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.AV, new SelectList(ViewBag.AV, dataTextField: "Text", dataValueField: "Value") ,new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.AV, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Cost, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Cost, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Cost, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.MaxQTY, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.MaxQTY, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.MaxQTY, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Cancel", "ViewRace", new { ID = Model.RaceID })
</div>
Edit: Been doing a bit of testing and reading, issue seems to be that the view is not selecting the selected value of model => model.MA yet the value is not null on editing so any value that has been selected by SelectListItem or SelectList is ignored.
Also passing any value into selectedValue other than a number or word (eg "1" or "Word", not a variable of type int or string) causes the item to not be selected.
Doesn't fix the issue but an interesting point.
Try this syntax:
in the view
#Html.DropDownListFor(model => model.MA, ViewBag.MA,"Select One", new { htmlAttributes = new { #class = "form-control" } })
in repository:
public SelectList SelectListMA(int MA)
{
var List = new List<SelectListItem>();
for(int i = 1; i <= 9; i++)
{
List.Add(new SelectListItem
{
Value = i.ToString(),
Text = i.ToString(),
});
}
return new SelectList(list, "Value", "Text",MA);
}
But you don't need to convert to List of SelectListItem your existed lists.
Just use retun new SelectList(yourlist, "yourvalueproperty", "yourtextproperty",);
The answer to this one lies between the keyboard and the screen.
Let me explain:
In the additional testing I had erroneously changed _RaceRepository.GetPlayerBase(ID) to another function that generates a new base for the record. (an impromptu Mutation Test!)
This meant every time I was trying to edit the player, I was passing the default value of "1 to the view and upon submission edited a model that never existed in the first place.
Upon setting the correct function, I was getting the correct values and thus the setting of the selected value sorted itself out.
I will however thank Sergey for having a look and trying to assist, and providing a better way of providing a SelectList (A better version would be to use a ViewModel, that will have to be used for another part).
So for those that are interested, here is the code that solves this issue:
From the Model:
public SelectList SelectListMA()
{
IList<SelectListItem> List = new List<SelectListItem>();
SelectListItem Item;
for(int i = 1; i <=9; i++)
{
Item = new SelectListItem()
{
Value = i.ToString(),
Text = i.ToString()
};
List.Add(Item);
}
return new SelectList(List,"Value","Text");
}
From the Controller:
public ActionResult BEditPlayer(int ID)
{
Races_Players SelectedPlayer = _RaceRepository.GetPlayerBase(ID);
ViewBag.MASelect = _RaceRepository.SelectListMA();
ViewBag.STSelect = _RaceRepository.SelectListST();
ViewBag.AGSelect = _RaceRepository.SelectListAG();
ViewBag.PASelect = _RaceRepository.SelectListPA();
ViewBag.AVSelect = _RaceRepository.SelectListAV();
return View(SelectedPlayer);
}
From the View: - as SelectList is to stop errors happening as the code is built
#Html.DropDownListFor(model => model.MA, ViewBag.MASelect as SelectList, "Select One")
Also, for any new programmers as per the research and testing, SelectList and SelectListItem have SelectedValue and Selected respectively for selecting Default values.
SelectedValue can be any object that identifies the primary key of the list or a new default value of the list (eg integer for a value already in the list, or a string for a default value of null).
Selected, however, is a boolean (ie true or false) that selects the value of the list. You only need to use one or the other.
Remember - if the value is passed from the controller to the view as the value in model => model.[Variable] then the value will be set to the value passed, not to the value set by SelectedValue or Selected.

There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'MembershipTypesId'

View class
<div class="editor-label">
#Html.LabelFor(model => model.MembershipTypesId, "MembershipTypesId", htmlAttributes: new { #class = "control-label col-md-2" })
</div>
<div class="editor-field">
#Html.DropDownList("MembershipTypesId", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.MembershipTypesId, "", new { #class = "text-danger" })
</div>
UsersController
public ActionResult Register(Customers customer)
{
if (ModelState.IsValid)
{
using (CDBContext dc = new CDBContext())
{
dc.Customers.Add(customer);
dc.SaveChanges();
ModelState.Clear();
customer = null;
ViewBag.MembershipTypesId = new SelectList(dc.MembershipTypes, "MembershipTypesId", "Name");
ViewBag.Message = "Successfully Registration Done";
}
}
return View(customer);
}
I used the same code for the others view and controller but somehow only this got the error. I tried to remove the null but it still the same.
What your error message suggest is that you are don't have ViewData that you should pass on this DropDownList:
#Html.DropDownList("MembershipTypesId", null, htmlAttributes: new { #class = "form-control" })
It is looking for ViewData with name MembershipTypesId
Your code on controller is correct IF you don't have problem on ModelState, but what if you have an error in your ModelState? Where is your ViewData that you need to pass back on your View?
This should be populated before you return to your View from your Controller:
public ActionResult Register(Customers customer)
{
if (ModelState.IsValid)
{
//Business Logic
}
ViewBag.MembershipTypesId = new SelectList(dc.MembershipTypes, "MembershipTypesId", "Name");
return View();
}

How to save dropdown values in database in asp.net MVC

When I select category from dropdown it is not saving in database. In database it is showing 101 for all values
MY view.cshtml is
<h4>RecStock</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Category, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="editor-field">
#Html.DropDownList("Category",null, new { #class = "form-control" } )
</div>
#Html.ValidationMessageFor(model => model.Category, "", new { #class = "text-danger" })
</div>
</div>
My Controller is
public ActionResult Create()
{
ViewBag.Category = new SelectList(db.ProductDetails, "id", "Category");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Category,ProductName,ReceiveQty,Date")] RecStock recStock)
{
if (ModelState.IsValid)
{
db.RecStocks.Add(recStock);
ViewBag.Category = new SelectList(db.ProductDetails, "id", "Category", recStock.id);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(recStock);
}
You should be using "DropDownListFor" and assign the selected dropdown value to the corresponding model property, like this:
#Html.DropDownListFor(m => m.MyModelProperty, new SelectList(Model.ListOfStuff, "ListOfStuffId", "ListOfStuffName"), string.Empty, new {#class = "form-control", id = "myList"})

Input field always sending null value

I have 3 input fields(User name, email & password) in my registration form. All of them are mandatory. But it looks like User Name field is always sending null value to controller and I'm getting unexpected validation message. Any help would be appreciated. P.S. rest 2 fields are just fine
HTML:
#using (Html.BeginForm("Create", "Registration", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Registration Form</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.UserName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UserName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UserName, "", new { #class = "text-danger" })
</div>
</div>
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Name,Email,Password")] UserRegistration userRegistration)
{
if (ModelState.IsValid)
{
db.UserSet.Add(userRegistration);
db.SaveChanges();
return View("Index");
}
return View(userRegistration);
}
I suppose that you need to change the Bind annotation to include a UserName and not a Name property
public ActionResult Create([Bind(Include = "UserName,Email,Password")] UserRegistration userRegistration)
When you use the Bind Attribute you define a list of property names for which the mvc engine should allow (include) the binding. The UserRegistration model has clearly a property named UserName and this property is not allowed in the binding list of names

Use same partial to add form to Create and Edit actions

When you create a new scaffolded item on VS it creates the views for Create and Edit actions that are almost identical, with the exception of the Edit view having an #Html.HiddenFor for your primary key.
Example of Edit view:
#model MyApp.Models.Destaque
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(m => m.IdDestaque)
<div class="form-group">
#Html.LabelFor(model => model.Mensagem, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Mensagem, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Mensagem, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CaminhoImagem, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CaminhoImagem, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CaminhoImagem, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.UrlLink, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UrlLink, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.UrlLink, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Salvar" class="btn btn-primary" />
</div>
</div>
</div>
}
If I place all content from the BeginForm (including the #using (...) and keep the #Html.HiddenFor(m => m.IdDestaque) in a _Form partial, it doesn't allow me to create new rows.
If I remove the #Html.HiddenFor from the _Form partial, the Edit action does not work (ModelState is invalid).
So what is the right way to do this and keep the DRY principles? Removing the PK from the ModelState validation in my Edit action seems an "uggly" workaround.
You should render the id of your model inside the view and use another overload for Html.BeginForm as follows:
#using (Html.BeginForm("Edit", "Controller", FormMethod.Post, new{attr1 = value1, attr2 = value2}))
{
#Html.HiddenFor(x => x.Id)
...
}
You always make a post to the EditAction. In you controller you will then only need one POST action for Edit and two get actions one Create and other Edit.
public ActionResult Create()
{
return View("Edit"); //return the edit view
}
public ActionResult Edit(int id)
{
var entity = manager.FetchById(id);
if (entity == null)
return HttpNotFound();
//convert your entity to model (optional, but recommended)
var model = Mapper.Map<ViewModel>(entity);
//return your edit view with your model
return View(model);
}
[HttpPost]
public ActionResult Edit(ViewModel model)
{
if (ModelState.IsValid)
{
//work with your model
return RedirectToAction("Index", "Controller");
}
//at this point there is an error, so your must return your view
return View(model);
}
Hope this helps!

Resources