The standard way to edit a record in ASP.NET MVC is the following:
//
// GET: /Movies/Edit/5
public ActionResult Edit(int id = 0)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return HttpNotFound();
}
return View(movie);
}
//
// POST: /Movies/Edit/5
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
The problem is that I need to edit order details (1 order, many details) and therefore based on two IDs (the order and the product ones). It does not work (I cannot get an OrderDetail item as action parameter). How can I solve this problem?
Thanks.
//
// GET: /Orders/EditDetails
public ActionResult EditDetails(int id, string productID)
{
OrderDetail od = GetOrderDetail(id, productID);
return View(od);
}
//
// POST: /Orders/EditDetails
[HttpPost]
public ActionResult EditDetails(OrderDetail od)
{
if (ModelState.IsValid)
{
context.Entry(od).State = EntityState.Modified;
context.SaveChanges();
return RedirectToAction("Index");
}
return View(od);
}
EDIT: Here is the code requested by Shimmy:
#using (Html.BeginForm("EditDetails", "Orders", FormMethod.Post))
{
#Html.LabelFor(m => m.quantity)
#Html.TextBoxFor(m => m.quantity)
#Html.LabelFor(m => m.productID)
#Html.DropDownListFor(m => m.productID, new SelectList((IEnumerable)ViewBag.productList, "productID", "fullProductName"))
#Html.HiddenFor(model => model.orderID)
}
Make sure the OrderDetail.Id itself as well as the OrderDetail.OrderId and the OrderDetail.MovieId properties are all present in the form as a hidden field.
In that way, when you post it back to the server you have track on what Movie and Order this OrderDetail is of, in the action.
Related
i am new in MVC5. I am trying to load master and details data using ActionResult for retrieving master data and JsonResult for Details retrieving data single click in ActionLink.
public JsonResult getOrderDetails(int? id)
{
List<OrderDetail> OrderDetail = new List<OrderDetail>();
OrderDetail = db.OrderDetails.Where(a => a.OrderID==id).OrderBy(a => a.OrderDetialsID).ToList();
return new JsonResult { Data = OrderDetail, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
OrderMaster OrderMaster = db.OrderMasters.Find(id);
return View(OrderMaster);
}
No, this won't work. It will throw an exception explaining that a link must point to exactly one resource (a.k.a one Controller, one Action). Also, that's not how you normally think of doing it in MVC. This is not WebForms where you load the master and detail separately.
You should be doing something like this instead:
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var orderMaster = db.OrderMasters
.Where(om => om.OrderMasterId == id)
.Include(om => om.OrderDetails) // include the details here
.Single();
return View(orderMaster);
}
I am new to ASP.NET MVC and I'm trying to create a small project but I'm stuck in the Edit Controller part.
This is my "real" controller with a function named PostEditViewModel with the queries inside to change the data.
public EditViewModel PostEditViewModel(EditViewModel model)
{
//var model = new EditViewModel();
using (var db = new NorthwindEntities())
{
var dati = db.Products
.Where(p => p.Id == model.Id).Single();
dati.Id = model.Id;
dati.Name = model.Name;
db.SaveChanges();
return model;
}
}
And this is my controller, its function is to only validate the model state.
[HttpPost]
public ActionResult Edit(EditViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
return RedirectToAction("Index");
}
Any help would be appreciated.
My bad, the validation didn't make sense at all.
[HttpPost]
public ActionResult Edit(EditViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
else
{
WorkerServices.PostEditViewModel(model);
return RedirectToAction("Index");
}
What I want is that when the schedule form is loaded for the first time (or without data passing), it shows a list of MovieName. When I click on one MovieName, its ID is sent back to controller as an input of a SQL query, then the result is passed back to the view.
Here are what I've done. But I think when I click on the ActionLink, the controller doesnt handle the data passed back as it is not HttpPost. Also, I dont know how to show the new data back in view. Please help!
ScheduleController.cs
[HttpGet]
public ActionResult Index()
{
var schedules = db.Schedules.Include(s => s.Movie)
.OrderByDescending(s => s.Movie.MovieName)
.ToList();
return View(schedules);
}
[HttpPost]
public ActionResult Index(int MovieID)
{
//return ("Clicked");
var schedules = (from s in db.Schedules
orderby s.ShowDate
select s).ToList();
return View(schedules);
}
Schedule/Index
#using Booking_Ticket_Management_System.Models;
#model IEnumerable<Schedule>
#{
ViewBag.Title = "Schedule";
}
<h2>Choose movies</h2>
#using (Html.BeginForm())
{
<div>
#foreach (Schedule schedule in #Model)
{
#Html.ActionLink(schedule.Movie.MovieName, "Index", "Schedule", new { MovieID = schedule.MovieID},null)
<br />
}
<br />
</div>
}
Ideally listing and detail view are always separate. i suggest you to make both the view separate.
[HttpGet]
public ActionResult Index()
{
var schedules = db.Schedules.Include(s => s.Movie)
.OrderByDescending(s => s.Movie.MovieName)
.ToList();
return View(schedules);
}
[HttpGet]
public ActionResult Movie(int id)
{
//return ("Clicked");
var schedules = (from s in db.Schedules
Where s.MovieId == id
orderby s.ShowDate
select s).ToList();
return View(schedules);
}
As you do not pass the movieId in your query
Try this :
[HttpPost]
public ActionResult Index(int MovieID)
{
//return ("Clicked");
var schedules = (from s in db.Schedules
where s.MovieId==MovieId
orderby s.ShowDate
select s).ToList();
return View(schedules);
}
But what I will suggest to you is to create another Action and another view to display only the movie clicked.
And as you just want to Get not to modify the value inside the Database. You have to use the [HttpGet]
[HttpGet]
public ActionResult Detail(int MovieID)
{
//return ("Clicked");
var schedule = (from s in db.Schedules
where s.MovieId==MovieId
orderby s.ShowDate
select s).FirstOrDefault();
return View(schedule);
}
And in your Detail view created
#using Booking_Ticket_Management_System.Models;
#model Schedule
In your Index view you must change the ActionLink to:
#Html.ActionLink(schedule.Movie.MovieName, "Detail", "Schedule", new { MovieID = schedule.MovieID},null
Following a tutorial, and have followed it step-by-step but get an error when I want to edit a field.
Source Error:
</div>
<div class="editor-field">
#Html.DropDownList("JobTitleID", String.Empty)
#Html.ValidationMessageFor(model => model.JobTitleID)
</div>
Here's my controller:
// POST: /Employee/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "SIN, FirstName, MiddleName, LastName, StartDate, Salary, JobTitleID, DepartmentID")] Employee employee)
{
try
{
if (ModelState.IsValid)
{
db.Employees.Add(employee);
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DataException dex)
{
if (dex.InnerException.InnerException.Message.Contains("IX_Employee_SIN"))
{
ModelState.AddModelError("SIN", "Unable to save changes. Remember, you cannot have duplicate SIN numbers.");
}
else
{
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
}
DepartmentDropDownList(employee.DepartmentID);
JobDropDownList(employee.JobTitleID);
return View(employee);
}
//
// GET: /Employee/Edit/5
public ActionResult Edit(int id = 0)
{
Employee employee = db.Employees.Find(id);
if (employee == null)
{
return HttpNotFound();
}
DepartmentDropDownList(employee.DepartmentID);
JobDropDownList(employee.JobTitleID);
return View(employee);
}
//
// POST: /Employee/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID, SIN, FirstName, MiddleName, LastName, StartDate, Salary, JobTitleID, DepartmentID")] Employee employee)
{
try
{
if (ModelState.IsValid)
{
db.Employees.Add(employee);
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (DataException dex)
{
if (dex.InnerException.InnerException.Message.Contains("IX_Employee_SIN"))
{
ModelState.AddModelError("SIN", "Unable to save changes. Remember, you cannot have duplicate SIN numbers.");
}
else
{
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
}
DepartmentDropDownList(employee.DepartmentID);
JobDropDownList(employee.JobTitleID);
return View(employee);
}
private void JobDropDownList(object selectedJob = null)
{
var dQuery = from d in db.JobTitles
orderby d.Title
select d;
ViewBag.JobID = new SelectList(dQuery, "ID", "Title", selectedJob);
}
private void DepartmentDropDownList(object selectedDepartment = null)
{
var dQuery = from d in db.Departments
orderby d.DepartmentName
select d;
ViewBag.DepartmentID = new SelectList(dQuery, "ID", "DepartmentName",selectedDepartment);
}
I'm not really that familiar with MVC, just thought I'd ask what the issue is, and how it can be fixed.
The ViewBag encapsulate the ViewData internally, so, the message you are getting is about the ViewBag. You have setted the ViewBag.JobID on the controller and in your view you are trying to use another key, JobTitleID. Try using the right key:
#Html.DropDownList("JobID", String.Empty)
I'm a new to MVC and getting troubles with saving edited information of an action.
Every time I trying to SaveChanges I'm getting:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
Here is my code:
[Authorize]
[HttpPost]
public ActionResult Profile(designer thisDesigner)
{
if (ModelState.IsValid)
{
db.Entry(thisDesigner).State = System.Data.EntityState.Modified;
try
{
db.SaveChanges();
}
catch (Exception)
{
return View(thisDesigner);
}
}
return RedirectToAction("Profile");
}
Also tried to query for new object and then to set and save the new values, in this case doesn't getting the exception, but the data is't saved.
Here is the code:
[Authorize]
[HttpPost]
public ActionResult Profile(designer thisDesigner)
{
designer updateDesigner = db.designers.Find(thisDesigner.designer_id);
if (ModelState.IsValid && updateDesigner != null)
{
db.Entry(updateDesigner).OriginalValues.SetValues(thisDesigner);
db.Entry(updateDesigner).State = System.Data.EntityState.Modified;
try
{
db.SaveChanges();
}
catch (Exception)
{
return View(thisDesigner);
}
}
return RedirectToAction("Profile");
}
Got it working :)
Just needed to add all properties of my model to page, like this:
#Html.HiddenFor(model => model.designer_id)
#Html.HiddenFor(model => model.designer_login_status)
#Html.HiddenFor(model => model.designer_register_date)
#Html.HiddenFor(model => model.designer_small_logo)
#Html.HiddenFor(model => model.designer_status)
#Html.HiddenFor(model => model.designer_vip_date)
And used same code from first example:
[Authorize]
[HttpPost]
public ActionResult Profile(designer thisDesigner)
{
if (ModelState.IsValid)
{
db.Entry(thisDesigner).State = System.Data.EntityState.Modified;
try
{
db.SaveChanges();
}
catch (Exception)
{
return View(thisDesigner);
}
}
return RedirectToAction("Profile");
}