I'm a full time systems engineering student and i have a project that i've hit a bumped on the road, i'm handling right now all the users state with sessions and i would like to implement the JWT token for more "security", the application is a 2 part app (Api's = backend in one solution, Frontend in another solution)
Have to mention, I'm using C# in VS 2022 with asp.net .Net framework 4.7.2
The code architechture is MVC.
Here is my code
This is in the Users Model:
public string GetToken(Guid Id)
{
try
{
var key = ConfigurationManager.AppSettings["JwtKey"];
var issuer = ConfigurationManager.AppSettings["JwtIssuer"];
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
//Create a List of Claims, Keep claims name short
var permClaims = new List<Claim>();
permClaims.Add(new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()));
permClaims.Add(new Claim("userid", "Id"));
//Create Security Token object by giving required parameters
var token = new JwtSecurityToken(issuer, //Issure
issuer, //Audience
permClaims,
expires: DateTime.Now.AddDays(1),
signingCredentials: credentials);
var jwt_token = new JwtSecurityTokenHandler().WriteToken(token);
return jwt_token;
}
catch(Exception ex)
{
return string.Empty;
}
}
Once i get this token i include it in the Users object response and i'm able to see it in the front end response, i'm able to see the information being returned succesfully, I'm storing this data in a session variable.
this is my LogIn Controller:
[HttpPost]
public ActionResult ValidateUser(Users User)
{
if (User.noHashPass != null && User.Username != null)
{
var datos = model.ValidateUser(User);
var tok = datos.User;
if (datos != null)
{
Session["User"] = new Users();
Session["User"] = datos.User;
return RedirectToAction("Index", "Home");
}
else
{
return ViewBag.Msj = "¡ERROR! El usuario o la contraseña son incorrectos. Por favor intente de nuevo."; ;
}
}
else
{
ViewBag.Msj = "¡ERROR! El usuario o la contraseña son incorrectos. Por favor intente de nuevo.";
}
return View();
}
i was trying to do this to extract just the token piece in the users model:
public Respuesta ViewUserById(Guid Id)
{
using (var client = new HttpClient())
{
try
{
object sesion = new Users();
sesion = HttpContext.Current.Session["User"];
string api = "Users/ViewUserById?Id=" + Id;
string route = Url + api;
HttpResponseMessage response = client.GetAsync(route).Result;
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
var responseBody = response.Content.ReadAsAsync<Respuesta>().Result; //serializacion del obj JSON a un objeto
return responseBody;
}
else
{
throw new Exception("No se encontro un usuario existente bajo el Id:" + " " + Id);
}
}
catch (Exception ex)
{
throw ex;
}
}
}
But the sesion variable only gives me a ToString() function, i can see the sesion variable filling up and getting all the data but i cannot handle it for example, sesion.Token to get the Token inside the session variable.
Any suggestions are appreciated.
How can i handle the session variable in order to get the data within?
I'm writing an application that inserts data into 6 different databases. Each database has its model and controller and views.
The problem is all of them have the same methods with a slight difference here and there but in general, they are all the same. This is redundancy and a lot of similar code in each controller.
Is there a way to reduce that? Would you suggest a design pattern to study to implement it here because I feel what I'm doing here is a bad programming practice?
Am I correct or just paranoid? Thanks
controller 1:
namespace Manage_account.Controllers
{
public class HRLoanController : Controller
{
private Entities db = new Entities();
string EmployeeLogin = System.Security.Principal.WindowsIdentity.GetCurrent().Name.Split('\\')[1];
[HttpGet]
public ActionResult Create()
{
ViewBag.DepID = new SelectList(db.Departments , "DepID", "Department1");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(AccountVM vM)
{
if (ModelState.IsValid)
{
#region Insert in account and lob of HRLoan database
var chk_accountName = db.Accounts.Any(x => x.AccountName == vM.Accountex.Name);
try
{
if (!chk_accountName)
{
Account account = new Account();
account.AccountName = vM.Accountex.Name;
account.IsActive = true;
db.Accounts.Add(account);
db.SaveChanges();
TempData["success"] = "account saved successfully !";
}
else
{
TempData["warning"] = "Data already exists";
}
var Find_AccountId = db.Accounts.Where(x => x.AccountName == vM.Accountex.Name).FirstOrDefault();
var theID = Find_AccountId.AccountID;
var chk_lobName = db.LOBs.Where(x => x.AccountID == theID).Any(x => x.LOB1 == vM.LOBex.Name);
if (!chk_lobName)
{
LOB oB = new LOB();
oB.LOB1 = vM.LOBex.Name;
oB.LOBValue = vM.LOBex.Name;
oB.IsActive = true;
oB.AccountID = theID;
oB.DEPID = vM.Accountex.Dep_ID;
db.LOBs.Add(oB);
db.SaveChanges();
TempData["success"] = "lob saved successfully !";
}
else
{
TempData["warning"] = "Data already exists";
}
}
catch
{
TempData["error"] = "Something went wrong :( .Please, try again later.";
}
#endregion
}
return RedirectToAction("Create");
}
public ActionResult CreateLob()
{
ViewBag.DepID = new SelectList(db.Departments, "DepID", "Department1");
ViewBag.AccountID = new SelectList(db.Accounts.OrderBy(x=>x.AccountName), "AccountID" , "AccountName");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateLob(LOBex lOBex)
{
#region insert in Lob table in HRLoan database
if (ModelState.IsValid)
{
try
{
var chk_LobName = db.LOBs.Where(x => x.AccountID == lOBex.Account_ID).Any(x => x.LOB1 == lOBex.Name);
if (!chk_LobName)
{
LOB oB = new LOB();
oB.LOB1 = lOBex.Name;
oB.LOBValue = lOBex.Name;
oB.IsActive = true;
oB.DEPID = lOBex.DEPID;
oB.AccountID = lOBex.Account_ID;
db.LOBs.Add(oB);
db.SaveChanges();
TempData["success"] = "Data saved to LOB Table !";
}
else
{
TempData["warning"] = "Data already exists !";
}
}
catch
{
TempData["danger"] = "Something went wrong :(. Please, try again later.";
}
}
return RedirectToAction("CreateLob");
#endregion
}
[HttpGet]
public ActionResult CreateUser()
{
ViewBag.RoleID = new SelectList(db.Roles.OrderBy(x => x.Role1), "RoleID", "Role1");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateUser(AddUser addUser)
{
#region Insert new user in Users table in HRLoan database
if (ModelState.IsValid)
{
var chk_user_existence = db.Users.Any(x => x.UserID == addUser.UserID); //check if user exists in db or not
if (!chk_user_existence)
{
User user = new User();
user.UserID = addUser.UserID;
user.UserName = addUser.UserName;
user.UserEmail = addUser.UserEmail;
user.IsActive = true;
user.InsertedOn = DateTime.Now;
user.UpdatedBy = EmployeeLogin;
user.GradeID = addUser.GradeID;
user.RoleID = addUser.RoleID;
db.Users.Add(user);
db.SaveChanges();
}
else
{
TempData["warning"] = "This user already exists in Users table !";
}
}
else
{
TempData["error"] = "Something went wrong :/ . Please, try again later!";
}
return RedirectToAction("CreateUser");
#endregion
}
[HttpGet]
public ActionResult CreateBoss_Department()
{
var get_Admin = db.Users.Where(x => x.RoleID == 1).Where(x=>x.IsActive==true).ToList();
ViewBag.UserID = new SelectList(get_Admin.OrderBy(x=>x.UserName) , "UserID", "UserName");
ViewBag.Indexs = new SelectList(db.LOBs , "Indexs", "LOB1");
ViewBag.AccountID = new SelectList(db.Accounts.OrderBy(x=>x.AccountName) , "AccountID", "AccountName");
return View();
}
#region populate user's ID with their specified names
//populate user's names
public JsonResult GetUserName_toUserLogin(string usr)
{
List<User> getUser = new List<User>();
getUser = (from r in db.Users where (r.UserID == usr) select r).ToList();
List<SelectListItem> User_ID = new List<SelectListItem>();
foreach (User name in getUser)
{
User_ID.Add(new SelectListItem { Text = name.UserID, Value = name.UserName.ToString() });
}
return Json(new SelectList(User_ID, "Value", "Text"));
}
#endregion
#region Populates Lobs according to the selected account in the Create boss-department view
//populate Lobs
public JsonResult GetLOB_toAccount(int acc)
{
List<LOB> getLob = new List<LOB>();
getLob = (from r in db.LOBs where (r.AccountID == acc) select r).ToList();
List<SelectListItem> Lobs = new List<SelectListItem>();
foreach (LOB lob in getLob)
{
Lobs.Add(new SelectListItem {Text = lob.LOB1, Value = lob.Indexs.ToString() });
}
return Json(new SelectList(Lobs , "Value" , "Text"));
}
#endregion
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateBoss_Department(Boss_Dep boss_Dep)
{
#region Insert new record for admins only in Boss_Deapartment table in HRLoan database
if (ModelState.IsValid)
{
var Chk_UsrAccess = db.Boss_Department.Where(x => x.BossLogin == boss_Dep.BossLogin).Any(x => x.LOBIndexs == boss_Dep.LOBIndexs);
if (!Chk_UsrAccess)
{
Boss_Department boss_ = new Boss_Department();
boss_.BossLogin = boss_Dep.BossLogin;
boss_.LOBIndexs = boss_Dep.LOBIndexs;
boss_.IsActive = true;
boss_.ToMail = boss_Dep.To_mail;
boss_.InsertedOn = DateTime.Now;
boss_.UpdatedBy = EmployeeLogin;
db.Boss_Department.Add(boss_);
db.SaveChanges();
TempData["success"] = "Data saved successfully !";
}
else
{
TempData["warning"] = "Data already exists in Boss_Department table !";
}
}
else
{
TempData["error"] = "something went wrong :( !";
}
return RedirectToAction("CreateBoss_Department");
#endregion
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
controller 2:
namespace Manage_account.Controllers
{
public class HrperonalController : Controller
{
private personal personal = new personal();
string EmployeeLogin = System.Security.Principal.WindowsIdentity.GetCurrent().Name.Split('\\')[1];
//GET: create
[HttpGet]
public ActionResult Create()
{
ViewBag.DepID = new SelectList(personal.Departments, "DepID", "Department");
return View();
}
//POST: create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(AccountVM vM)
{
if (ModelState.IsValid)
{
#region insert account in account table in HRPersonnal db
var chk_accountName = personal.Accounts.Any(x => x.AccountName == vM.Accountex.Name);
if (!chk_accountName)
{
Accounts accounts = new Accounts();
accounts.AccountName = vM.Accountex.Name;
accounts.IsActive = true;
personal.Accounts.Add(accounts);
personal.SaveChanges();
TempData["success"] = "Account has been saved successfully :) !";
}
else
{
TempData["warning"] = "account already exists";
}
#endregion
#region insert Lob under that account in LOB table in HRPersonnal db
var Added_account = personal.Accounts.Where(x=>x.AccountName == vM.Accountex.Name).FirstOrDefault().AccountID;
var chk_lobName = personal.LOB.Where(x => x.DEPID == vM.LOBex.DEPID)
.Where(x => x.AccountID == Added_account).Any(x => x.LOB1 == vM.LOBex.Name);
if (!chk_lobName)
{
LOB lOB = new LOB();
lOB.LOB1 = vM.LOBex.Name;
lOB.LOBValue = vM.LOBex.Name;
lOB.AccountID = Added_account;
lOB.DEPID = vM.LOBex.DEPID;
lOB.IsActive = true;
personal.LOB.Add(lOB);
personal.SaveChanges();
TempData["success"] = "Lob has been saved successfully :) !";
}
else
{
TempData["warning"] = "Lob already exists on that account";
}
#endregion
}
else
{
TempData["error"] = "Something went wrong.Please, try again later :/.";
}
return RedirectToAction("Create");
}
//GET: createLob
[HttpGet]
public ActionResult CreateLob()
{
ViewBag.AccountID = new SelectList(personal.Accounts, "AccountID", "AccountName");
ViewBag.DepID = new SelectList(personal.Departments , "DepID", "Department");
return View();
}
//POST: createLob
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateLob(LOBex oBex)
{
#region insert Lob in LOB table in HRPersonnal db
if (ModelState.IsValid)
{
var chk_Lob = personal.LOB.Where(x => x.DEPID == oBex.DEPID).Where(x => x.AccountID == oBex.Account_ID).Any(x=>x.LOB1 == oBex.Name);
if (!chk_Lob)
{
LOB lOB = new LOB();
lOB.LOB1 = oBex.Name;
lOB.LOBValue = oBex.Name;
lOB.DEPID = oBex.DEPID;
lOB.AccountID = oBex.Account_ID;
lOB.IsActive = true;
personal.LOB.Add(lOB);
personal.SaveChanges();
TempData["success"] = "Lob has been saved successfully :) ! ";
}
else
{
TempData["warning"] = "Lob already exists !";
}
}
#endregion
else
{
TempData["error"] = "Something went wrong.Please, try again later :/ !";
}
return RedirectToAction("CreateLob");
}
//GET: createuser
[HttpGet]
public ActionResult CreateUser()
{
ViewBag.RoleID = new SelectList(personal.Roles , "RoleID", "Role");
ViewBag.DepID = new SelectList(personal.Departments, "DepID", "Department");
return View();
}
//POST: createuser
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateUser(PersonnalUser user)
{
if (ModelState.IsValid)
{
var chk_user = personal.Users.Any(x => x.UserID == user.usrID);
if (!chk_user)
{
Users usr = new Users();
usr.UserID = user.usrID;
usr.UserName = user.Name;
usr.RoleID = user.Roleid;
usr.IsActive = true;
usr.GradeID = user.Gradeid;
usr.InsertedBy = EmployeeLogin;
usr.InsertedOn = DateTime.Now;
usr.Email = user.Email;
usr.PositionName = user.PositionName;
usr.DepartmentName = user.DepartmentName;
personal.Users.Add(usr);
personal.SaveChanges();
TempData["success"] = "User has been saved successfully :) !";
}
else
{
TempData["warning"] = "User already exists !";
}
}
return RedirectToAction("CreateUser");
}
//GET: create boss-department
[HttpGet]
public ActionResult CreateBoss_Dep()
{
var get_this_Admin = personal.Users.Where(x => x.RoleID == 1).Where(x => x.IsActive == true).ToList();
ViewBag.UserID = new SelectList(get_this_Admin.OrderBy(x => x.UserName), "UserID", "UserName");
ViewBag.Indexs = new SelectList(personal.LOB, "Indexs", "LOB1");
ViewBag.AccountID = new SelectList(personal.Accounts, "AccountID", "AccountName");
return View();
}
#region populate user's ID with their specified names
//populate user's names
public JsonResult GetUserName_toUserLogin(string usr)
{
List<Users> getUser = new List<Users>();
getUser = (from r in personal.Users where (r.UserID == usr) select r).ToList();
List<SelectListItem> User_ID = new List<SelectListItem>();
foreach (Users name in getUser)
{
User_ID.Add(new SelectListItem { Text = name.UserID, Value = name.UserName.ToString() });
}
return Json(new SelectList(User_ID, "Value", "Text"));
}
#endregion
#region Populates Lobs according to the selected account in the Create boss-department view
//populate Lobs
public JsonResult GetLOB_toAccount(int acc)
{
List<LOB> getLob = new List<LOB>();
getLob = (from r in personal.LOB where (r.AccountID == acc) select r).ToList();
List<SelectListItem> Lobs = new List<SelectListItem>();
foreach (LOB lob in getLob)
{
Lobs.Add(new SelectListItem { Text = lob.LOB1, Value = lob.Indexs.ToString() });
}
return Json(new SelectList(Lobs, "Value", "Text"));
}
#endregion
//POST: create boss-department
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateBoss_Dep(Boss_Dep boss_Dep)
{
#region Insert new record for admins only in Boss_Deapartment table in HRLoan database
if (ModelState.IsValid)
{
var Chk_UsrAccess = personal.Boss_Department.Where(x => x.BossLogin == boss_Dep.BossLogin).Any(x => x.LOBIndexs == boss_Dep.LOBIndexs);
if (!Chk_UsrAccess)
{
Boss_Department boss_Department = new Boss_Department();
boss_Department.BossLogin = boss_Dep.BossLogin;
boss_Department.LOBIndexs = boss_Dep.LOBIndexs;
boss_Department.IsActive = true;
boss_Department.ToMail = boss_Dep.To_mail;
boss_Department.InsertedOn = DateTime.Now;
boss_Department.UpdatedBy = EmployeeLogin;
personal.Boss_Department.Add(boss_Department);
personal.SaveChanges();
TempData["success"] = "Data saved successfully !";
}
else
{
TempData["warning"] = "Data already exists in Boss_Department table !";
}
}
else
{
TempData["error"] = "something went wrong :( !";
}
return RedirectToAction("CreateBoss_Dep");
#endregion
}
}
}
Congratulations for spotting the repetitive nature of your code. That's a good start.
On the flip side, you have a long way to go, in that, there's a lot you'll need to learn.
Upon a study of your code structure, it looks like this:
(1) Controller Class
-- (2) HTTP GET METHOD / ACTION
-- (3) HTTP POST METHOD / ACTION
-- -- (4) If the model state is valid
-- -- -- (5) If the object does not already exist in the database
-- -- -- -- (6) Do the thing. In your case, create a record in the database and save it.
-- -- -- -- (7) While doing it, if there's an error, write it to TempData.
-- -- -- (8) Else if the object already exists in the database
-- -- -- -- (9) Write an error to the temp data
-- -- -- (10) End of check if the object exists in the database
-- -- (11) Else if the model state is not valid
-- -- -- (12) Write an error to TempData
-- -- (13) End of check if model state is valid or not
-- -- (14) If while doing the whole method thing, there's an error, write it to TempData
-- (15) End of method.
Fortunately, this isn't a new problem at all, or even a difficult one to crack. It's basically the meat and potatoes of all simple, CRUD applications.
The problem is shouting loud and clear, and you have an inkling that something's wrong. Here's the problem.
All is mixed up. In sophisticated language, you're mixing concerns.
So, you need to separate out your concerns.
This is a basic design principle rather than a specific design pattern.
Separation of Concerns
You have code that sits close to the UI, i.e. your controller actions, your business or model objects, i.e. classes such as User, Account, etc. your utility classes such as methods that convert stuff to JSON and back, all in one place.
Besides, you've made even your utility methods that do the JSON and back conversion from your business objects into public methods, making them callable as actions on your controller.
All these mistakes are in violation of good design principles.
You need to separate out these, so that your code reads more like two or three lines like so:
public void PostAction(ModelObject model)
{
if (!ModelState.IsValid)
{
// Some error handling strategy common to the whole
// application that sits well with the kind of interface
// this application has. Are you making a website or is this
// a web API?
}
// You're here because the model state is valid
// Get the repository object somehow:
// (a) Either through dependency injection in the controller's constructor, and
// when you get the dependency, get it in the lowest / basest possible interface
// so that it is polymorphic.
// (b) Or as a service location strategy, which means new it up here
repositoryObject.doTheThing();
}
public class MyCentralErrorHandler : HandleErrorAttribute
{
...
}
In separating them, I noticed I applied a few patterns:
Dependency Injection
Service Location
Repository
I also applied the SOLID principle of interface seggregation. That is, I got my dependency using a polymorphic compile-time type like so:
public class MyController : Controller
{
public MyController(IRepository repositoryObject) : base()
{
}
}
So, to answer the other aspect of your question about what design pattern to apply, I'd say you're still falling in the same trap that all rookies fall. It's not applying a design pattern you need to learn at this stage. But you need to code more.
Code a lot for practice until your own intuition develops to a stage where, just like you spotted that there was something messy about your code, your own intuition clearly and unequivocally tells you boundaries of what needs to go where, and you begin to work on your intuition and at the end of following its instruction, you realize, "Hey, what I did just now, it's called such and such a design pattern. Viola! I never did it consciously."
So, in a nutshell, study them all. Learn all the design patterns for now. Learn them thoroughly and give it a few years to roll in your head. And then throw them all out of your head when you're writing code. You're not supposed to be super-imposing design patterns on your code. They're just supposed to come out of you like poop does. And believe me, it'll happen. All you need is just more years of practice.
Meanwhile, write plenty of code. Plenty of code.
Another matter-of-fact answer to your question, as I already stated above is, you need to apply these things:
The design principle of separation of concerns;
The repository pattern, which is itself a manifestation of the principle of separation of concerns;
Service Location
Dependency Injection
The SOLID principle of programming to an interface rather than to a concrete implementation
A proper error / exception handling strategy. This is a lot of thinking that's due here. You need to ask yourself a lot of questions about what kind of an interface your application has and what do you intend to do at each stage. It's not something I can write here and be done with. You need a mentor or plenty of years of practice.
One more thing I must bring to your attention is that design patterns overlap. So, there are a few more obvious design patterns that actually also go by more than one name that are already applied in the solution I highlighted above. They're basically different names for the same thing. So, these are nebulous ideas that are demarkated on the basis of their function and even the context.
For e.g just the principle of programming to an interface can also be referred to as interface seggregation though the term interface seggregation has another, wider connotation in the context of system design. The same thing can also be noticed to be polymorphism at play. And I am sure there's another pattern name that can be ascribed to the same common-sensical, obvious solution.
I am inserting into my database. My code is working fine, but am stuck trying to throw message if the insertion is successful or not. Please check my code below. For example, if the insertion is successful, a message like "Insertion successful" should be shown.
public class HomeController : Controller
{
public ActionResult Index()
{
SalesLayanEntities3 db = new SalesLayanEntities3();
List<Product_Category> list = db.Product_Category.ToList();
ViewBag.ProductName = new SelectList(list,"cat_id","cat_name");
return View();
}
public ActionResult SaveRecord(ProductForm model)
{
try
{
SalesLayanEntities3 db = new SalesLayanEntities3();
Product prod = new Product();
prod.prod_name = model.Prod_name;
prod.prod_model = model.Prod_model;
prod.prod_quantity = model.Prod_quantity;
prod.prod_description = model.Prod_description;
prod.prod_unit_cost_price = model.Prod_unit_cost_price;
prod.cat_id = model.Cat_id;
db.Products.Add(prod);
db.SaveChanges();
int latestProdId = prod.prod_id;
}
catch (Exception ex)
{
throw ex;
}
return RedirectToAction("Index");
}
}
You are not getting any message because you are redirecting to Index page.
you may want to redirect to success page RedirectToAction("Success", "Shared").
you can use Error page for thrown exceptions which I believe you are already doing that by default.
You might want to use TempData. It can be accessed in your view.
Controller:
TempData["status"] = "Success";
View:
{
#TempData["status"];
}
You could do it like this:
public ActionResult SaveRecord(ProductForm model)
{
try
{
SalesLayanEntities3 db = new SalesLayanEntities3();
Product prod = new Product();
prod.prod_name = model.Prod_name;
prod.prod_model = model.Prod_model;
prod.prod_quantity = model.Prod_quantity;
prod.prod_description = model.Prod_description;
prod.prod_unit_cost_price = model.Prod_unit_cost_price;
prod.cat_id = model.Cat_id;
db.Products.Add(prod);
db.SaveChanges();
int latestProdId = prod.prod_id;
TempData["status"] = "Success";
}
catch (Exception ex)
{
TempData["status"] = "Error";
throw ex;
}
return RedirectToAction("Index");
}
Try adding a parameter to the redirect (you will need to change the scope of latestProdId):
return RedirectToAction("Index", new {addedID = latestProdId );
and then add an optional parameter to Index
public ActionResult Index(int latestProdId = 0)
Test latestProdId for a non-zero value and then pass that back to the view to display.
I am sending a Post using ajax for my controller to update the records of a product, but I get the following error:
"The instance of entity type 'Produtos' cannot be tracked because
another instance with the same key value for {'Cod'} is already being
tracked. When attaching existing entities, ensure that only one entity
instance with a given key value is attached. Consider using
'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the
conflicting key values."
my knowledge is still very limited and I do not know what I am doing wrong.
Here is where I load the data on the screen for editing:
[HttpGet]
public PartialViewResult EditaProduto(int cod)
{
var produtos = new Produtos();
if (cod != 0)
produtos = _petalertaContext.Produtos.Where(c => c.Cod == cod).SingleOrDefault();
return PartialView("_ProdutoCadAlt", produtos);
}
Here is where I create or update the product in the database:
[HttpPost]
public IActionResult GravaProduto([FromBody] Produtos produto)
{
if (ModelState.IsValid)
{
try
{
int codShop = Convert.ToInt32(new UserLogado(this.User).PegaDados("cod"));
produto.Codshop = codShop;
Produtos prodAtual = _petalertaContext.Produtos.Find(produto.Cod);
string strResp = "Produto alterado com sucesso!";
if (prodAtual == null)
{
strResp = "Produto adicionado com sucesso!";
prodAtual = _petalertaContext.Produtos.Where(c => c.Nome.ToUpper() == produto.Nome.ToUpper() && c.Codshop == codShop).SingleOrDefault();
if (prodAtual != null)
return Content("Erro: Você já possui o produto " + produto.Nome + " cadastrado!");
_petalertaContext.Add(produto);
}
else
{
_petalertaContext.Update(produto); //<== ERROR
}
_petalertaContext.SaveChanges();
return Content(strResp);
}
catch (DbUpdateConcurrencyException ex)
{
return Content("Erro ao gravar produto: " + ex.Message + " : " + ex.InnerException?.Message);
}
}
return Content("Erro: Não foi possível gravar o produtoes!");
}
Thanks for any help, thank you!
I believe it has to do with this line:
Produtos prodAtual = _petalertaContext.Produtos.Find(produto.Cod);
You already have produto so you don't need to get it again.
I would just do this:
produto.Codshop = codShop;
DbEntityEntry<Produtos> entry = _petalertaContext.Entry(produto);
entry.State = EntityState.Modified;
_petalertaContext.SaveChanges();
I am new to MVC. I am facing below problem.
I wrote all logic in model.In Web.config I mention path of file (No Connection string).
I am adding [Authorize] attribute. After login, it is navigating to Home page. When I navigate gift create page again redirect to login page (Recursive).
FYI: Temporarily I am using session variable to solve problem.
This is my code
[HttpPost]
[ActionName("Create")]
[Authorize]
public ActionResult CreateGift(GiftModel gif)
{
if (Session["UserType"] != null)
{
if (Session["UserType"].ToString() == "1")
return RedirectToAction("Index", "home");
}
else
{
return RedirectToAction("Login", "User");
}
string path = System.Configuration.ConfigurationManager.AppSettings["Path"];
if (ModelState.IsValid)
{
Gift InsertCoupon = new Gift(path);
InsertCoupon.InsertGift(gif);
return RedirectToAction("GiftList");
}
return View();
}
In Web.config
<add key="Path" value="D:\"/>
Login Page
public ActionResult Login(LoginModel user)
{
string path = System.Configuration.ConfigurationManager.AppSettings["Path"];
if(ModelState.IsValid)
{
Users LoginUser = new Users(path);
UserModel uM = new UserModel();
uM.Password = user.Password;
uM.User_Email_ID = user.User_Email_ID;
uM.Name = user.Name;
string res = LoginUser.LoginUser(uM);
uM = LoginUser.GetUserFrom_Email(user.User_Email_ID);
if (res != "")
ViewBag.Msg = res;
else
{
Session["username"] = uM.Name;
Session["E_Mail"] = uM.User_Email_ID;
Session["UserType"] = uM.User_Type;
if (uM.User_Type == 0)
return RedirectToAction("AdminHome", "Admin");
else
return RedirectToAction("Index", "Home");
}
}
return View();
}