How to solve This modify Controller? - c#

Every Thing goes right ,I've all the values that make me get the new model with values to modify it but something goes wrong at the final step
and my model validation state is true
This is my post Controller
[HttpPost]
public ActionResult Edit(Problem problem, HttpPostedFileBase fileUpload)
{
Problem Edproblem = db.Problems.Find(problem.Id);
ViewBag.ATMId = new SelectList(db.ATMs, "Id", "AtmNumber", Edproblem.ATM.AtmNumber);
ViewBag.UserId = WebSecurity.GetUserId(User.Identity.Name);
ViewBag.ProblemTypeId = new SelectList(db.ProblemTypes, "Id", "Name", Edproblem.ProblemTypeId);
var bankId = from e in db.ATMs where e.Id == problem.ATMId select e;
ViewBag.BankId = new SelectList(db.Banks, "Id", "Name", bankId);
ViewBag.AreaId = new SelectList(db.Areas, "Id", "Name", db.Areas.Where(p => p.Id == Edproblem.ATM.AreaId));
ViewBag.GovId = new SelectList(db.Governates, "Id", "Name", Edproblem.ATM.Area.GovernateId);
Problem beforeEdit = db.Problems.AsNoTracking().First(p => p.Id == problem.Id);
if (ModelState.IsValid)
{
DateTime now = DateTime.Now;
if (!Directory.Exists(Server.MapPath("~/UploadImages/" + now.ToString("yyyy_MM/"))))
{
Directory.CreateDirectory(Server.MapPath("~/UploadImages/" + now.ToString("yyyy_MM/")));
}
if (!Directory.Exists(Server.MapPath("~/UploadImages/" + now.ToString("yyyy_MM/") + Edproblem.ATMId.ToString())))
{
Directory.CreateDirectory(Server.MapPath("~/UploadImages/" + now.ToString("yyyy_MM/") + Edproblem.ATMId.ToString()));
}
if (!Directory.Exists(Server.MapPath("~/UploadImages/" + now.ToString("yyyy_MM/") + Edproblem.ATMId.ToString() + now.ToString("/dd/"))))
{
Directory.CreateDirectory(Server.MapPath("~/UploadImages/" + now.ToString("yyyy_MM/") + Edproblem.ATMId.ToString() + now.ToString("/dd/")));
}
var image = WebImage.GetImageFromRequest();
if (fileUpload != null)
{
string fileName = fileUpload.FileName.ToString();
fileName = Guid.NewGuid().ToString() + fileName.Substring(fileName.LastIndexOf("."));
fileName = now.ToString("yyyy_MM/") + problem.ATMId.ToString() + "/" + now.ToString("dd/") + fileName;
if (fileUpload != null && fileUpload.ContentLength > 0)
fileUpload.SaveAs(Server.MapPath("~/UploadImages/" + image));
image.Save(Server.MapPath("/UploadImages/" + fileName));
problem.ImagePath = fileName;
}
else
{
if (problem.ImagePath == null)
{
var getPath = (from e in db.Problems
where e.Id == problem.Id
select e.ImagePath).ToList();
problem.ImagePath = getPath[0].ToString();
}
}
problem.UserId = WebSecurity.GetUserId(User.Identity.Name);
db.Entry(problem).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(problem);
}
This is Error as it appear exactly:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

You're loading a Problem object into variable beforeEdit, and there is no further use of it.
If you try to update the beforeEdit with the new data from the parameter, and save that one instead of the object returned from the view.

Related

Multiselect list items overwrites instead of adding

I'm trying to add multi-selected items to list _AT.SOrderDetails = new List<SOrderDetail>(); but the list is overwritten by the last record selected. The list at right Datagrid only shows data of the last selected record of the left Datagrid instead of all records
foreach (int i in ((GridView)gridControl3.MainView).GetSelectedRows())
{
DataRowView oSOrder = (DataRowView)((GridView)gridControl3.MainView).GetRow(i);
int id = Convert.ToInt32(oSOrder.Row.ItemArray[0]);
if (oSOrder == null)
{
MessageBox.Show("select an item to edit", "Item not yet selected", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
int x = Convert.ToInt32(oSOrder["SOrderID"]);
_Order = db.SOrderTables.FirstOrDefault(o => o.QSOrdersID == x);
SOrderTable oOrder = null;
oOrder = _Order;
if (_Order != null)
{
_AT.SOrderDetails = new List<SOrderDetail>();
if (_Order.SOrderDetails != null)
{
foreach (SOrderDetail oPODItem in _Order.SOrderDetails.ToList())
{
_OrderDetail = new SOrderDetail();
Product oProduct = db.Products.FirstOrDefault(o => o.ProductID == oPODItem.ProductID);
_OrderDetail.ProductID = oPODItem.ProductID;
_OrderDetail.Description = oProduct.Description;
_OrderDetail.Quantity = oPODItem.Quantity;
_OrderDetail.Form = oPODItem.Form;
_OrderDetail.Price = oPODItem.Price;
_AT.SOrderDetails.Add(_OrderDetail);
}
}
}
}
The list at right Datagrid only shows data of the last selected record of the left datagrid
How do I add all values of the selected records, I need help I'm still new, thank you.
i created a new list _tapiwa.SOrderDetails = new List<SOrderDetail>(); So i was now saving information from list _Order.SOrderDetails.ToList(); to the new list i created.
`foreach (int i in ((GridView)gridControl3.MainView).GetSelectedRows())
{
DataRowView oSOrder = (DataRowView)((GridView)gridControl3.MainView).GetRow(i);
int id = Convert.ToInt32(oSOrder.Row.ItemArray[0]);
if (oSOrder == null)
{
MessageBox.Show("select an item to edit", "Item not yet selected", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
int x = Convert.ToInt32(oSOrder["SOrderID"]);
_Order = db.SOrderTables.FirstOrDefault(o => o.QSOrdersID == x);
label1.Text += (oSOrder.Row.ItemArray[0]).ToString()+" "+ (oSOrder.Row.ItemArray[1]).ToString()+" " + (oSOrder.Row.ItemArray[2]).ToString()+ "\n";
SOrderTable oOrder = null;
// db = new MedriveEntities();
oOrder = _Order;
if (_Order != null)
{
if (_tapiwa == null)
{
_tapiwa = new SOrderTable();
_tapiwa.SOrderDetails = new List<SOrderDetail>();
}
foreach (SOrderDetail oPODItem in oOrder.SOrderDetails.ToList())
{
_OrderDetail = new SOrderDetail();
// label2.Text += oPODItem.ProductID.ToString() + " " + oPODItem.Description.ToString() + " " + oPODItem.Quantity.ToString() + "\n";
Product oProduct = db.Products.FirstOrDefault(o => o.ProductID == oPODItem.ProductID);
_OrderDetail.ProductID = oPODItem.ProductID;
_OrderDetail.Description = oProduct.Description;
_OrderDetail.Quantity = oPODItem.Quantity;
_OrderDetail.Form = oPODItem.Form;
_OrderDetail.Price = oPODItem.Price;
_tapiwa.SOrderDetails.Add(_OrderDetail);
}
}
}
RefreshList1();`

Entity Framework Null reference exception when adding to bridge tables

I'm using Entity Framework with an MVC5 Application and currently I am trying to save some form data that touches multiple tables in my database. When I am adding data to the tables it seems to be working fine but once I hit the bridge tables I am getting a null ref exception that, to me, doesn't make sense.
I am new to programming so any help would be greatly appreciated.
public void RegisterNewUser(IDCRegisterViewModel model)
{
//
string fullAddress = model.AddressLine1 + "\n" + model.AddressLine2 + (string.IsNullOrEmpty(model.AddressLine2) ? "" : "\n" ) + model.City + ", " + model.State + " " + model.Zip + "\n" + model.Country;
using (var AuthContext = new InfoKeeperEntities1())
{
AuthContext.Locations.Add(new Location {
Line1 = model.AddressLine1,
Line2 = model.AddressLine2,
City = model.City,
State = model.State,
Zip = model.Zip,
Country = model.Country,
UserID = model.UserID,
FullAddr = fullAddress
});
AuthContext.ProfileDatas.Add(new ProfileData
{
UserID = model.UserID,
UACC = model.UACC,
isRecCenter = model.IsRecCenter,
isCustAdmin = model.IsCustAdmin
});
//Add to bridge tables for user/dept and group/dept
List<Department> deptList = new List<Department>();
foreach (var ID in model.GroupIDs)
{
deptList.Add(AuthContext.Departments.FirstOrDefault(x => x.ID == ID));
}
foreach (var department in deptList)
{
//NULL REF EXCEPTION HERE
AuthContext.AspNetUsers.FirstOrDefault(x => x.Id == model.UserID).Departments.Add(department);
foreach (var groupID in model.GroupIDs)
{
AuthContext.Groups.FirstOrDefault(x => x.ID == groupID).Departments.Add(department);
}
}
}
}
If you turn the LazyLoadingEnabled and ProxyCreationEnabled off you always face with an error because of using Department after FirstorDefault Query and EntityFramework doesn't include it for AppUsers, You have the same problem with adding the department to the Group. So you must include the Department first for both of them.
put using System.Data.Entity; in the very first of the codes.
change the code statement to this:
public void RegisterNewUser(IDCRegisterViewModel model)
{
string fullAddress = model.AddressLine1 + "\n" + model.AddressLine2 + (string.IsNullOrEmpty(model.AddressLine2) ? "" : "\n" ) + model.City + ", " + model.State + " " + model.Zip + "\n" + model.Country;
using (var AuthContext = new InfoKeeperEntities1())
{
AuthContext.Locations.Add(new Location {
Line1 = model.AddressLine1,
Line2 = model.AddressLine2,
City = model.City,
State = model.State,
Zip = model.Zip,
Country = model.Country,
UserID = model.UserID,
FullAddr = fullAddress
});
AuthContext.ProfileDatas.Add(new ProfileData
{
UserID = model.UserID,
UACC = model.UACC,
isRecCenter = model.IsRecCenter,
isCustAdmin = model.IsCustAdmin
});
//Add to bridge tables for user/dept and group/dept
List<Department> deptList = new List<Department>();
foreach (var ID in model.GroupIDs)
{
deptList.Add(AuthContext.Departments.FirstOrDefault(x => x.ID == ID));
}
var user = AuthContext.AspNetUsers.Include("Departments").FirstOrDefault(x => x.Id == model.UserID);
foreach (var department in deptList)
{
user.Departments.Add(department);
foreach (var groupID in model.GroupIDs)
{
var group = AuthContext.Groups.Include("Departments").FirstOrDefault(x => x.ID == groupID);
group.Departments.Add(department);
}
}
}
}
Tip: Don't forget to make a new instance of List<Depatment> in the constructor of AspNetUsers and Groups:
public class ApplicationUser
{
Public ApplicationUser()
{
this.Departments = new List<Department>();
}
}
public class Group
{
Public Group()
{
this.Departments = new List<Department>();
}
}

Incorrect upload multiple images in Edit method

I have method Edit that uploads one image for Main Page and multiple images for gallery to the existing record in database. I have one to many relationship table (FurnitureImages where I store info about image) , also I use View Model
So here my code
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(FurnitureVM model)
{
if (model.MainFile != null && model.MainFile.ContentLength > 0)
{
string displayName = model.MainFile.FileName;
string extension = Path.GetExtension(displayName);
string fileName = string.Format("{0}{1}", Guid.NewGuid(), extension);
string path = "~/Upload/" + fileName;
model.MainFile.SaveAs(Server.MapPath( path));
model.MainImage = new ImageVM() { Path = path, DisplayName = displayName };
}
foreach (HttpPostedFileBase file in model.SecondaryFiles)
{
FurnitureImages images = new FurnitureImages();
if (file != null && file.ContentLength > 0)
{
string displayName = file.FileName;
string extension = Path.GetExtension(displayName);
string fileName = string.Format("{0}{1}", Guid.NewGuid(), extension);
var path = "~/Upload/" + fileName;
file.SaveAs(Server.MapPath(path));
model.SecondaryImages = new List<ImageVM> { new ImageVM { DisplayName = displayName, Path = path } };
}
}
if (!ModelState.IsValid)
{
model.CategoryList = new SelectList(db.Categories, "CategoryId", "Name",model.CategoryId); // repopulate the SelectList
return View(model);
}
Furniture furniture = db.Furnitures.Where(x => x.FurnitureId == model.ID).FirstOrDefault();
FurnitureImages main = furniture.Images.Where(x => x.IsMainImage).FirstOrDefault();
furniture.Name = model.Name;
furniture.Description = model.Description;
furniture.Manufacturer = model.Manufacturer;
furniture.Price = model.Price;
furniture.CategoryId = model.CategoryId;
furniture.Size = model.Size;
main.DisplayName = model.MainImage.DisplayName;
main.Path = model.MainImage.Path;
main.IsMainImage = model.MainImage.IsMainImage;
if (model.MainImage != null && !model.MainImage.Id.HasValue)
{
FurnitureImages image = new FurnitureImages
{
Path = model.MainImage.Path,
DisplayName = model.MainImage.DisplayName,
IsMainImage = true
};
furniture.Images.Add(image);
db.Entry(furniture).State = EntityState.Modified;
}
// Update secondary images
IEnumerable<ImageVM> newImages = model.SecondaryImages.Where(x => x.Id == null);
foreach (ImageVM image in newImages)
{
FurnitureImages images = new FurnitureImages
{
DisplayName = image.DisplayName,
Path = image.Path ,
IsMainImage = false
};
furniture.Images.Add(images);
}
ViewBag.CategoryId = new SelectList(db.Categories, "CategoryId", "Name", furniture.CategoryId);
db.SaveChanges();
return RedirectToAction("Index");
}
Main image uploads good , but when I try to upload multiple images from another input file
#Html.TextBoxFor(m => m.SecondaryFiles, new { type = "file", multiple = "multiple" , name = "SecondaryFiles" })
#Html.ValidationMessageFor(m => m.SecondaryFiles)
#for (int i = 0; i < Model.SecondaryImages.Count; i++)
{
#Html.HiddenFor(m => m.SecondaryImages[i].Id)
#Html.HiddenFor(m => m.SecondaryImages[i].Path)
#Html.HiddenFor(m => m.SecondaryImages[i].DisplayName)
<img src="#Url.Content(Model.SecondaryImages[i].Path)" />
}
It uploads only one image , And as much as I keep trying to upload many images, it always upload only one, so where are errors in my method?
Your issue is that inside the first foreach loop, you correctly save each file to the server, but in each iteration, your creating an new List<ImageVM> and overwriting the value of SecondaryImages so when the loop has completed, it contains only one item (based on the last image).
Change the loop to
foreach (HttpPostedFileBase file in model.SecondaryFiles)
{
// FurnitureImages images = new FurnitureImages(); -- DELETE
if (file != null && file.ContentLength > 0)
{
string displayName = file.FileName;
string extension = Path.GetExtension(displayName);
string fileName = string.Format("{0}{1}", Guid.NewGuid(), extension);
var path = "~/Upload/" + fileName;
file.SaveAs(Server.MapPath(path));
// Add a new ImageVM to the collection
model.SecondaryImages.Add(new ImageVM { DisplayName = displayName, Path = path });
}
}
Note that the above assumes you view model has a parameter-less constructor that initializes SecondaryImages. If not, then add model.SecondaryImages = new List<ImageVM> before the loop.
A few other minor issues to address.
The code for generating the SelectList should be just
model.CategoryList = new SelectList(db.Categories, "CategoryId", "Name"); - the last parameter of the SelectList constructor is
ignored when binding to a model property so its pointless.
Delete the ViewBag.CategoryId = new SelectList(...) line of code.
Your model already contains a property for the SelectList (as per
note 1) but in any case, your redirecting, so adding anything to
ViewBag is pointless.
Move your db.Entry(furniture).State = EntityState.Modified; line
of code to immediately before db.SaveChanges();

Dynamic Where Linq C#

I'm using System.Linq.Dynamic to make dinanmico where in my research. In the code below I try to filter by Funcao, but returns the error:
No property or field 'Funcao' exists in type 'ASO'
How do I filter by an alias of my Linq?
CODE
public static ResultadoListagemPadrao Grid(int iniciarNoRegistro, int qtdeRegistro, string orderna, string ordenaTipo, string filtro, int filtroID, UsuarioLogado usuarioLogado)
{
var where = "";
var id = 0;
if (filtroID > 0)
where += " FuncionarioID == " + filtroID.ToString();
else
{
if (int.TryParse(filtro, out id))
where += " ASOID == " + id.ToString();
if (filtro != null)
where += " Funcao.Contains(#0) ";
}
using (var db = new ERPContext())
{
var resultado = new ResultadoListagemPadrao();
resultado.TotalRegistros = db.ASO.Total(usuarioLogado.EmpresaIDLogada);
resultado.TotalRegistrosVisualizados = db.ASO.ToListERP(usuarioLogado.EmpresaIDLogada).AsQueryable().Where(where, filtro).Count();
resultado.Dados =
(from a in db.ASO.ToListERP(usuarioLogado.EmpresaIDLogada).AsQueryable()
select new
{
a.ASOID,
a.FuncionarioID,
Cliente = a.Funcionario.Cliente.Pessoa.Nome,
Setor = a.FuncionarioFuncao.Funcao.Setor.Descricao,
Funcao = a.FuncionarioFuncao.Funcao.Descricao,
Funcionario = a.Funcionario.Pessoa.Nome,
a.DtASO,
a.Status
})
.Where(where, filtro)
.OrderBy(orderna + " " + ordenaTipo)
.Skip(iniciarNoRegistro)
.Take(qtdeRegistro)
.ToArray();
return resultado;
}
}
Issue is this line db.ASO.ToListERP(usuarioLogado.EmpresaIDLogada).AsQueryable().Where(where, filtro)
Your class ASO doesn't have a property Funcao.
Try remove the Where on that line. Try this...
var resultado = new ResultadoListagemPadrao();
resultado.TotalRegistros = db.ASO.Total(usuarioLogado.EmpresaIDLogada);
var query = (from a in db.ASO.ToListERP(usuarioLogado.EmpresaIDLogada).AsQueryable()
select new
{
a.ASOID,
a.FuncionarioID,
Cliente = a.Funcionario.Cliente.Pessoa.Nome,
Setor = a.FuncionarioFuncao.Funcao.Setor.Descricao,
Funcao = a.FuncionarioFuncao.Funcao.Descricao,
Funcionario = a.Funcionario.Pessoa.Nome,
a.DtASO,
a.Status
})
.Where(where, filtro);
resultado.TotalRegistrosVisualizados = query.Count();
resultado.Dados = query
.OrderBy(orderna + " " + ordenaTipo)
.Skip(iniciarNoRegistro)
.Take(qtdeRegistro)
.ToArray();
return resultado;
Please in future translate your code.

Collection property not properly added to parent on save

Look at the following code example.
What it does:
Iterates a bunch of customers. If it already knows the customer, it retrieves the existing database object for that customer (this is the problem-ridden part). Otherwise, it creates a new object (this works fine).
All loans where the social security number matches (CPR) will be added to the new or existing customer.
The problem: it works for new customer objects, but when I retrieve an existing customer object, the loans lose their relation to the customer when saved (CustomerID = null). They are still saved to the database.
Any ideas?
protected void BuildCustomerData()
{
Console.WriteLine(" Starting the customer build.");
var counter = 0;
var recycleCount = 100;
var reportingCount = 100;
var sTime = DateTime.Now;
var q = from c in db.IntermediaryRkos
select c.CPR;
var distincts = q.Distinct().ToArray();
var numbersToProcess = distincts.Count();
Console.WriteLine(" Identified " + numbersToProcess + " customers. " + (DateTime.Now - sTime).TotalSeconds);
foreach (var item in distincts)
{
var loans = from c in db.IntermediaryRkos
where c.CPR == item
select c;
var existing = db.Customers.Where(x => x.CPR == item).FirstOrDefault();
if (existing != null)
{
this.GenerateLoanListFor(existing, loans);
db.Entry(existing).State = System.Data.EntityState.Modified;
}
else
{
var customer = new Customer
{
CPR = item,
};
this.GenerateLoanListFor(customer, loans);
db.Customers.Add(customer);
db.Entry(customer).State = System.Data.EntityState.Added;
}
counter++;
if (counter % recycleCount == 0)
{
this.SaveAndRecycleContext();
}
if (counter % reportingCount == 0)
{
Console.WriteLine(" Processed " + counter + " customers of " + numbersToProcess + ".");
}
}
db.SaveChanges();
}
protected void GenerateLoanListFor(Customer customer, IQueryable<IntermediaryRko> loans)
{
customer.Loans = new List<Loan>();
foreach (var item in loans.Where(x => x.DebtPrefix == "SomeCategory").ToList())
{
var transformed = StudentLoanMap.CreateFrom(item);
customer.Loans.Add(transformed);
db.Entry(transformed).State = System.Data.EntityState.Added;
}
}
EDIT 1:
As pointed out, I am manually setting the state. This is due to the RecycleContext call, which is implemented for maximum db transaction performance:
protected void SaveAndRecycleContext()
{
db.SaveChanges();
db.Dispose();
db = new SolutionDatabase();
db.Configuration.AutoDetectChangesEnabled = false;
db.Configuration.ValidateOnSaveEnabled = false;
}
Existing loan or not, you wipe out the customer.Loans Property when you call
customer.Loans = new List<Loan>();

Categories

Resources