I have simple site
controller.cs
public ActionResult Dodaj()
{
EduSiatkiEntities daneProgramu = new EduSiatkiEntities();
SelectList profileHasel = new SelectList(daneProgramu.SYS_PROFILE_HASEL.Select(e => new{ Value = e.idProfiluHasla, Text = e.nazwaProfilu,}), "Value", "Text");
ViewBag.profileHasel = profileHasel;
ViewBag.CzyZapisanoDane = "nie";
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Dodaj(Models.UzytkowniDodajkViewModel uzytkownikForm)
{
Debug.WriteLine(uzytkownikForm.idProfilHasla.Where(x => x.Selected=true).FirstOrDefault().Value.ToString());
if (ModelState.IsValid)
{
/**/
}
else
{
ViewBag.CzyZapisanoDane = "nie";
}
return View(uzytkownikForm);
}
view.cshtml
#Html.DropDownListFor(a => a.idProfilHasla, (SelectList)#ViewBag.profileHasel, "Wybierz opcje...", new { #class = "form-control" })
model.cs
[Display(Name = "Profil hasła użytkownika")]
[Required(ErrorMessage = "Wybierz profil hasła użytkownika")]
public IEnumerable<SelectListItem> idProfilHasla { get; set; }
When i debug the program I alway get NULL value from DropDownList (from code below)
Debug.WriteLine(uzytkownikForm.idProfilHasla.Where(x => x.Selected=true).FirstOrDefault().Value.ToString());
#Html.DropDownListFor(a => a.idProfilHasla, (SelectList)#ViewBag.profileHasel,
"Wybierz opcje...", new { #class = "form-control" })
For above DropDownList , idProfilHasla should be string type, because DropDownList selected value is a string.
[Display(Name = "Profil hasła użytkownika")]
[Required(ErrorMessage = "Wybierz profil hasła użytkownika")]
public string idProfilHasla { get; set; }
If you want to place SelectList inside model instead of ViewBag, you might want to read this answer.
Related
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 4 years ago.
This model is used to define a view:
namespace OnlineStore.ViewModels
{
public class SubCategoryVM
{
[Key]
public int ID { get; set; }
[Required]
public virtual string Name { get; set; }
[Required(ErrorMessage = "Parent Category Name is required")]
public virtual string ParentName { get; set; }
public IEnumerable<SelectListItem> categoryNames { get; set; }
}
}
Inside controller:
public ActionResult createSubCategory()
{
SubCategoryVM model = new SubCategoryVM();
var cNames = db.Categories.ToList();
model.categoryNames = cNames.Select(x
=> new SelectListItem
{
Value = x.Name,
Text = x.Name
});
return View(model);
}
[HttpPost]
public ActionResult createSubCategory(int? id, SubCategoryVM model)
{
SubCategory sc = new SubCategory();
if (ModelState.IsValid)
{
sc.ParentName = model.ParentName;
sc.Name = model.Name;
}
return View();
}
and View:
#model OnlineStore.ViewModels.SubCategoryVM
<div class="form-group">
#Html.LabelFor(model => model.ParentName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.ParentName, Model.categoryNames, "--Please select an option--", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ParentName, "", new { #class = "text-danger" })
</div>
This code is throwing a null-reference exception on line #Html.DropDownListFor(model => model.ParentName, Model.categoryNames, "--Please select an option--", new { #class = "form-control" }) saying:
Model.categoryName (Object reference not set to an instance of an object).
Please help me debug it.
Thanks in advance.
Problem is when you are posting the form and returning the View with the form data in case of invalid form, categoryNames in the model is becoming null and you have to repopulate the categoryNames before returning the view with model again.
So update your createSubCategory post method as follows:
[HttpPost]
public ActionResult createSubCategory(int? id, SubCategoryVM model)
{
SubCategory sc = new SubCategory();
if (ModelState.IsValid)
{
sc.ParentName = model.ParentName;
sc.Name = model.Name;
}
var cNames = db.Categories.ToList();
model.categoryNames = cNames.Select(x
=> new SelectListItem
{
Value = x.Name,
Text = x.Name
});
return View(model);
}
I'm having trouble with sending checkboxes and EditorFor values in MVC. I have two classes:
public class CompleteReceiving
{
public List<SiteOrderReceiving> order_detail { get; set; } //<- Data from DB. It contains all items for Order Receiving.
public List<SomeClass> new_form { get; set; } //<- Fields for form
}
public class SomeClass
{
[RegularExpression("^[0-9]*$", ErrorMessage = "Receive Quantity can only contain number")]
public decimal? receive_quantity { get; set; }
[RegularExpression("^[0-9]*$", ErrorMessage = "Damaged Quantity can only contain number")]
public decimal? damaged_quantity { get; set; }
public bool IsSelected { get; set; }
}
This is my View:
#for(int i = 0; i < Model.order_detail.Count; i++)
{
<tr>
<td>#Html.CheckBoxFor(m => m.new_form[i].IsSelected, new { id = "site_rec_checkbox", #class= "site_rec_checkbox" })
</td>
<td>#Html.EditorFor(m => m.new_form[i].receive_quantity, new { htmlAttributes = new { #class = "form-control fm", #autocomplete = "off", #autofocus = "autofocus", #placeholder = "Receiving Quantity" } })
#Html.ValidationMessageFor(m => m.new_form[i].receive_quantity, "", new { #class = "text-danger" })
</td>
}
And this is my Controller Action Code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SiteOrderReceiving(CompleteReceiving sor)
{
//Code for post
}
The problem is that whenever i select checkbox at any other index than 1 or 2 the List is always null. But for the first time if i select 3 or 4 and after that i select 1 or 2 than it works fine.
I don't know what i am doing wrong here.
Any help would be much appreciated.
Update
This is my Controller Action Code
[HttpGet]
public ActionResult SiteOrderReceiving(int? order_id)
{
var get_detail = (from oa in db.order_send
where oa.order_id == order_id
select new SiteOrderReceiving()
{
quantity_send = oa.send_quantity,
date_send = oa.send_date,
order_id = oa.order_id
}).ToList();
var a = new CompleteReceiving();
a.order_detail = get_detail;
return View(a);
}
And this is my View
#using (Html.BeginForm("SiteOrderReceiving", "Site", FormMethod.Post, new { id = "receive_form" }))
{
#Html.AntiForgeryToken();
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#for(int i = 0; i < Model.order_detail.Count; i++)
{
<tr>
<td>#Html.CheckBoxFor(m => m.new_form[i].IsSelected, new { id = "site_rec_checkbox", #class= "site_rec_checkbox" })
</td>
<td>#Html.EditorFor(m => m.new_form[i].receive_quantity, new { htmlAttributes = new { #class = "form-control fm", #autocomplete = "off", #autofocus = "autofocus", #placeholder = "Receiving Quantity" } })
#Html.ValidationMessageFor(m => m.new_form[i].receive_quantity, "", new { #class = "text-danger" })
</td>
}
}
So i solved my problem. What i did was move properties of my form to existing class in which i was getting the data from DB.
Now my ViewModel looks like this:
public class CompleteReceiving
{
public List<SomeClass> order_detail { get; set; }
//Some Other properties
}
And then:
public class SomeClass
{
[RegularExpression("^[0-9]*$", ErrorMessage = "Receive Quantity can only contain number")]
public decimal? receive_quantity { get; set; }
[RegularExpression("^[0-9]*$", ErrorMessage = "Damaged Quantity can only contain number")]
public decimal? damaged_quantity { get; set; }
public bool IsSelected { get; set; }
public string item_name { get; set; }
}
After updating my code like above, everything started working fine. Hope it helps someone in the future.
I have a people controller for user management and I'm trying to figure out how to get the dropdown choice when the user submits from the edit page. Whenever I hit submit on the page, none of the values from the view model seem to carry through to the post. I can't get the value they chose from the drop down to set the role.
See view model below:
public class PersonViewModel
{
public int PersonId { get; set; }
[Display(Name = "Full Name")]
public string FullName { get; set; }
public string Email { get; set; }
[Display(Name = "Current Role")]
public string SetRole { get; set; }
public List<RoleListViewModel> Roles { get; set; }
}
See controller edit functions below:
// GET: People/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Person person = db.people.Find(id);
if (person == null)
{
return HttpNotFound();
}
PersonViewModel pvm = new PersonViewModel();
List<IdentityRole> roles = adb.Roles.ToList();
var rlvm = new List<RoleListViewModel>();
roles.ForEach(x => rlvm.Add(new RoleListViewModel { RoleId = x.Id, RoleName = x.Name }));
pvm.PersonId = person.PersonId;
pvm.FullName = person.FirstName + " " + person.LastName;
pvm.Email = person.Email;
pvm.Roles = rlvm;
ViewBag.RoleList = new SelectList(rlvm, "RoleName", "RoleName", person.CurrentRole);
return View(pvm);
}
// POST: People/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(PersonViewModel pvm)
{
if (ModelState.IsValid)
{
db.Entry(pvm).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
var usr = new AccountController();
var pers = db.people.Where(x => x.PersonId == pvm.PersonId).FirstOrDefault();
usr.UserManager.AddToRoleAsync(pers.NetId, /* their choice should go here but how? */);
db.SaveChanges();
return View(pvm);
}
Here is the cshtml:
<div class="form-group">
#Html.LabelFor(model => model.Roles, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="form-control-static">
#Html.DropDownList("RoleList", null, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Roles, "", new { #class = "text-danger" })
</div>
</div>
Make a variable in your View Model to store the selected value and then in the view use
#Html.DropDownListFor(m => m.SelectedRoleVariable, RolesSelectList, new { #class = "form-control" });
I tried to bind the database with dropdown using IEnumerable. But it showing error which is showed in the below image.
My Model (CustomerViewModel)
public Nullable<System.Guid> AreaID { get; set; }
public string Area { get; set; }
public IEnumerable<SelectListItem> AreaList { get; set; }
My Controller
public ActionResult Create ()
{
CustomerViewModel cvm = new CustomerViewModel();
cvm.AreaList = db.Areas.Where(a => a.IsDeleted == false).Select(a => new SelectListItem()
{
Value = a.AreaID.ToString(),
Text = a.DisplayName
});
return View();
}
My View Code
#Html.LabelFor(model => model.Area, new { #class = "control-label" })
#Html.DropDownListFor(m => m.AreaID, Model.AreaList, "Please select a Area", new { #class = "form-control" })
The code you have works ok. The problem is that you are creating a query where you use the .ToString() method, which cannot be translated to a DB equivalent syntax.
To make it work, you need to select the items from DB using .ToList(), and after that create the SelectListItem
cvm.AreaList = db.Areas.Where(a => a.IsDeleted == false).ToList().Select(a => new SelectListItem()
{
Value = a.AreaID.ToString(),
Text = a.DisplayName
});
What I'm trying to do...
I am trying to get a newly added item to display in a cascading dropdownlist.
Overview...
The first dropdownlist (I'll call it ddlCategory) is for selecting a Category of electrical devices (ie. Appliances, Audio-Visual, Lighting, etc.). The second dropdownlist (I'll call ddlElecDev) is populated with the devices which are filtered by the selected Category. If the device isn't listed in ddlElecDev then the user can click a link to add a new one. After saving the newly added electrical device, the user is redirected back to the original page with the electrical device id as a parameter.
All the above seems to work fine. However, when the user is redirected to the first page, not only is the newly added electrical device not selected in ddlElecDev, but it doesn't even appear in the list. Strangely, if I refresh the page, it is automatically selected.
Can anyone explain to me how to get the newly added device to be selected without having to refresh the page?
Here's the markup for selecting the category and electrical device:
<div class="form-group">
#Html.LabelFor(model => model.SelectedCategory, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.SelectedCategory, Model.Categories, "Select a Category", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.SelectedCategory, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ElectricalDeviceID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.CascadingDropDownListFor(
expression: model => model.ElectricalDeviceID,
triggeredByProperty: model => model.SelectedCategory,
url: Url.Action("GetElectricalDevices", "ElectricalDeviceConfigurations"),
ajaxActionParamName: "categoryId",
optionLabel: "Select an Electrical Device",
disabledWhenParrentNotSelected: false,
htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.ElectricalDeviceID, "", new { #class = "text-danger" })
#Html.ActionLink("Not Listed? Add a new Electrical Device", "AddNew", "ElectricalDevices", new { returnUrl = string.Format("/ElectricalDeviceConfigurations/AddConfiguration?eventVendorId={0}", Model.EventVendorID) }, null)
</div>
</div>
The documentation for the Cascading DropDownList Helper can be found at
https://github.com/alexanderar/Mvc.CascadeDropDown
Here's the Controller method for selecting the Electrical Device:
public ActionResult AddConfiguration(int? eventVendorId, int? newElecDev)
{
(Some code removed for brevity)
var selectedCategoryId = db.ElectricalDeviceCategoryLookups.Where(cat => cat.Category == Enums.ElectricalDeviceCategory.All).FirstOrDefault().ID;
var electricalDeviceID = (newElecDev.HasValue) ? newElecDev : null;
return View(new ElecDevConfigSelectionViewModel { EventVendorID = eventVendorId, EventVendor = eventVendor, Categories = GetCategories(), SelectedCategory = selectedCategoryId, ElectricalDeviceID = electricalDeviceID });
}
Here's the controller methods for populating the Categories and the Electrical Devices:
private List<SelectListItem> GetCategories()
{
var categories = new List<SelectListItem>();
db.ElectricalDeviceCategoryLookups.OrderBy(c => c.Description).ToList().ForEach(item => categories.Add(new SelectListItem { Text = item.Description, Value = item.ID.ToString() } ));
return categories;
}
public ActionResult GetElectricalDevices(int? categoryId)
{
if (categoryId.HasValue)
{
var selCategory = db.ElectricalDeviceCategoryLookups.Where(cat => cat.ID == categoryId).FirstOrDefault().Category;
var elecDevicesSelectList = new List<SelectListItem>();
var elecDevices = (selCategory == Enums.ElectricalDeviceCategory.All) ? db.ElectricalDevices.OrderBy(ed => ed.Name).ToList() : db.ElectricalDevices.Where(ed => ed.Category == selCategory).OrderBy(ed => ed.Name).ToList();
elecDevices.ForEach(ed => elecDevicesSelectList.Add(new SelectListItem { Text = ed.Name, Value = ed.ID.ToString() }));
return Json(elecDevicesSelectList, JsonRequestBehavior.AllowGet);
}
return null;
}
Here's the View Model:
public class ElecDevConfigSelectionViewModel
{
public int? EventVendorID { get; set; }
public EventVendor EventVendor { get; set; }
[Display(Name = "Category")]
public int SelectedCategory { get; set; }
public IList<SelectListItem> Categories { get; set; }
[Display(Name = "Electrical Device")]
public int? ElectricalDeviceID { get; set; }
}
Here's the controller methods for adding a new electrical device:
// GET: ElectricalDevices/AddNew
public ActionResult AddNew(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
var selectedCategoryId = db.ElectricalDeviceCategoryLookups.FirstOrDefault().ID;
return View(new AddNewElectricalDeviceViewModel { ReturnUrl = returnUrl, Categories = GetCategories(), SelectedCategory = null });
}
// POST: ElectricalDevices/AddNew
// 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 AddNew(AddNewElectricalDeviceViewModel model)
{
if (ModelState.IsValid)
{
var selectedCategory = db.ElectricalDeviceCategoryLookups.Find(model.SelectedCategory);
var electricalDevice = new ElectricalDevice
{
Name = model.ElectricalDevice.Name,
Description = model.ElectricalDevice.Description,
Category = selectedCategory.Category,
Wattage = model.ElectricalDevice.Wattage
};
db.ElectricalDevices.Add(electricalDevice);
db.SaveChanges();
var returnUrl = string.Format("{0}&newElecDev={1}", model.ReturnUrl, electricalDevice.ID);
return RedirectToLocal(returnUrl);
}
return View();
}
Here's the View Model for adding a new electrical device:
public class AddNewElectricalDeviceViewModel
{
public string ReturnUrl { get; set; }
[Display(Name = "Category")]
public int? SelectedCategory { get; set; }
public IList<SelectListItem> Categories { get; set; }
public ElectricalDevice ElectricalDevice { get; set; }
}