I'm trying to get the original selectedvalue from the database in the Edit view. I need for the original value to be displayed, and from there the user can choose another value.
ViewModel
public Local Local { get; set; }
public SelectList Estados { get; set; }
public int IdEstadoSeleccionado { get; set; }
public SelectList Proveedores { get; set; }
public int IdProveedorSeleccionado { get; set; }
public LocalEditarViewModel(Local local, List<Estado> estados, List<Proveedor> proveedores,int estadoid)
{
this.Local = local;
this.Estados = new SelectList(estados, "Id", "State");
this.Proveedores = new SelectList(proveedores, "Id", "Nombre");
}
Controller
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Local local = db.Locales.Find(id);
List<Estado> estados;
List<Proveedor> proveedores;
using (AutoContex db = new AutoContex())
{
estados = db.Estados.ToList();
proveedores = db.Proveedores.ToList();
}
LocalEditarViewModel vm = new LocalEditarViewModel(local, estados, proveedores);
if (local == null)
{
return HttpNotFound();
}
Session["LocalId"] = local.Id;
return View(vm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(LocalEditarViewModel vm)
{
using (AutoContex db = new AutoContex())
{
if (ModelState.IsValid)
{
string id = Session["LocalId"].ToString();
int localId = 0;
int.TryParse(id, out localId);
vm.Local.Id = localId;
vm.Local.Proveedor = db.Proveedores.Find(vm.IdProveedorSeleccionado);
vm.Local.Estado = db.Estados.Find(vm.IdEstadoSeleccionado);
Local original = db.Locales.Find(localId);
original.Estado = vm.Local.Estado;
original.Proveedor = vm.Local.Proveedor;
original.Id = localId;
original.Direccion = vm.Local.Direccion;
original.FechaIngreso = vm.Local.FechaIngreso;
//original.FechaInstalacion = vm.Local.FechaInstalacion;
original.Localidad = vm.Local.Localidad;
original.NombreComercio = vm.Local.NombreComercio;
original.NombreComercioUnificado = vm.Local.NombreComercioUnificado;
original.Provincia = vm.Local.Provincia;
original.Telefono = vm.Local.Telefono;
original.ViejoId = vm.Local.ViejoId;
original.NuevoId = vm.Local.NuevoId;
db.SaveChanges();
}
}
return View(vm);
}
VIEW
<div class="form-group">
#Html.LabelFor(model => model.Estados, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.IdEstadoSeleccionado, Model.Estados)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Proveedores, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.IdProveedorSeleccionado, Model.Proveedores,"--Select--")
</div>
In your Edit GET action method, set the value for IdProveedorSeleccionado and IdProveedorSeleccionado properties.
vm.IdProveedorSeleccionado = local.IdProveedorSeleccionado ;
vm.IdProveedorSeleccionado = local.IdProveedorSeleccionado ;
return View(vm);
The DropDownListFor helper method will select the option which has matching value attribute value as of these property values.
Related
Am I doing something wrong?
I am not able to update data in my LsstoreDetails table but the Lsstores table is the only table that is updating the data in the database.
Whenever I debug, I can see that model.StoreDetail.StoreDetailsEn is not null and has registered my input but it doesn't save it.
I am not sure what to do as I tried so many different methods and the same issue kept persisting.
I am not getting any errors.
It would be much appreciated if I could receive some help/guidance to resolve this issue.
Thank you!
Model class:
public class Manage
{
public Lsstore Store { get; set; }
public List<Lscity> Cities { get; set; }
public List<Lscountry> Countries { get; set; }
public List<LsstoreStatus> Status { get; set; }
public List<LsstoreType> Types { get; set; }
public List<Lsprovince> Provinces { get; set; }
public List<LsstoreMall> Malls { get; set; }
public List<Lsregion> Regions { get; set; }
public List<LssubBrand> SubBrands { get; set; }
public List <LsstoreBusinessHour> StoreBusinessHours { get; set; }
public List<Lslanguage> Languages { get; set; }
public List<Lsbanner> Banners { get; set; }
public VwLsstoreMgmtInfo LsstoreMgmt { get; set; }
public VwStoreKiboInfo StoreKiboInfo { get; set; }
public LsstoreDetail StoreDetail { get; set; }
}
A part of the view (it is in a form):
<div class="mb-1">
#Html.LabelFor(model => model.Store.StoreDescription, "Store Name",
htmlAttributes: new { #class = "control-label" })
#Html.EditorFor(model => model.Store.StoreDescription, new { htmlAttributes
= new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Store.StoreDescription, "", new {
#class = "text-danger" })
</div>
<div class="form-group input-group-lg mb-1">
#Html.LabelFor(model => model.StoreDetail.StoreDetailsEn, "Store Description", htmlAttributes: new { #class = "control-label" })
<ul class="nav nav-tabs" id="myTab">
<li class="nav-item">
EN
</li>
<li class="nav-item">
FR
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade show active" id="english">
#Html.TextAreaFor(model => model.StoreDetail.StoreDetailsEn, new { htmlAttributes = new { #class = "form-control" }, rows = 10, cols = 60 })
#Html.ValidationMessageFor(model => model.StoreDetail.StoreDetailsEn, "", new { #class = "text-danger" })
</div>
<div class="tab-pane fade" id="french">
#Html.TextAreaFor(model => model.StoreDetail.StoreDetailsFr, new { htmlAttributes = new { #class = "form-control" }, rows = 10, cols = 60 })
#Html.ValidationMessageFor(model => model.StoreDetail.StoreDetailsFr, "", new { #class = "text-danger" })
</div>
</div>
</div>
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int? id, Manage model)
{
if (id == null)
{
return NotFound();
}
// This part doesn't work
var storeDetail = db.LsstoreDetails.Where(x => x.StoreId.Equals(id)).FirstOrDefault();
if (storeDetail != null)
{
storeDetail.StoreDetailsEn = model.StoreDetail.StoreDetailsEn;
db.SaveChanges();
}
//-------------------------
// This part works
var data = db.Lsstores.Find(id);
if (data != null)
{
data.StoreDescription = model.Store.StoreDescription;
data.Address = model.Store.Address;
data.Local = model.Store.Local;
data.Zip = model.Store.Zip;
data.Sqft = model.Store.Sqft;
data.Fax2 = model.Store.Fax2;
data.Phone1 = model.Store.Phone1;
data.Fax1 = model.Store.Fax1;
data.RegisterCount = model.Store.RegisterCount;
data.PosVersion = model.Store.PosVersion;
data.Latitude = model.Store.Latitude;
data.Longitude = model.Store.Longitude;
data.OpenDate = model.Store.OpenDate;
data.CloseDate = model.Store.CloseDate;
data.ModifiedDate = model.Store.ModifiedDate;
data.ModifiedBy = model.Store.ModifiedBy;
db.SaveChanges();
}
//------------------------------------------
return RedirectToAction("index", "Home");
}
}
I think this is what you wanted to accomplish, but got confused along the way, i would suggest you read about auto mapper it would help clean up your code.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int? id, Manage model)
{
if (id == null)
{
return NotFound();
}
// This part doesn't work
var storeDetail = db.LsstoreDetails.Where(x => x.StoreId.Equals(id)).FirstOrDefault();
if (storeDetail != null)
{
storeDetail.StoreDetailsEn = model.StoreDetail.StoreDetailsEn;
db.LsstoreDetails.update(storeDetail);
}
//-------------------------
// This part works
var data = db.Lsstores.Find(id);
if (data != null)
{
data.StoreDescription = model.Store.StoreDescription;
data.Address = model.Store.Address;
data.Local = model.Store.Local;
data.Zip = model.Store.Zip;
data.Sqft = model.Store.Sqft;
data.Fax2 = model.Store.Fax2;
data.Phone1 = model.Store.Phone1;
data.Fax1 = model.Store.Fax1;
data.RegisterCount = model.Store.RegisterCount;
data.PosVersion = model.Store.PosVersion;
data.Latitude = model.Store.Latitude;
data.Longitude = model.Store.Longitude;
data.OpenDate = model.Store.OpenDate;
data.CloseDate = model.Store.CloseDate;
data.ModifiedDate = model.Store.ModifiedDate;
data.ModifiedBy = model.Store.ModifiedBy;
db.Lsstores.update(data);
}
db.SaveChanges();
//------------------------------------------
return RedirectToAction("index", "Home");
}}
When I want to add new customer into my database, I am getting returned to the same page and customer isn't added to database.
Everything was fine until I added validation into my Customer controller.
After adding
if (!ModelState.IsValid)
{
var viewModel = new NewCustomerViewModel
{
Customer = customer,
MemberShipTypes = _context.MemberShipTypes.ToList()
};
return View("New", viewModel);
}
Customer class
public class Customer
{
public int? Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
public bool IsSubscribedToNewsLetter { get; set; }
public MemberShipType MemberShipType { get; set; }
[Display(Name = "Membership Type")]
public int MemberShipTypeId { get; set; }
[Display(Name = "Birth of Date")]
[Min18YearsIfAMember]
public DateTime? BirthDate { get; set; }
}
I got this problem:
New view
#using System.Security.Cryptography
#model Vidly.VIewModels.NewCustomerViewModel
#{
ViewBag.Title = "New";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#{
if (Model.Customer != null)
{
<h2>Edit Customer</h2>
}
else
{
<h2>New Customer</h2>
}
}
#using (Html.BeginForm("Save", "Customers"))
{
#Html.HiddenFor(m => m.Customer.Id)
<div class="form-group">
#Html.LabelFor(m => m.Customer.Name)
#Html.TextBoxFor(m => m.Customer.Name, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Customer.Name)
</div>
<div class="form-group">
#Html.LabelFor(m => m.Customer.BirthDate)
#Html.TextBoxFor(m => m.Customer.BirthDate, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Customer.BirthDate)
</div>
<div class="form-group">
#Html.LabelFor(m => m.Customer.MemberShipTypeId)
#Html.DropDownListFor(m => m.Customer.MemberShipTypeId, new SelectList(Model.MemberShipTypes,"Id","Name"), "", new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Customer.MemberShipTypeId)
</div>
<div class="checkbox">
<label>
#Html.CheckBoxFor(m => m.Customer.IsSubscribedToNewsLetter) Subscribed to NewsLetter?
</label>
</div>
<button type="submit" class="btn btn-primary">Save</button>
}
CustomerController:
public class CustomersController : Controller
{
private ApplicationDbContext _context;
public CustomersController()
{
_context = new ApplicationDbContext();
}
protected override void Dispose(bool disposing)
{
_context.Dispose();
}
[HttpPost]
public ActionResult Save(Customer customer)
{
if (!ModelState.IsValid)
{
var viewModel = new NewCustomerViewModel
{
Customer = customer,
MemberShipTypes = _context.MemberShipTypes.ToList()
};
return View("New", viewModel);
}
if (customer.Id == 0)
_context.Customers.Add(customer);
else
{
var customerInDb = _context.Customers.Single(c => c.Id == customer.Id);
customerInDb.Name = customer.Name;
customerInDb.BirthDate = customer.BirthDate;
customerInDb.MemberShipTypeId = customer.MemberShipTypeId;
customerInDb.IsSubscribedToNewsLetter = customer.IsSubscribedToNewsLetter;
}
_context.SaveChanges();
return RedirectToAction("Index", "Customers");
}
public ActionResult New()
{
var memberships = _context.MemberShipTypes.ToList();
var viewModel = new NewCustomerViewModel
{
MemberShipTypes = memberships
};
return View(viewModel);
}
// GET: Customer
public ActionResult Index()
{
var customers = _context.Customers.Include(c=> c.MemberShipType).ToList();
return View(customers);
}
public ActionResult Details(int id)
{
var customer = _context.Customers.Include(c => c.MemberShipType).SingleOrDefault(c => c.Id == id);
if (customer == null)
return HttpNotFound();
return View(customer);
}
public ActionResult Edit(int id)
{
var customer = _context.Customers.SingleOrDefault(c => c.Id == id);
if (customer == null)
return HttpNotFound();
var viewModel = new NewCustomerViewModel
{
Customer = customer,
MemberShipTypes = _context.MemberShipTypes.ToList()
};
return View("New", viewModel);
}
}
[Min18YearsIfAMember] is my custom validation for Minimum 18 years old if a new member is.
since your Customer Id is nullable fix your code
if (customer.Id == null || customer.Id == 0 )
or you can change your Id property
public int Id { get; set; }
I have the following two models (stripped to relevant parts):
Models\Department.cs:
public class DepartmentValidator : AbstractValidator<Department> {
public DepartmentValidator() {
RuleFor(d => d.Name)
.NotEmpty().WithMessage("You must specify a name.")
.Length(0, 256).WithMessage("The name cannot exceed 256 characters in length.");
}
}
[Validator(typeof(DepartmentValidator))]
public class Department {
public int Id { get; set; }
[Column(TypeName = "nvarchar")]
[MaxLength(256)]
public string Name { get; set; }
}
Models\FacultyMember.cs:
public class FacultyValidator : AbstractValidator<FacultyMember> {
public FacultyValidator() {
RuleFor(f => f.Name)
.NotEmpty().WithMessage("You must specify a name.")
.Length(0, 64).WithMessage("The name cannot exceed 64 characters in length.");
}
}
[Validator(typeof(FacultyValidator))]
public class FacultyMember {
public int Id { get; set; }
[Column(TypeName = "nvarchar")]
[MaxLength(64)]
public string Name { get; set; }
public virtual ICollection<Department> Departments { get; set; }
public FacultyMember() {
Departments = new HashSet<Department>();
}
}
I have the following controller code:
Controllers\FacultyController.cs:
// GET: Faculty/Create
public ActionResult Create() {
// Get Departments.
var departmentList = db.Departments.ToList().Select(department => new SelectListItem {
Value = department.Id.ToString(),
Text = department.Name
}).ToList();
ViewBag.DepartmentList = departmentList;
var facultyMember = new FacultyMember();
facultyMember.Departments.Add(new Department()); // Create a single dropdown for a department to start out.
return View(facultyMember);
}
// POST: Faculty/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,Name,Departments")] FacultyMember facultyMember) {
// Get Departments.
var departmentList = db.Departments.ToList().Select(department => new SelectListItem {
Value = department.Id.ToString(),
Text = department.Name
}).ToList();
ViewBag.DepartmentList = departmentList;
if (!ModelState.IsValid) { // Problem here...
return View(facultyMember);
}
db.Faculty.Add(facultyMember);
db.SaveChanges();
return RedirectToAction("Index");
}
Views\Faculty\Create.cshtml:
...
<div class="form-group">
#Html.LabelFor(model => model.Departments, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Departments, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Departments, "", new { #class = "text-danger" })
</div>
</div>
...
Views\Shared\EditorTemplates\Department.cshtml:
#model MyProject.Models.Department
#Html.DropDownListFor(model => model.Id, ViewBag.DepartmentList as IEnumerable<SelectListItem>, "Select...", new { #class = "form-control" })
So, when I navigate to the create faculty page, everything displays properly; the 'Departments' field has a dropdown list with the departments in my database. However, upon submitting the form, my model state is invalid (see comment in code above). Upon further inspection, it seems that FluentValidation is spitting out an error because my "Name" field is null. That's exactly what it should do when I'm creating/editing departments, but for this dropdown in faculty members, it shouldn't be validating the entire department, should it? The only thing the dropdown is sending back is the Id, as I've specified.
The only thing that this dropdown sends is the Id of the department, which is properly received. So, what do I need to do to make this work? My goal is to have a dynamic set of dropdown lists, each populated with existing departments in the database. Similar to this example.
Please let me know if anything else needs explaining.
The solution, as explained by Stephen Muecke, was to create a view model to represent all data I wanted to pass to the form and back.
ViewModel\FacultyMemberViewModel.cs:
public class FacultyMemberViewModelValidator : AbstractValidator<FacultyMemberViewModel> {
public FacultyMemberViewModelValidator() {
RuleFor(f => f.Name)
.NotEmpty().WithMessage("You must specify a name.")
.Length(0, 64).WithMessage("The name cannot exceed 64 characters in length.");
RuleFor(s => s.SelectedDepartments)
.NotEmpty().WithMessage("You must specify at least one department.")
}
}
[Validator(typeof(FacultyMemberViewModelValidator))]
public class FacultyMemberViewModel {
public int Id { get; set; }
public string Name { get; set; }
public int[] SelectedDepartments { get; set; }
[DisplayName("Departments")]
public IEnumerable<SelectListItem> DepartmentList { get; set; }
}
Views\Faculty\Create.cshtml:
...
<div class="form-group">
#Html.LabelFor(model => model.DepartmentList, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.ListBoxFor(model => model.SelectedDepartments, Model.DepartmentList, new { #class = "form-control" }) #Html.ValidationMessageFor(model => model.SelectedDepartments, "", new { #class = "text-danger" })
</div>
</div>
...
Controllers\FacultyController.cs:
// GET: Faculty/Create
public ActionResult Create() {
var facultyMemberViewModel = new FacultyMemberViewModel {
DepartmentList = GetDepartmentList()
};
return View(facultyMemberViewModel);
}
// POST: Faculty/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,Name,SelectedDepartments,DepartmentList")] FacultyMemberViewModel facultyMemberViewModel) {
if (!ModelState.IsValid) {
// Re-set the Department list.
if (facultyMemberViewModel.DepartmentList == null) {
facultyMemberViewModel.DepartmentList = GetDepartmentList();
}
return View(facultyMemberViewModel);
}
var facultyMember = new FacultyMember {
Id = facultyMemberViewModel.Id,
Name = facultyMemberViewModel.Name,
};
foreach (var departmentId in facultyMemberViewModel.SelectedDepartments) {
// I'm assuming this is safe to do (aka the records exist in the database)...
facultyMember.Departments.Add(db.Departments.Find(departmentId));
}
db.Faculty.Add(facultyMember);
db.SaveChanges();
return RedirectToAction("Index");
}
I want to make my model to associate with a User from the Identity system in ASP.NET MVC 5, instead of an Employee. My problem is that I can't seem to figure out the magic behind #Html.DropDownList... I'm pulling my hair out. Here is my ViewModel:
public class TicketViewModel
{
[Display(Name="ID#")]
public int TicketId { get; set; }
public int EmployeeId { get; set; }
public int ShopId { get; set; }
public int UserId { get; set; }
public int ApplicationUserId { get; set; }
public string Description { get; set; }
public string Status { get; set; }
public EmployeeViewModel Employee { get; set; }
public ShopViewModel Shop { get; set; }
public TotsUser User { get; set; }
}
and the TicketController method:
// GET: /Ticket/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Ticket ticket = db.Tickets.Find(id);
if (ticket == null)
{
return HttpNotFound();
}
TicketViewModel ticketVM = Mapper.Map(ticket, new TicketViewModel());
ViewBag.EmployeeId = new SelectList(db.Employees, "EmployeeId", "Name", ticketVM.EmployeeId);
ViewBag.ShopId = new SelectList(db.Shops, "ShopId", "Name", ticketVM.ShopId);
ViewBag.UserListing = new SelectList(db.Users, "Id", "UserName", ticketVM.UserId);
return View(ticketVM);
}
The view (the part in question)
<div class="form-group">
#Html.LabelFor(model => model.EmployeeId, "EmployeeId", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("EmployeeId", String.Empty)
#Html.ValidationMessageFor(model => model.EmployeeId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.UserId, "UserId", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#* #Html.DropDownList("UserId", String.Empty) *#
#Html.DropDownList("UserId", #ViewBag.UserListing, null);
#Html.ValidationMessageFor(model => model.UserId)
</div>
</div>
I can't even explain how it even works with EmployeeId. This is the way that the scaffold generated it for my original model. It populates EmployeeId just fine. Can someone please explain the dark magic going on with the #Html.DropDownList helper and explain why I can't get the DropDownList to populate with anything?
you can try to change
ViewBag.UserListing = new SelectList(db.Users, "Id", "UserName", ticketVM.UserId);
to
ViewBag.UserId = new SelectList(db.Users, "Id", "UserName", ticketVM.UserId);
or change
#Html.DropDownList("UserId", #ViewBag.UserListing, null);
to
#Html.DropDownList("UserId", (SelectList)#ViewBag.UserListing);
This is incorrect no matter which method you use
#Html.DropDownList("UserId", #ViewBag.UserListing, null);
You have to tell the helper what type of object #ViewBag.UserListing is. In your case it would be (SelectList)#ViewBag.UserListing
I have cshtml page like this:
<div class="form-group">
#Html.LabelFor(m => m.QuestionnaireName, new { #class = "col-md-2 control-label" })
#Html.DropDownListFor(m => m.QuestionnaireName, Model.Questionnaires, new { #id = "ddlQuestionnaires", #class = "form-control" })
#Html.Label("Questions list:", new { #class = "col-md-2 control-label" })
// here: how to check if any dropdownlistfor value is selected?
</div>
Like i said in comment above. I want to check if value of DropDownListFor is selected and in case yes, build dynamicaly (table or list) for element of chosen Questionnaire.
Let say that Questionnaire.name is unique id and Questionnaire contain List Questions.
here is my model:
public class FillQuestionnaireModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Select questionnaire")]
public string QuestionnaireName { get; set; }
public SelectList Questionnaires { get; set; }
}
and my controller actions:
public ActionResult Fill()
{
QuestionnaireServiceReference.QuestionnaireServiceClient client = new QuestionnaireServiceReference.QuestionnaireServiceClient();
FillQuestionnaireModel model = new FillQuestionnaireModel();
List<QuestionnaireServiceReference.Questionnaire> Questionnaires = client.GetAllQuestionnaires().ToList();
Questionnaires.Insert(0, new QuestionnaireServiceReference.Questionnaire() { questionnaire_id = 0, name = "--Select--" });
model.Questionnaires = new SelectList(Questionnaires, "name", "name");
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Fill(FillQuestionnaireModel model)
{
if (!ModelState.IsValid)
{
string SelectedValue = model.QuestionnaireName;
return View(model);
}
else
{
QuestionnaireServiceReference.QuestionnaireServiceClient client = new QuestionnaireServiceReference.QuestionnaireServiceClient();
List<QuestionnaireServiceReference.Questionnaire> Questionnaires = client.GetAllQuestionnaires().ToList();
Questionnaires.Insert(0, new QuestionnaireServiceReference.Questionnaire() { questionnaire_id = 0, name = "--Select--" });
model.Questionnaires = new SelectList(Questionnaires, "name", "name");
}
return View(model);
}