[CustomeAuthorizeForAjaxAndNonAjax(Roles = "ResetCMSUserPassword")] //This method is called using ajax requests so authorize it with the custome attribute we created for the logged in users with the appropriate role. public async Task <IActionResult> ResetPasswordByAdmin(ResetPasswordByAdmin model) { if (ModelState.IsValid) { var user = await _userManager.FindByEmailAsync(model.Email); //if nothing was found: if (user == null) { return(NotFound()); } var token = await _userManager.GeneratePasswordResetTokenAsync(user); var result = await _userManager.ResetPasswordAsync(user, token, model.Password); if (result.Succeeded) { //After the successfull Create or Edit, we do not return a view because we already did the Create or Edit using Ajax request, //which means we did not reload the page, so return the _ViewAll.cshtml which has the html table, return it as serialized html in json file, to be rendered in Index.cshtml as a partial view: return(Json(new { isValid = true, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "_ViewAll", _userManager.Users) })); //return NotFound(); } // If there are any errors, add them to the ModelState object // which will be displayed by the validation summary tag helper foreach (var error in result.Errors) { ModelState.AddModelError(string.Empty, error.Description); } } //if the model submitted is not valid according to the Attriburtes in [] in the model file in Models folder: return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "ResetPasswordByAdmin", model) })); }
[CustomeAuthorizeForAjaxAndNonAjax(Roles = "EditUserRoles")] //This method is called using ajax requests so authorize it with the custome attribute we created for the logged in users with the appropriate role. public async Task <IActionResult> EditUserRoles(List <UserRoleViewModel> model) { /* * Note: * -We are executing 2 Select (Get or Read) calls to the DB in: * var users _userManager.FindByEmail(_Email); * var roles = await _userManager.GetRolesAsync(user); * * -Unfortunately, the PostgresDB does not support multiple select calls for one instance of DbContext, * and we wil get an exception thrown saying: "A command is already in progress" when performing the second one ! * * -The solution was found bu using .ToList() in the first command. * ToList() forced the aoolication to stop and wat untill the execution is finished, then moved to the execute the second one. * * -The other commands: * await _userManager.RemoveFromRolesAsync(user, roles); * await _userManager.AddToRolesAsync(user, model.Where(x => x.IsSelected).Select(y => y.RoleName)); * are not select commands, so no problem with them. */ //We need to bring the user info who we are going to modify his roles, //we will bring him by his email, //the user's email is existed in each object "UserRoleViewModel" in the list "List<UserRoleViewModel>", //so we can take the email from the object of index=0 for exampl, //but instead of executing var users _userManager.FindByEmail(_Email), we did the below according to the note above: var user = _userManager.Users.Where(p => p.Id != null).ToList().Where(x => x.Email == model[0].userEmail).FirstOrDefault(); if (user == null) { return(NotFound()); } //bring all the Roles which are assigned to this user: var roles = await _userManager.GetRolesAsync(user); //Remove all the assigned Roles to the user we have, so we can add what we want below: var result = await _userManager.RemoveFromRolesAsync(user, roles); if (!result.Succeeded) { ModelState.AddModelError("", "Cannot remove user existing roles"); //in case of errors: return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "EditUserRoles", model) })); } //Now re-assign new Roles to the user according to the IsSelected checkbox of the UserRoleViewModel objects: result = await _userManager.AddToRolesAsync(user, model.Where(x => x.IsSelected).Select(y => y.RoleName)); if (!result.Succeeded) { ModelState.AddModelError("", "Cannot add selected roles to user"); //in case of errors: return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "EditUserRoles", model) })); } //After the successfull Edit, we do not return a view because we already did the Create or Edit using Ajax request, //which means we did not reload the page, so return the _ViewAll.cshtml which has the html table, return it as serialized html in json file, to be rendered in Index.cshtml as a partial view: return(Json(new { isValid = true, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "_ViewAll", _userManager.Users) })); }
[CustomeAuthorizeForAjaxAndNonAjax(Roles = "DeleteDeliveryMethod")] //This method is called using ajax requests so authorize it with the custome attribute we created for the logged in users with the appropriate role. public async Task <IActionResult> DeleteConfirmed(int id) { var deliveryMethod = await _context.DeliveryMethods.FindAsync(id); _context.DeliveryMethods.Remove(deliveryMethod); await _context.SaveChangesAsync(); //After the successfull delete, we do not return a view because we already did the Create or Edit using Ajax request, //which means we did not reload the page, so return the _ViewAll.cshtml which has the html table, return it as serialized html in json file, to be rendered in Index.cshtml as a partial view: return(Json(new { html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "_ViewAll", _context.DeliveryMethods.ToList()) })); }
[CustomeAuthorizeForAjaxAndNonAjax(Roles = "DeleteProduct")] //This method is called using ajax requests so authorize it with the custome attribute we created for the logged in users with the appropriate role. public async Task <IActionResult> DeleteConfirmed(int id) { var product = await _context.Products.FindAsync(id); _context.Products.Remove(product); await _context.SaveChangesAsync(); //After the successfull delete, we do not return a view because we already did the Create or Edit using Ajax request, //which means we did not reload the page, so return the _ViewAll.cshtml which has the html table, return it as serialized html in json file, to be rendered in Index.cshtml as a partial view: return(Json(new { html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "_ViewAll", _context.Products.Include(p => p.ProductBrand).Include(p => p.ProductType).ToList()) })); //in Index.cshtml we are displaying the Brand Name and Type Name, not Id, so return the Brand and Type all info using .Include(p => p.ProductBrand).Include(p => p.ProductType) }
[CustomeAuthorizeForAjaxAndNonAjax] //The below method is called using ajax request. To authorize it, use this custome attribute. Authorize it for logged in users without any role. public async Task <IActionResult> ChangeMyPassword(ChangeMyPasswordViewModel model) { if (ModelState.IsValid) { //bring the current logged in user's info using the GetUserAsync(User) whereas "User" is a predefined parameter in microsoft identity to represent the logged in user. var user = await _userManager.GetUserAsync(User); if (user == null) { //return RedirectToAction("Login", "Account"); //we are calling this method using ajax request, so it is hard to redirect without specific modifications, so: return(NotFound()); } // ChangePasswordAsync changes the user password var result = await _userManager.ChangePasswordAsync(user, model.CurrentPassword, model.NewPassword); // The new password did not meet the complexity rules or // the current password is incorrect. Add these errors to // the ModelState and rerender ChangePassword view if (!result.Succeeded) { foreach (var error in result.Errors) { ModelState.AddModelError(string.Empty, error.Description); } return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "ChangeMyPassword", model) })); } // Upon successfully changing the password refresh sign-in cookie await _signInManager.RefreshSignInAsync(user); var AccountProfileViewModel = new AccountProfileViewModel { Id = user.Id, DisplayName = user.DisplayName, UserName = user.UserName, Email = user.Email }; return(Json(new { isValid = true, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "_ViewAll", AccountProfileViewModel) })); } //if the model submitted is not valid according to the Attriburtes in [] in the model file in Models folder: return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "ChangeMyPassword", model) })); }
[CustomeAuthorizeForAjaxAndNonAjax] //The below method is called using ajax request. To authorize it, use this custome attribute. Authorize it for logged in users without any role. public async Task <IActionResult> EditMyProfile(EditUserViewModel model) { if (ModelState.IsValid) { //bring the current logged in user's info using the GetUserAsync(User) whereas "User" is a predefined parameter in microsoft identity to represent the logged in user. var user = await _userManager.GetUserAsync(User); //or we can use the model.Email for that if (user == null) { //return RedirectToAction("Login", "Account"); //we are calling this method using ajax request, so it is hard to redirect without specific modifications, so: return(NotFound()); } user.DisplayName = model.DisplayName; var result = await _userManager.UpdateAsync(user); if (result.Succeeded) { //After the successfull Create or Edit, we do not return a view because we already did the Create or Edit using Ajax request, //which means we did not reload the page, so return the _ViewAll.cshtml which has the html table, return it as serialized html in json file, to be rendered in Index.cshtml as a partial view: var AccountProfileViewModel = new AccountProfileViewModel { Id = user.Id, DisplayName = user.DisplayName, UserName = user.UserName, Email = user.Email }; return(Json(new { isValid = true, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "_ViewAll", AccountProfileViewModel) })); //return NotFound(); } // If result is not successful, If there are any errors, add them to the ModelState object // which will be displayed by the validation summary tag helper foreach (var error in result.Errors) { ModelState.AddModelError(string.Empty, error.Description); } return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "EditMyProfile", model) })); } //if the model submitted is not valid according to the Attriburtes in [] in the model file in Models folder: return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "EditMyProfile", model) })); }
[CustomeAuthorizeForAjaxAndNonAjax(Roles = "RegisterNewCMSUser")] //This method is called using ajax requests so authorize it with the custome attribute we created for the logged in users with the appropriate role. public async Task <IActionResult> Register(RegisterViewModel model) { if (ModelState.IsValid) { //Create new user object as ApplicationUser instance, thensubmit it to AspNetUsers using UserManager. var user = new CmsUser { UserName = model.Email, Email = model.Email, DisplayName = model.DisplayName //AspNetUsers table has nearly 14 columns, we fill email and and password only. //others will be filled by microsoft if requierd. //Also, we added the column DisplayName, so we will fill it as well. }; // Store user data in AspNetUsers database table var result = await _userManager.CreateAsync(user, model.Password); //this will create a user, and assign true to "result" if creation is successful. //if creation is not successful, "result" will contain Errors array and description for each one. // If user is successfully created, sign-in the user using: if (result.Succeeded) { //After the successfull Create or Edit, we do not return a view because we already did the Create or Edit using Ajax request, //which means we did not reload the page, so return the _ViewAll.cshtml which has the html table, return it as serialized html in json file, to be rendered in Index.cshtml as a partial view: return(Json(new { isValid = true, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "_ViewAll", _userManager.Users) })); //return NotFound(); } //If result is not success, If there are any errors, add them to the ModelState object // which will be displayed by the validation summary tag helper foreach (var error in result.Errors) { ModelState.AddModelError(string.Empty, error.Description); } return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "Register", model) })); } //if the model submitted is not valid according to the Attriburtes in [] in the model file in Models folder: return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "Register", model) })); }
[CustomeAuthorizeForAjaxAndNonAjax(Roles = "DeleteCMSUser")] //This method is called using ajax requests so authorize it with the custome attribute we created for the logged in users with the appropriate role. public async Task <IActionResult> DeleteConfirmed(string id) { var user = await _userManager.FindByIdAsync(id); if (user == null) { return(NotFound()); } var result = await _userManager.DeleteAsync(user); if (result.Succeeded) { //After the successfull delete, we do not return a view because we already did the Create or Edit using Ajax request, //which means we did not reload the page, so return the _ViewAll.cshtml which has the html table, return it as serialized html in json file, to be rendered in Index.cshtml as a partial view: return(Json(new { html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "_ViewAll", _userManager.Users) })); } //else return(BadRequest()); }
[CustomeAuthorizeForAjaxAndNonAjax(Roles = "AddOrEditCustomer")] //This method is called using ajax requests so authorize it with the custome attribute we created for the logged in users with the appropriate role. public async Task <IActionResult> AddOrEdit(string id, [Bind("Id,DisplayName,UserName,NormalizedUserName,Email,NormalizedEmail,EmailConfirmed,PasswordHash,SecurityStamp,ConcurrencyStamp,PhoneNumber,PhoneNumberConfirmed,TwoFactorEnabled,LockoutEnd,LockoutEnabled,AccessFailedCount")] AspNetUser Model) { if (ModelState.IsValid) { //Create if (string.IsNullOrEmpty(id)) { //This creation in "AspNetUsers" table (reversly scaffolded from "skinet" application tables) is wrong. //The creation should be with UserManager Service from Microsoft identity library. //Anyway, we are not allowing the creation to be used here, but I kept this anyway. _context.Add(Model); await _context.SaveChangesAsync(); } //Update else { try { _context.Update(Model); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!CustomerExists(Model.Email)) { return(NotFound()); } else { throw; } } } //After the successfull Create or Edit, we do not return a view because we already did the Create or Edit using Ajax request, //which means we did not reload the page, so return the _ViewAll.cshtml which has the html table, return it as serialized html in json file, to be rendered in Index.cshtml as a partial view: return(Json(new { isValid = true, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "_ViewAll", _context.AspNetUsers.ToList()) })); //return NotFound(); } //if the model submitted is not valid according to the Attriburtes in [] in the model file in Models folder: return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "AddOrEdit", Model) })); }
[CustomeAuthorizeForAjaxAndNonAjax(Roles = "AddOrEditOrder")] //This method is called using ajax requests so authorize it with the custome attribute we created for the logged in users with the appropriate role. public async Task <IActionResult> AddOrEdit(int id, [Bind("Id,BuyerEmail,OrderDate,ShipToAddressFirstName,ShipToAddressLastName,ShipToAddressStreet,ShipToAddressCity,ShipToAddressState,ShipToAddressZipcode,DeliveryMethodId,Subtotal,Status,PaymentIntentId")] Order Model) { if (ModelState.IsValid) { //Create if (id == 0) { _context.Add(Model); await _context.SaveChangesAsync(); } //Update else { try { _context.Update(Model); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!OrderModelModelExists(Model.Id)) { return(NotFound()); } else { throw; } } } //After the successfull Create or Edit, we do not return a view because we already did the Create or Edit using Ajax request, //which means we did not reload the page, so return the _ViewAll.cshtml which has the html table, return it as serialized html in json file, to be rendered in Index.cshtml as a partial view: return(Json(new { isValid = true, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "_ViewAll", _context.Orders.Include(p => p.DeliveryMethod).ToList()) })); //in Index.cshtml we are displaying the DeliveryMethod ShortName, not Id, so return the DeliveryMethod all info using .Include(p => p.DeliveryMethod) //return NotFound(); } //if the model submitted is not valid according to the Attriburtes in [] in the model file in Models folder: return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "AddOrEdit", Model) })); }
[CustomeAuthorizeForAjaxAndNonAjax(Roles = "AddOrEditDeliveryMethod")] //This method is called using ajax requests so authorize it with the custome attribute we created for the logged in users with the appropriate role. public async Task <IActionResult> AddOrEdit(int id, [Bind("Id,ShortName,DeliveryTime,Description,Price")] DeliveryMethod Model) { if (ModelState.IsValid) { //Create if (id == 0) { _context.Add(Model); await _context.SaveChangesAsync(); } //Update else { try { _context.Update(Model); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!DeliveryMethodModelModelExists(Model.Id)) { return(NotFound()); } else { throw; } } } //After the successfull Create or Edit, we do not return a view because we already did the Create or Edit using Ajax request, //which means we did not reload the page, so return the _ViewAll.cshtml which has the html table, return it as serialized html in json file, to be rendered in Index.cshtml as a partial view: return(Json(new { isValid = true, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "_ViewAll", _context.DeliveryMethods.ToList()) })); //return NotFound(); } //if the model submitted is not valid according to the Attriburtes in [] in the model file in Models folder: return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "AddOrEdit", Model) })); }
[CustomeAuthorizeForAjaxAndNonAjax(Roles = "AddOrEditProduct")] //This method is called using ajax requests so authorize it with the custome attribute we created for the logged in users with the appropriate role. public async Task <IActionResult> AddOrEdit(int id, [Bind("Id,Name,Description,Price,PictureUrl,ProductTypeId,ProductBrandId")] Product Model, IFormFile Picture) { if (ModelState.IsValid) { //Create if (id == 0) { //upload a picture then save its path in the db table column : //note that blogImg is a parameter above in the function brackets: if (Picture != null && Picture.Length > 0) { //the method _upload saves the picture in a folder and returns its path. string PictureUrl = await _upload.UploadFile(Picture, "images/products"); Model.PictureUrl = PictureUrl; } _context.Add(Model); await _context.SaveChangesAsync(); } //Update else { try { //upload a picture then save its path in the db table column : //note that blogImg is a parameter above in the function brackets: if (Picture != null && Picture.Length > 0) { //the method _upload saves the picture in a folder and returns its path. string PictureUrl = await _upload.UploadFile(Picture, "images/products"); Model.PictureUrl = PictureUrl; } _context.Update(Model); await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!ProductModelModelExists(Model.Id)) { return(NotFound()); } else { throw; } } } //After the successfull Create or Edit, we do not return a view because we already did the Create or Edit using Ajax request, //which means we did not reload the page, so return the _ViewAll.cshtml which has the html table, return it as serialized html in json file, to be rendered in Index.cshtml as a partial view: return(Json(new { isValid = true, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "_ViewAll", _context.Products.Include(p => p.ProductBrand).Include(p => p.ProductType).ToList()) })); //in Index.cshtml we are displaying the Brand Name and Type Name, not Id, so return the Brand and Type all info using .Include(p => p.ProductBrand).Include(p => p.ProductType) //return NotFound(); } //if the model submitted is not valid according to the Attriburtes in [] in the model file in Models folder: return(Json(new { isValid = false, html = SerializeHtmlElemtnsToString.RenderRazorViewToString(this, "AddOrEdit", Model) })); }