This question already has answers here:
Populating a razor dropdownlist from a List<object> in MVC
(9 answers)
Closed 3 years ago.
I have a view to create an 'Appointment' after choosing some options in 3 different drop-down menus (Patient, Doctor, Clinic)
I need help with creating and populating these 3 drop-down menus.
I'm pretty new to ASP.NET MVC and C#. So, your help is most appreciated.
I'll include the appointment controller and appointment creation view code.
AppointmentController
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ClinicManagement.Models;
namespace ClinicManagement.Controllers
{
public class AppointmentController : Controller
{
// GET: Appointment
public ActionResult Index()
{
using (HospitalDatabaseEntities DataBase = new HospitalDatabaseEntities())
{
return View(DataBase.Appointments.ToList());
}
}
// GET: Appointment/Details/5
public ActionResult Details(int id)
{
using (HospitalDatabaseEntities DataBase = new HospitalDatabaseEntities())
{
return View(DataBase.Appointments.Where(x => x.AppintID == id).FirstOrDefault());
}
}
// GET: Appointment/Create
public ActionResult Create()
{
return View();
}
// POST: Appointment/Create
[HttpPost]
public ActionResult Create(Appointment appointment)
{
try
{
using (HospitalDatabaseEntities DataBase = new HospitalDatabaseEntities())
{
DataBase.Appointments.Add(appointment);
DataBase.SaveChanges();
}
// TODO: Add insert logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
// GET: Appointment/Edit/5
public ActionResult Edit(int id)
{
using (HospitalDatabaseEntities DataBase = new HospitalDatabaseEntities())
{
return View(DataBase.Appointments.Where(x => x.AppintID == id).FirstOrDefault());
}
}
// POST: Appointment/Edit/5
[HttpPost]
public ActionResult Edit(int id, Appointment appointment)
{
try
{
using (HospitalDatabaseEntities DataBase = new HospitalDatabaseEntities())
{
DataBase.Entry(appointment).State = EntityState.Modified;
DataBase.SaveChanges();
}
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
// GET: Appointment/Delete/5
public ActionResult Delete(int id)
{
using (HospitalDatabaseEntities DataBase = new HospitalDatabaseEntities())
{
return View(DataBase.Appointments.Where(x => x.AppintID == id).FirstOrDefault());
}
}
// POST: Appointment/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
using (HospitalDatabaseEntities DataBase = new HospitalDatabaseEntities())
{
Appointment appointment = (DataBase.Appointments.Where(x => x.AppintID == id).FirstOrDefault());
DataBase.Appointments.Remove(appointment);
DataBase.SaveChanges();
}
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}
Appointment 'Create' View
#model ClinicManagement.Models.Appointment
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Appointment</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.DoctorID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DoctorID, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.DoctorID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PatientID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PatientID, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PatientID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ClinicID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ClinicID, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ClinicID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Date, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Date, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create Appointment" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
If the drop down menu options are in a database, why not add a list to your model, populate that list in your GET ActionMethod and then render it using the DropdownListFor helper tag.
For example...
public class Appointment
{
public IEnumerable<SelectListItem> Clinic {get; set;}
//You should add this for every dropdown menu you intend to put in the list.
//I am guessing you already have a model like this as this was not in the question
}
public class Clinic
{
public int ClinicId {get; set;}
public string ClinicName {get; set;}
}
In the controller, you can then query the database for the options
public ActionResult Create()
{
var Clinic = context.Clinic.ToList();
var model = new Appointments()
{
Clinic = Clinic.Select(x => new SelectListItem
{
Value = x.ClinicId.ToString(),
Text = x.ClinicName
}
}
return View(model);
}
Like before, you would have to do this for all the fields. If you are worried about the numerous roundtrip to the database to get the values, do some research about Z.EntityFrameWork nuget pakages that lets you run batch SQL statements so you can get all three results with one database round trip.
Then in the view, you can do this...
#Html.DropDownListFor(m => m.ClinicId, Model.Clinic, "Select Clinic", new { #class = "form-control", id = "clinic" })
In Create controller GET , you should create 3 viewbag like
ViewBag.Patient = Database.Patient.ToList();
...
and in view, use dropdownlist:
#Html.DropDownList("PatientId", new SelectList(ViewBag.Accounts, "PatientId", "PatientName")), "choose the patient", new { #class = "form-control" }))
Related
I have created a model with a controller and a view in my ASP.NET MVC application. Initially, when a new application is created using the create action, the user doesn't have the possibility to fill in 5 of the parts of the model (see code).
Editing is only possible when logging in as an admin, not as any user. Getting the edit page for the right application connected to the right user is not a problem. HOWEVER, when I fill in the checkboxes and write any comments etc. in the 'edit mode', and press submit, nothing happens. It seems the changes are not registered by the program (db.SaveChanges() doesn't work??)
Please, do someone know how I can fix this, or to begin with, what the problem is? It is almost as if the save button is just a shell, so might there me a connection or something missing?
Thank you for your time.
code:
part of the model (last 5 are not filled in in 'create mode'
[Display(Name = "Course for master")]
public string Course_Master { get; set; }
[Required]
[Display(Name = "Words for Office")]
[MaxLength(3000)]
public string Motivation { get; set; }
//[DataType(DataType.Upload)]
[Display(Name = "Upload Resume")]
//[Required(ErrorMessage = "Please choose file to upload")]
public string Resume { get; set; }
//these 5 are the ones I want to edit
public bool Interview { get; set; } //checkbox
public string Comments { get; set; }
public string Notes { get; set; }
public bool Unfit { get; set; } //checkbox
public bool Candidate { get; set; } //checkbox
razor page
#model NEA.Models.Application
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Edit</h2>
#using (Html.BeginForm("Edit","Applications", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Application</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.UserId)
<div class="form-group">
#Html.LabelFor(model => model.Interview, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.Interview)
#Html.ValidationMessageFor(model => model.Interview, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Comments, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Comments, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Comments, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Notes, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Notes, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Notes, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Unfit, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.Unfit)
#Html.ValidationMessageFor(model => model.Unfit, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Candidate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.Candidate)
#Html.ValidationMessageFor(model => model.Candidate, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
action
// GET: Applications/Edit/5
public ActionResult Edit(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Application application = db.Applications.Find(id);
if (application == null)
{
return HttpNotFound();
}
return View(application);
}
// POST: Applications/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Application application)
{
if (ModelState.IsValid)
{
db.Entry(application).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(application);
}
Edit
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Application application)
{
//db.Entry(application).State = EntityState.Modified;
db.Entry(application).Property(o => o.Interview).IsModified = true;
db.Entry(application).Property(o => o.Comments).IsModified = true;
db.Entry(application).Property(o => o.Notes).IsModified = true;
db.Entry(application).Property(o => o.Unfit).IsModified = true;
db.Entry(application).Property(o => o.Candidate).IsModified = true;
db.SaveChanges();
return RedirectToAction("Index");
//return View(application);
}
If you want to change certain values, according to your above code does not know which property is modified. You can set properties as isModified=true that you want to change value of properties.
EDIT:
db.Application.Attach(application);
db.Entry(application).Property(o => o.Interview).IsModified = true;
db.Entry(application).Property(o => o.Comments).IsModified = true;
db.SaveChanges();
return RedirectToAction("Index");
Or you can make this below way with list;
var included= new[] { "Interview ", "Comments " };
var entry = context.Entry(obj);
entry.State = EntityState.Modified;
foreach (var name in included)
{
entry.Property(name).IsModified = true;
}
I figured out how to fix it, whilst keeping #Html.BeginForm() empty
edit action
// POST: Applications/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Application application, string id)
{
var data = db.Applications.Find(id);
data.Interview = application.Interview;
data.Comments = application.Comments;
data.Notes = application.Notes;
data.Unfit = application.Unfit;
data.Candidate = application.Candidate;
db.SaveChanges();
return RedirectToAction("Index");
}
I am fairly new to coding, and am working on a personal MVC project. I am trying to implement a DropDown that uses values submitted by the user. I believe I have almost everything written correctly, but when I go to update an entity, I get the following error:
The ViewData item that has the key 'WrestlerId' is of type 'System.Int32' but must be of type 'IEnumerable'.
Any assistance with this would be appreciated, and I will edit/update to help figure this out.
Edit: The error itself happens in the View on the following line of code:
#Html.DropDownListFor(x => Model.WrestlerId, Model.Wrestlers, htmlAttributes: new { #class = "form-control" })
Model
public class TitleEdit
{
public int TitleId { get; set; }
public string TitleName { get; set; }
[Display (Name = "Favorite")]
public bool IsStarred { get; set; }
[Display(Name ="Date Established")]
public DateTime DateEstablished { get; set; }
[Display(Name = "Current Champion")]
public int? WrestlerId { get; set; }
public string WrestlerName { get; set; }
public IEnumerable<SelectListItem> Wrestlers { get; set; }
}
View
#model Models.TitleCRUD.TitleEdit
#{
ViewBag.Title = "Edit";
}
<h2>Updating Title</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.TitleId)
<div class="form-group">
#Html.LabelFor(model => model.TitleName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.TitleName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.TitleName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.IsStarred, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.IsStarred)
#Html.ValidationMessageFor(model => model.IsStarred, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DateEstablished, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DateEstablished, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.DateEstablished, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.WrestlerId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(x => Model.WrestlerId, Model.Wrestlers, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Wrestlers, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div id="linkColor">
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Controller
//GET: Edit
public ActionResult Edit(int id)
{
var service = CreateTitleService();
var detail = service.GetTitleById(id);
var wrestlerList = new WrestlerRepo();
var model = new TitleEdit
{
TitleId = detail.TitleId,
TitleName = detail.TitleName,
IsStarred = detail.IsStarred,
DateEstablished = detail.DateEstablished,
WrestlerId = detail.WrestlerId
};
model.Wrestlers = wrestlerList.GetWrestlers();
return View(model);
}
//POST: Edit
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, TitleEdit model)
{
if (!ModelState.IsValid)
{
var wrestlerList = new WrestlerRepo();
model.Wrestlers = wrestlerList.GetWrestlers();
return View(model);
}
if (model.TitleId != id)
{
ModelState.AddModelError("", "ID Mismatch");
return View(model);
}
var service = CreateTitleService();
if (service.UpdateTitle(model))
{
TempData["SaveResult"] = "The title has been updated!";
return RedirectToAction("Index");
}
ModelState.AddModelError("", "The title could not be updated.");
return View(model);
}
GetWrestlers()
public IEnumerable<SelectListItem> GetWrestlers()
{
using (var ctx = new ApplicationDbContext())
{
List<SelectListItem> wrestlers = ctx.Wrestlers.AsNoTracking()
.OrderBy(n => n.RingName)
.Select(n =>
new SelectListItem
{
Value = n.WrestlerId.ToString(),
Text = n.RingName
}).ToList();
var wrestlerTip = new SelectListItem()
{
Value = null,
Text = "Select a Wrestler"
};
wrestlers.Insert(0, wrestlerTip);
return new SelectList(wrestlers, "Value", "Text");
}
}
This question already has answers here:
MVC5 - How to set "selectedValue" in DropDownListFor Html helper
(5 answers)
Closed 4 years ago.
I'm quite new to ASP.Net and I'm trying to make a reservation to a specified branch. When I click the reservation link of a branch, it comes to a drop-down list for me to choose a branch from those already existed in the database. What I want is the branch has already been set based on the reservation link of that branch I clicked. In the database, the reservation entity has an attribute referencing to the branchId in the branch entity. I have viewed some related questions such as MVC5 - How to set “selectedValue” in DropDownListFor Html helper, but neither solved my question properly. I still have no idea of this for now.
The following images are what it looks like now.
This is the create action in my reservation controller:
// GET: Reservations/Create
public ActionResult Create()
{
ViewBag.branchId = new SelectList(db.Branches, "branchId", "name");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "reservationId,branchId,customerId,date")] Reservation reservation)
{
reservation.customerId = User.Identity.GetUserId();
ModelState.Clear();
TryValidateModel(reservation);
if (ModelState.IsValid)
{
db.Reservations.Add(reservation);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.branchId = new SelectList(db.Branches, "branchId", "name", reservation.branchId);
return View(reservation);
}
This is my reservation create view:
#model Mel_Medicare_Location_Reservation_System.Models.Reservation
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Reservation</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group ">
#Html.LabelFor(model => model.branchId, "branchId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("branchId", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.branchId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.customerId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.customerId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.customerId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.date, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.date, "", 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("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
You should have the dropdown options as a get-only property of your model, then use the #Html.DropDownListFor() HTML helper to bind model.branchId to that list, which will set the value appropriately.
I would re-write your Create() controller method to return the view with an instance of the Reservation view model bound to it. This will involve adding a constructor to the view model class which accepts a branch id as a parameter. Something like:
// GET: Reservations/Create
public ActionResult Create(int branchId)
{
return View(new Reservation(branchId));
}
And in your Reservation model:
public class Reservation
{
public int BranchId { get; set; }
// Other properties...
public SelectList BranchOptions
{
get
{
return new SelectList(db.Branches);
}
}
public Reservation(int branchId)
{
this.BranchId = branchId;
}
}
Then in your view:
#Html.DropDownListFor(m => m.BranchId, Model.BranchOptions, htmlAttributes: new { #class = "form-control" })
Got 3 tables :
Question (QuestionId,QuestionText)
Survey(SurveyId,QuestionId,UserId,AnswerTExt,Comment)
User(UserId,UserName)
How to make a form in a view for all questions in table question .
Example I got 90 questions , when I answer this form 5 times , Table answers must have 450 records
Controller:
public class SurveysController : Controller
{
private TESTEntities db = new TESTEntities();
// GET: Surveys
public ActionResult Index()
{
var surveys = db.Surveys.Include(s => s.Question).Include(s => s.User);
return View(surveys.ToList());
}
// GET: Surveys/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Survey survey = db.Surveys.Find(id);
if (survey == null)
{
return HttpNotFound();
}
return View(survey);
}
// GET: Surveys/Create
public ActionResult Create()
{
ViewBag.QuestionId = new SelectList(db.Questions, "QuesionId", "QuestionText");
ViewBag.UserId = new SelectList(db.Users, "UserId", "Name");
return View();
}
// POST: Surveys/Create
// 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 Create([Bind(Include = "SuerveyId,UserId,QuestionId,Answer,Comment")] Survey survey)
{
if (ModelState.IsValid)
{
db.Surveys.Add(survey);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.QuestionId = new SelectList(db.Questions, "QuesionId", "QuestionText", survey.QuestionId);
ViewBag.UserId = new SelectList(db.Users, "UserId", "Name", survey.UserId);
return View(survey);
}
// GET: Surveys/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Survey survey = db.Surveys.Find(id);
if (survey == null)
{
return HttpNotFound();
}
ViewBag.QuestionId = new SelectList(db.Questions, "QuesionId", "QuestionText", survey.QuestionId);
ViewBag.UserId = new SelectList(db.Users, "UserId", "Name", survey.UserId);
return View(survey);
}
// POST: Surveys/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 = "SuerveyId,UserId,QuestionId,Answer,Comment")] Survey survey)
{
if (ModelState.IsValid)
{
db.Entry(survey).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.QuestionId = new SelectList(db.Questions, "QuesionId", "QuestionText", survey.QuestionId);
ViewBag.UserId = new SelectList(db.Users, "UserId", "Name", survey.UserId);
return View(survey);
}
// GET: Surveys/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Survey survey = db.Surveys.Find(id);
if (survey == null)
{
return HttpNotFound();
}
return View(survey);
}
// POST: Surveys/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Survey survey = db.Surveys.Find(id);
db.Surveys.Remove(survey);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
Create View:
#model TEST.Models.Survey
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Survey</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.UserId, "UserId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("UserId", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.UserId, "", new { #class = "text-danger" })
</div>
</div>
#foreach (var item in ViewBag.QuestionId)
{
<div class="form-group">
#Html.LabelFor(model => model.QuestionId, "QuestionId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.HiddenFor(s=>s.QuestionId)
#Html.ValueFor(s =>item)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Answer, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Answer, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Answer, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Comment, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Comment, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Comment, "", 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("Back to List", "Index")
</div>
First I want to make sure I understand what you are trying to do.
In your Create action you are getting all the Questions from the Question table and adding them to the View bag as QuestionId.
Assuming that when you debug the code, you see the correct data in Viewbag.QuestionId when you try to print your label to the screen with
#Html.LabelFor(model => model.QuestionId, "QuestionId", htmlAttributes: new { #class = "control-label col-md-2" })
You are trying to print out the object of QuestionId. I think you need to use 'item' in your label because this changes as your code iterates through the collection.
item.Question
should be used where you want to print out the text of the question
.NET 4.51, MVC 5
I have a view Edit.cshtml as follows:
#model EnergyMission.Country.Dtos.GetCountryOutput
#{
ViewBag.Title = "Edit Country";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#Html.Partial("_AddEditPartial", new ViewDataDictionary { { "ActionName", "Edit" } })
and then New.cshtml as follows:
#model EnergyMission.Country.Dtos.GetNewCountryOutput
#{
ViewBag.Title = "New Country";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#Html.Partial("_AddEditPartial", new ViewDataDictionary { { "ActionName", "Create" } })
Note from the above that:
Each one has a different model namely GetCountryOutput and GetNewCountryOutput. Both of these have the same properties. Currently they cannot be made the same class for other reasons.
I pass the action name so that I can use it in the Html.BeginForm in the partial view
I still need to figure out how to pass the model type to the partial view
The _AddEditPartial.cshtml looks as follows:
#model EnergyMission.Country.Dtos.GetCountryOutput
<h3>#ViewData["ActionName"]</h3>
#using (Html.BeginForm(#ViewData["ActionName"], "Countries"))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>CountryTableModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.AbbreviationCode, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.AbbreviationCode, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.AbbreviationCode, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.InternationalCountryDialCode, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.InternationalCountryDialCode, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.InternationalCountryDialCode, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
</div>
}
My questions are as follows:
Is there an easier way to share a common data entry layout for Add / Edit operations that whay I am doing above?
If I were to follow the approach described how do I:
Pass the model type to the partial view. Is it something like:
_
#Html.Partial("_AddEditPartial", new ViewDataDictionary { { "ActionName", "Create" }, {"ModelTypeName", "EnergyMission.Country.Dtos.GetCountryOutput"} })
and then in _AddEdit.cshtml
_
#model typeof(#ViewData["ModelTypeName"])
Why is the following not valid:
_
#using (Html.BeginForm(ViewData["ActionName"], "Countries"))
as that gives me a compile time error.
Create a single view, then use your controller to direct to a single view and use your repository to insert/update accordingly in a Save method. However, please note, in the example below you will need to make sure the model is the same - based on the principle that you should remove duplication. If that's not possible consider using a dynamic model in your view or using the ViewModel you can map the properties accordingly (anyway I don't want to over complicate the answer as I'm hoping this provides the solution you need - give or take some refactoring here and there).
A simplified example of the controller and repository (using a viewmodel)....
public class ProductController : Controller
{
private IProductRepository _repository;
public ProductController(IProductRepository productsRepository)
{
this._repository = productsRepository;
}
public ViewResult Edit(int productID)
{
ProductEditViewModel model = new ProductEditViewModel
{
Product = this._repository.Products.Where(m => m.ProductID == productID).FirstOrDefault()
};
return View(model);
}
[HttpPost]
public ActionResult Edit(int productId)
{
ProductEditViewModel model = new ProductEditViewModel
{
Product = _repository.Products.First(m => m.ProductID == productId)
};
TryUpdateModel(model);
if (ModelState.IsValid)
{
_repository.Save(model.Product);
return RedirectToAction("Index");
}
else
{
return View(model);
}
}
public ViewResult Create()
{
return View("Edit", new Product());
}
[HttpPost]
public ActionResult Create(Product product)
{
return Edit(product.ProductID);
}
}
The repository....
public class SqlProductRepository : IProductRepository
{
private MyDataContext db;
private Table<Product> _productsTable;
public IQueryable<Product> Products
{
get { return _productsTable; }
}
public void Save(Product product)
{
if (product.ProductID == 0)
{
_productsTable.InsertOnSubmit(product);
}
else if (_productsTable.GetOriginalEntityState(product) == null)
{
_productsTable.Attach(product);
_productsTable.Context.Refresh(RefreshMode.KeepCurrentValues, product);
}
_productsTable.Context.SubmitChanges();
}
}
Well the answer to 3. is that html.beginform expects a string as its first parameter, and as you are using ViewData which is a
Dictionary<string, object>
you need to cast your value as a string:
#using (Html.BeginForm(ViewData["ActionName"] as string, "Countries"))
For 1. You could try deriving both of your dto classes from a base class and setting that class as the model type for both the add and edit views