i m working on MVC application and using Entity Framework 4.0 for database connection.While editing record i want to update some fields in table. code for edit is
[HttpPost]
public ActionResult Edit(ProjectActivityDetail projectactivitydetail, FormCollection formcollection)
{
if (ModelState.IsValid)
{
string value = Request["ChkIntBool"];
if (value.Substring(0, 4) == "true") { projectactivitydetail.IsApproved = 1; } else { projectactivitydetail.IsApproved = 0; }
projectactivitydetail.ProjectActivityDID = long.Parse(Session["ProjectActivityDID"].ToString());
projectactivitydetail.UpatedBy = long.Parse(Session["UserID"].ToString());
projectactivitydetail.UpdatedON = System.DateTime.Now;
db.Entry(projectactivitydetail).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.FK_ProjectActivityID = new SelectList(db.ProjectActivityMasters, "ProjectActivityID", "ActivityName", projectactivitydetail.FK_ProjectActivityID);
return View(projectactivitydetail);
}
i just want to update these fields but when this executred my other fields updated to null , is there any way i can keep those values as it is and update these many values in database table.please help
It looks like the entity being passed into the service call is not complete. My advice would be to find the existing entity and make the changes to that rather than attaching the one passed in:
[HttpPost]
public ActionResult Edit(ProjectActivityDetail projectactivitydetail, FormCollection formcollection)
{
if (ModelState.IsValid)
{
//I'm assuming the PK of the entity is id so adjust for that
var entity = db.Set<ProjectActivityDetail>().Find(projectactivitydetail.id);
string value = Request["ChkIntBool"];
entity.IsApproved = value.Substring(0, 4) == "true" ? 1 : 0;
entity.ProjectActivityDID = long.Parse(Session["ProjectActivityDID"].ToString());
entity.UpatedBy = long.Parse(Session["UserID"].ToString());
entity.UpdatedON = System.DateTime.Now;
db.Entry(entity).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.FK_ProjectActivityID = new SelectList(db.ProjectActivityMasters, "ProjectActivityID", "ActivityName", projectactivitydetail.FK_ProjectActivityID);
return View(projectactivitydetail);
}
Yes, there's a way. Add hidden fields to your view with the data you want to persist on the model, int this case ProjectActivityDetail, this way the properties will get bound to the projectactivitydetail variable on the model binding stage.
Suppose you have a property called CreatedOn that is being set to null, on your view you'd add:
#Html.HiddenFor(model => model.CreatedOn)
Then, when you submit the form the value originally on CreatedOn will be bound to the property at projectactivitydetail and your model will be saved just fine. Your fields are being updated to null because model binding is not finding any values for them.
Good luck.
Related
I have a model called Employee with a boolean field called OnDuty. Our business rules only allow for one employee on duty.
On the index page, I've setup the checkbox so they trigger an update call to update the employee as being "on call". However, I'm not set any other employees to off duty using my controller action below. How do I go about making sure that no other employee is on duty?
[HttpPost]
public JsonResult Update(Employee employee)
{
IEnumerable<Employee> onCallEmployee = _db.Employees.Where(e => e.OnCall == true);
foreach (Employee e in onCallEmployee) {
e.OnCall = false;
_db.Entry(e).State = EntityState.Modified;
_db.SaveChanges();
}
_db.Entry(employee).State = EntityState.Modified;
_db.SaveChanges();
return Json("Employee updated!");
}
It appears that my error(s) were caused by the way I was trying to update the employees. I had to exclude the employee which was already being updated by the function from onCallEmployee because it would throw an error (Attaching an entity of type 'Employee' failed because another entity of the same type already has the same primary key value.) when trying to save the updates.
Also, based on #mwwallace8, suggestion, I removed the SaveChanges() call from the for loop and left a single call at the end.
[HttpPost]
public JsonResult Update(Employee employee)
{
IEnumerable<Employee> onCallEmployee = _db.Employees.Where(e => e.OnCall == true && e.ID != employee.ID);
foreach (Employee e in onCallEmployee) {
e.OnCall = false;
_db.Entry(e).State = EntityState.Modified;
}
_db.Entry(employee).State = EntityState.Modified;
_db.SaveChanges();
return Json("Employee updated!");
}
I've been new to ASP.NET MVC. This is what I'm doing. I've 2 Controllers:Home and Customerservice.
Now I have a Customer list where when I click details gets redirected to the products he acquired.
So, I need to pass in the id so that the products of that customer can be displayed. So, my home consists of customer details. Now i need to pass that id to CustomerService controller ,Index action. This is what I've done in Home:
public ActionResult Customers()
{
var dc = new ServicesDataContext();
var query = (from m in dc.Customers
select m);
return View(query);
}
public ActionResult Details(int id)
{
var datacontext = new ServicesDataContext();
var serviceToUpdate = datacontext.Customers.First(m => m.CustomerId == id);
ViewData.Model = serviceToUpdate;
// return View();
return Redirect("/CustomerService");
}
[HttpPost]
public ActionResult Details(FormCollection form)
{
var id = Int32.Parse(form["CustomerID"]);
var datacontext = new ServicesDataContext();
var service = datacontext.Customers.First(m => m.CustomerId == id);
return Redirect("Customers");
}
}
Now I'm not sure whether I need to pass an id as parameter for index in CustomerService. SO can you please guide me in finishing this?
If you are using any Redirect (such as RedirectToAction) you can use TempData to store any parameters. The semantics have slightly changed in MVC 3 but TempData is designed to pass data between actions in a POST-Redirect-GET scenario.
Passing it as a parameter is probably your best option. Try using something like return RedirectToAction(ActionName, ControllerName, RouteValues);.
i'm quite new to Entity Framework (and asp.net mvc 3) and this is my really first experience with EF4.1 code first.
My question is simple: when I generate via model a new table for database I would like to make
Automatically add current datetime to a field when a new row is created.
Automatically update the field every time the field is updated.
Actually, the variable appears like:
[DisplayName("Data Modifica")]
[DataType(DataType.DateTime)]
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime DataModifica { get; set; }
I guess i could write something on "OnModelCreating" event of datacontext but I'm too new to already master this :)
Can someone help?
thanks in advance,
V.
That has nothing to do with creation of model. The "model" is description of your mapping between classes and database. OnModelCreating is used to modify mapping definition, not to modify data. It has nothing to do with data in the entity instance itself.
If you want automatic modification you can override SaveChanges:
public override int SaveChanges()
{
DateTime now = DateTime.Now;
foreach (var entity in ChangeTracker.Entries<YourEntityType>()
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
.Select(e => e.Entity))
{
entity.DateModifica = now; // set the date
}
return base.SaveChanges();
}
Why not define the property to be one with a backing field, which is initialized to the default value ?
private DateTime _dateOfRequest = DateTime.Today;
[Display(Name = "Date of Request"), DataType(DataType.Date)]
public System.DateTime DateOfRequest {
get { return _dateOfRequest; }
set { _dateOfRequest = value; }
}
I'm trying to create a very basic MVC app based on a tutorial. I am using the default routing, and simple Views and Model.
The problem I am having is with the HttpPost Edit function. I am expecting an object of my "MyObject" type to be passed as the parameter, but it always comes back null.
Here are my Edit functions from the controller (the Get function works properly):
public ActionResult Edit(int? id)
{
if (!id.HasValue)
return RedirectToAction("Index");
var item = (from obj in mDB.MyDatabaseObjects
where obj.Id == id
select obj).First();
return View(item);
}
//
// POST: /Main/Edit/5
[HttpPost]
public ActionResult Edit(MyDatabaseObject someObject)
{
var original = (from obj in mDB.MyDatabaseObjects
where obj.Id == someObject.Id
select obj).First();
if (!ModelState.IsValid)
return View(original);
mDB.ApplyCurrentValues(original.EntityKey.EntitySetName, someObject);
mDB.SaveChanges();
return RedirectToAction("Index");
}
Note that my (nearly identical) Create method works as expected:
[HttpPost]
public ActionResult Create([Bind(Exclude="Id")] MyDatabaseObject newObject)
{
if (!ModelState.IsValid)
return View();
int max = mDB.MyDatabaseObjects.Max(data => data.TaskOrder);
newObject.TaskOrder = max + 1;
mDB.AddToMyDatabaseObjects(newObject);
mDB.SaveChanges();
return RedirectToAction("Index");
}
Thanks,
wTs
Ensure the values on your view for MyDatabaseObject are inside of the form. Validate these values are being posted over - inspect Request.Form or use change the method signature to use
FormsCollection collection
simply to validate the values are getting posted. If its choosing that method - it should be matching the properties to the form field - its generally very simple.
If I have the usual Edit actions, one for GET to retrieve an object by it's ID and to display it in an edit form. The next for POST to take the values in the ViewModel and update the object in the database.
public virtual ActionResult Edit(int id)
[HttpPost]
public ActionResult Edit(VehicleVariantEditSaveViewModel viewModel)
If an error occurs during model binding in the POST action, I understand I can RedirectToAction back to the GET action and preserve the ModelState validation errors by copying it to TempData and retrieving it after the redirect in the GET action.
if (TempData["ViewData"] != null)
{
ViewData = (ViewDataDictionary)TempData["ViewData"];
}
How do I then convert that ViewData, which includes the previous invalid ModelState, into a new model to send to the view so the user sees their invalid input with validation warnings? Oddly enough if I pass in a new instance of my ViewModel retrieved from the database (with the original valid data) to the View() this is ignored and the (invalid) data in the ViewData is displayed!
Thanks
I had a similar problem and decided to use the following pattern:
public ActionResult PersonalRecord(Guid id)
{
if (TempData["Model"] == null)
{
var personalRecord = _context.PersonalRecords.Single(p => p.UserId == id);
var model = personalRecord.ToPersonalRecordModel();
return View(model);
}
else
{
ViewData = (ViewDataDictionary) TempData["ViewData"];
return View(TempData["Model"]);
}
}
[HttpPost]
public ActionResult PersonalRecord(PersonalRecordModel model)
{
try
{
if (ModelState.IsValid)
{
var personalRecord = _context.PersonalRecords.Single(u => u.UserId == model.UserId);
personalRecord.Email = model.Email;
personalRecord.DOB = model.DOB;
personalRecord.PrimaryPhone = model.PrimaryPhone;
_context.Update(personalRecord);
_context.SaveChanges();
return RedirectToAction("PersonalRecord");
}
}
catch (DbEntityValidationException ex)
{
var errors = ex.EntityValidationErrors.First();
foreach (var propertyError in errors.ValidationErrors)
{
ModelState.AddModelError(propertyError.PropertyName, propertyError.ErrorMessage);
}
}
TempData["Model"] = model;
TempData["ViewData"] = ViewData;
return RedirectToAction("PersonalRecord", new { id = model.UserId });
}
Hope this helps.
I noticed that the Model is included in ViewData so you don't need to pass it in addition to the ViewData, what I don't understand is how you get at it to then return it to the view.
public ViewResult Edit(int id)
{
// Check if we have ViewData in the session from a previous attempt which failed validation
if (TempData["ViewData"] != null)
{
ViewData = (ViewDataDictionary)TempData["ViewData"];
}
VehicleVariantEditViewModel viewModel = new VehicleVariantControllerViewModelBuilder()
.BuildForEdit(id);
return View(viewModel);
}
The above works but obviously it's making an unnecessary call to the database to build a new Model (which gets automagically overwritten with the invalid values from the Model in the passed ViewData)
Confusing.