MVC 5 Edit Action Saving Input Error - c#

When I'm editing a "salesmember" and I'm trying to save the new file path / or old file path, based on user input, it should either overwrite the image, or it will use the previous image stored in the DB.
But, when I try to modify the entity state, before I save the changes in my SQL Server, I get the error:
An exception of type 'System.InvalidOperationException' occured in EntityFramework.dll but was not handled in user code. Additional information: Attaching an entity of type 'SalesMember' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
I'm modifying the SalesMember with that primary key. Which, it saves the image locally, but it won't save the DB row.
My Edit Action -----
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="SalesMemberID,FirstName,LastName,PageName,CellPhone,Email,InactiveRedirectTo,CustomText,Photo,Active, Position")] SalesMember salesmember, HttpPostedFileBase file)
{
SalesMember SalesPhoto = db.SalesMembers.Find(salesmember.SalesMemberID);
salesmember.Photo = saveImage(file, salesmember, SalesPhoto);
if (ModelState.IsValid)
{
salesmember.AddDate = SalesPhoto.AddDate;
salesmember.UpdateDate = DateTime.Now;
salesmember.IPAddress = Request.UserHostAddress;
salesmember.AddUser = "admin";
salesmember.UpdateUser = "admin";
db.Entry(salesmember).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(salesmember);
}
SalesPhoto Save Function --
private string saveImage(HttpPostedFileBase file, SalesMember salesmember, SalesMember SalesPhoto = null)
{
string photo = "";
string returnPhoto = "";
//File blank
if( file == null )
//If File Path For that User Already In DB, return that File Path
if(! String.IsNullOrEmpty(SalesPhoto.Photo))
return "/Images/no-upload-icon.jpg";
//If File ! empty, Save image uploaded
photo = Server.MapPath("/Images/" + salesmember.PageName.ToString() + ".jpg");
file.SaveAs(photo);
returnPhoto = "/Images/" + salesmember.PageName.ToString() + ".jpg";
return returnPhoto;
}
I believe it has to do with the LINQ Query, as when I remove the LINQ Query & saveImage method and just save the photo with a test path(i.e., "/Images/foo.jpg"), it works.
Thanks in advance.

You can not have two entities (same type) with same primary keys in memory in Entity Framework. salesmember and SalesPhoto if you want to have AddDate in your form Edit, you can Include it as a HiddenField in form, Or
my recommendation is to deal with ViewModels not EF models in views to
ignore these Issues
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="SalesMemberID,FirstName,LastName,PageName,CellPhone,Email,InactiveRedirectTo,CustomText,Photo,Active, Position")] SalesMember salesmember, HttpPostedFileBase file)
{
SalesMember SalesPhoto = db.SalesMembers.AsNoTracking().Find(salesmember.SalesMemberID);
salesmember.Photo = saveImage(file, salesmember, SalesPhoto);
if (ModelState.IsValid)
{
salesmember.AddDate = SalesPhoto.AddDate;
salesmember.UpdateDate = DateTime.Now;
salesmember.IPAddress = Request.UserHostAddress;
salesmember.AddUser = "admin";
salesmember.UpdateUser = "admin";
db.Entry(salesmember).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(salesmember);
}

Related

How can I delete an image in my image folder?

I can delete an image in my database but not in an image folder.
I want to delete also the image in folder when I delete the row.
public IActionResult Delete(int? id,MotorModel motor)
{
var motors = db.Motors.Find(id);
var filename = motor.Image.FileName;
var delete = Path.Combine(hostEnvironment.WebRootPath, "Image");
var filePath = Path.Combine(delete, filename);
if (motors == null)
{
return View();
}
db.Entry(motors).State = EntityState.Deleted;
if (db.SaveChanges() > 0)
{
if (System.IO.File.Exists(filePath))
{
System.IO.File.Delete(filePath);
}
return RedirectToAction("Index");
}
return View();
}
I suspect this is because you've made the questionable decision to have a method argument MotorModel motor and a local variable car motors = db.Motors.Find... and you're getting confused as to which motor/motors you're supposed to be using. Xavier is asking you "is anything null?" and you're looking in motors and going "nope, nothing is null" and the code is trying to delete based on motor instead
In my opinion a delete method need only take an id, it should look up what to delete based on that id and remove the file that is tracked by the db. It should not take an id and some other user provided data (motormodel) and delete files based on what it finds in the user provided data. It opens you up to abuse/hacking attempts if you're allowing the user to choose what files to delete arbitrarily by modifying the data provided. On that point too you should verify, given that the is to delete is an int, that the user truly owns the file they are deleting otherwise some script kid will just write a loop that calls Delete(1), Delete(2) ... Delete(10000000) and hose the entire contents of your server, for a laugh
As a style tip, a Find method will only return one entity so the variable to which it is assigned shouldn't have a plural name. Use plurals for collections of items

Inserting a row into Relational database table

I am very new to c# and asp.net mvc. I'm building a HR portal for our company where a user can submit a leave form among other things... So I'm using mssql as the database server and using Entity Frame work to communicate with it. I have 3 entities, user (Containing user details), permissions (the user permissions for allowing actions in the app) and then the leave form table (where the leave form details are stored). There is a one to many relationship between user - permission and then a one to many relationship between user-leave. I am not fazed about the permissions as that gets created when the user account is being created.
The problem I am facing is, how do I add a leave form for a specific user? Below is my controller code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Leave(MasterViewModel model)
{
DocSubViewModel mv = model.DSModel;
int userId = Convert.ToInt32(Session["userID"]);
try
{
using (HrDcpDBContainer db = new HrDcpDBContainer())
{
var leave = db.leaves.Create();
leave.dateFrom = mv.DateFrom;
leave.dateSubmitted = DateTime.Now;
leave.dateTo = mv.DateTo;
leave.nrDays = mv.NrDays;
leave.reason = mv.SpecialLeave;
leave.TLApproval = null;
leave.TLApprovalDate = null;
leave.TLApprovalID = mv.TeamLeaderID;
leave.DMApprovalDate = null;
leave.DMApprovalID = mv.DepManagerID;
leave.DMApproval = null;
leave.type = mv.Type;
leave.user = userId;
db.leaves.Add(leave);
db.SaveChanges();
}
ViewBag.Message = "Leave Form submitted Successfully. You will be redirected shortly...";
return View("result");
}
catch (Exception ex)
{
ViewBag.Message = ex;
//ViewBag.Message = "Leave Form submitted Successfully. You will be redirected shortly...";
return View("result");
}
The problem comes in leave.user = userId;. It says:
Cannot implicitly convert int to Portal.Model.user
I can't seem to find out how to do this...
You're telling it to put the UserId where your leave model is asking for a User.
Your relationship requires a User to go in there, so you'll have to update your code a little bit:
using (HrDcpDBContainer db = new HrDcpDBContainer())
{
var leave = db.leaves.Create();
leave.user = db.users.First(x => x.Id == userId);
}
This will put reference to the actual user in the new leave record. If you go later and check it out you'll see a column in the leave table called user_Id that has an integer value in it and is set as a foreign key to the users table.
Note that this will error if no user exists having the specified Id value. If you anticipate this to be a problem, rather use .FirstOrDefault() instead of .First() and then account for the value being null before you add it to your new leave object.
That's expected since User is a object and not int. What you should be doing probably is leave.user.UserId = userId; instead [Assuming leave.user is of type User which has a UserId property]

Trouble editing the role

I am having a problem in editing the role of a user. I have these codes:
`
Entities db2 = new Entities();
private UsersContext db = new UsersContext();
//
// POST: /AdminOnly/Edit/5
[Authorize(Roles = "Owner")]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(UserProfile userprofile, int? roless)
{
if (ModelState.IsValid)
{
webpages_UsersInRoles s = new webpages_UsersInRoles();
s = db2.webpages_UsersInRoles.Where(m => m.UserId == userprofile.UserId).FirstOrDefault();
if (s != null) //with existing role, edit it
{
s.RoleId = roless.Value;
db.Entry(userprofile).State = EntityState.Modified;
db2.Entry(s).State = EntityState.Modified;
db.SaveChanges();
db2.SaveChanges();
return RedirectToAction("Index");
}
else //no existing role
{
//some code here
}
}
ViewBag.roless = new SelectList(db2.webpages_Roles, "RoleId", "RoleName");
return View(userprofile);
}
`
When I try to save the changes in the database, db2.SaveChanges(); throws me an error that says:
An exception of type 'System.InvalidOperationException' occurred in
System.Data.Entity.dll but was not handled in user code
Additional information: The property 'RoleId' is part of the object's
key information and cannot be modified.
What should I do? Thanks in advance!
RoleId is used as key constraint and main identifier of entity. You can't change this id. Just don't update this property or add more comments why do you need to update it.
It's saying that RoleId is part of the primary key and cannot be changed. Instead of editing the existing row in webpages_UsersInRoles, try deleting that row and adding a new one with the new RoleId value.
Turns out that the column I want to change is a compound foreign key. I need to remove the first value of the RoleId and save the changes to the table. And add again the second value and save the new changes to the table. Thanks to those who helped!

Fetching collection inside nhibernate session

One property has many photos. One photo belong to one property.
Inside my mvc controller I'm getting as parameter array of integers. These integers represents id of Photo which I want to delete.
I'm using nhibernate session and transaction to interact with db.
public ActionResult DeleteImgs(int[] data)
{
Property p = null;
using (ISession session = ....)
{
using(ITransaction transaction session.BeginTransaction())
{
Photo photo = session.Get<Photo>(data[0]);
p = session.Get<Property>(photo.Id);
// found images and delete them
foreach(int id in data)
{
Photo ph = session.Get<Photo>(id);
//remove property from association so I can delete photo
ph.Property = null;
session.Delete(ph);
session.SaveOrUpdate(ph);
}
//load property now with collection of remaining photos
// here IS THE PROBLEM, Even there is photos inside collection
// in debug I'm getting empty collection
p = session.Query<Property>().
.Fetch(x=>x.Photos).ToList() //empty?
.FirstOrDefault;
transaction.Commit();
}
}
return View();
}
Since I'm sending just IEnumrable of photos to the view problem is solved like this,
instead of sending lazy load property photos collection I'm sending IEnumerable of Photos like this
IEnumerable<Photo>photos = session.Query<Photo>().Where(x => x.Property == p).ToList();

Having problems while updation in asp.net mvc project

My create and delete operations are working well. But, the Edit function is giving the following error :- 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.
NOTE:- CatPicView is a ViewModel merging the two entities Category and Picture
Following is the code for my Edit action code :-
[HttpPost]
public ActionResult Edit(CatPicView catPic)
{
if (ModelState.IsValid)
{
if (!String.IsNullOrEmpty(catPic.Picture.PictureUrl))
{
if (catPic.Category.PictureId == null)
{
Picture picture = new Picture();
picture.PictureUrl = catPic.Picture.PictureUrl;
db.Pictures.Add(picture);
catPic.Category.PictureId = picture.Id;
}
else
{
db.Entry(catPic.Picture).State = EntityState.Modified;
}
}
db.Entry(catPic.Category).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ParentCategoryId = new SelectList(db.Categories, "Id", "Name", catPic.Category.ParentCategoryId);
return View(catPic);
}
Using the debuger, check the properties of the object you are trying to update. The most likely is that you have an ID in null.
To fix this, you should place a hidden field holding the id of the modified object so when posting the form it became mapped to your object.
You are using an ID that does not exist in the current context which is picture.Id. At the time that you are using it an ID has not yet been generated, add db.SaveChanges before attempting to use the ID.
if (catPic.Category.PictureId == null)
{
Picture picture = new Picture();
picture.PictureUrl = catPic.Picture.PictureUrl;
db.Pictures.Add(picture);
db.SaveChanges();
catPic.Category.PictureId = picture.Id;
}

Categories