عمليات Create, Read, Update & Delete في ASP.NET Core Identity
-
في هذا الدرس بنتعلم كيف بنعمل عمليات الاضافة والحذف والتعديل والقراءة (عمليات CRUD )باستخدام ASP.NET Core Identity
تمام حتي نفهم الموضوع نكمل الشغل على مشروع ASP.NET.Core.Identity:
انشاء Create Users in Identity
نبدأ بانشاء Model Class باسم Identity داخل مجلد Models باسم User.cs ونضيف الكود التالي الى الملف:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace ASP.NET.Core.Identity.Models
{
public class User
{
[Required]
public string Name { get; set; }
[Required]
[RegularExpression("^[a-zA-Z0-9_.-]+@([a-zA-Z0-9-]+.)+[a-zA-Z]{2,6}$", ErrorMessage = "E-mail is not valid")]
public string Email { get; set; }
[Required]
public string Password { get; set; }
}
}
تتم إدارة Users من خلالclass
UserManager<T>
حيث T هي class المختارة لتمثيل Users في قاعدة البيانات.
في الجدول التالي بنوضح مكونات هذا class
الاسم | الوصف |
Users | تقوم هذه الخاصية بإرجاع تسلسل يحتوي على المستخدمين المخزنين في قاعدة بيانات الهوية. |
FindByIdAsync(id) | ييستخدم للبحث عن مستخدم عن طريق رقم محدد specified ID |
CreateAsync(user, password) | تخزن هذه الطريقة مستخدم جديد في قاعدة البيانات باستخدام كلمة المرور المحددة |
UpdateAsync(user) | يتم تعديل مستخدم موجود في قاعدة بناء على بيانات الهوية Identity . |
DeleteAsync(user) | يتم حذف مستخدم من قاعدة بيانات عن طريق الهويةIdentity . |
AddToRoleAsync(user, name) | يضيف مستخدم إلى role |
RemoveFromRoleAsync(user, name) | يزيل مستخدم من role |
GetRolesAsync(user) | يعطي أسماء الأدوار roles التي يكون المستخدم عضوًا فيها |
IsInRoleAsync(user, name) | إرجاع "true" هو أن المستخدم عضو في دور محدد specified role، وإلا ترجع خطأ |
تمام نتذكر ان انشانا class باسم AppUser والي بنستخدمو لتمثيل المستخدمين في قاعدة البيانات واكيد تم وراثة IdentityUser لهذا class
الجدول التالي يصف خصائص AppUser class الأكثر فائدة.
الاسم | الوصف |
Id | يحتوي على Unique Id للمستخدم |
UserName | يحتوي على username الخاص بالمستخدم |
Email | يحتوي على البريد الإلكتروني للمستخدم |
تمام بهيك بنكون جهزنا الملفات التي بنحتاجها.
الان دور نعمل Controllers خلونا نضيف Controllers باسم AdminController داخل مجلد Controllers (اذا ما كان المجلد موجد اعمل مجلد بنفس الاسم) ونضيف الكود التالي:
using ASP.NET.Core.Identity.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ASP.NET.Core.Identity.Controllers
{
public class AdminController : Controller
{
private UserManager<AppUser> userManager;
public AdminController(UserManager<AppUser> usrMgr)
{
userManager = usrMgr;
}
public IActionResult Index()
{
return View();
}
}
}
نفهم شو عملنا في هذا Controllor
في Controller ، عملنا instance باسم userManager من UserManager من خلال حقن التبعية Dependency Injection. وبعدها في constructor عملنا تعيين قيمة المتغير المسمى userManager إلى كائن <UserManager<AppUser من خلال DI
الان خلونا نضيف Action باسم CreateUser والي بنستخدمها لانشاء مستخدم جديد في Identity database. الكود :
public ViewResult CreateUser() => View();
هذا action لاستدعاء CreateUser() View
[HttpPost]
public async Task<IActionResult> CreateUser(User user)
{
if (ModelState.IsValid)
{
AppUser appUser = new AppUser
{
UserName = user.Name,
Email = user.Email
};
IdentityResult result = await userManager.CreateAsync(appUser, user.Password);
if (result.Succeeded)
return RedirectToAction("Index");
else
{
foreach (IdentityError error in result.Errors)
ModelState.AddModelError("", error.Description);
}
}
return View(user);
}
نفهم الكود:
اولا هذا ال action من نوع HTTP POST يستقبل Model من نوع User الي المفروض بتحتوي على بيانات المستخدم، وبعدها بنتأكد من ModelState اذا كانت Valid او لا. اذا كانت Valid بنكمل شغل اذا لا بنرجع رسالة خطأ.
تمام الان اذا كانت ModelState صالحة بتم عمل instance باسم appUser من AppUser وبنخزن فيها قيم UserName, Email الي راجعه من User Model . الكود الي بيعمل هاذ الاشي :
AppUser appUser = new AppUser
{
UserName = user.Name,
Email = user.Email
};
الخاصية | الوصف | |
Succeeded | في حال نجاح العملية بتكون النتيجة Succeeded | |
Errors | يتم ارجاع object من نوع IEnumerable بحيث يحتوي على الأخطاء التي حدثت أثناء تنفيذ عملية Identity. ويحتوي IdentityError على خاصية description تعطي وصفًا لكل خطأ حدث |
IdentityResult result = await userManager.CreateAsync(appUser, user.Password);
if (result.Succeeded)
return RedirectToAction("Index");
else
{
foreach (IdentityError error in result.Errors)
ModelState.AddModelError("", error.Description);
}
return View(user);

@model User @{ ViewData["Title"] = "Create User"; } <h1 class="bg-light text-black">Create User</h1> <div asp-validation-summary="All" class="text-danger"></div> <form method="post"> <div class="form-group"> <label asp-for="Name"></label> <input asp-for="Name" class="form-control" /> </div> <div class="form-group"> <label asp-for="Email"></label> <input asp-for="Email" class="form-control" /> </div> <div class="form-group"> <label asp-for="Password"></label> <input asp-for="Password" class="form-control" /> </div><button type="submit" class="btn btn-success">Create</button></form>
@model User
@using ASP.NET.Core.Identity
@using ASP.NET.Core.Identity.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
https://localhost:44347/admin/CreateUser

حاول ادخال بيانات ثم اضغط فوق Create. خلونا نشوف قاعدة البيانات بعد الاضافة
من Visual Studio نروح الى
وبعدها من قاعدة البيانات نروح الى Table المسمى AspNetUsers واعرض البيانات بتكون النتيجة :
بهيك بنكون اضفنا مستخدم الى قاعدة البيانات .
طيب الان خلونا نعمل عمليات التعديل والحذف على المستخدمين .
اول اشي بنعملو هو قراءة بيانات المستخدمين وعرضها في صفحه وبعدها بنعمل العمليات.
قراءة جميع المستخدمين من Read all Users in Identity
public IActionResult Index()
{
return View(userManager.Users);
}
@model IEnumerable<AppUser>
@{
ViewData["Title"] = "All Identity Users";
}
<h1 class="bg-info text-white">All Identity Users</h1>
<table class="table table-sm table-bordered">
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
</tr>
@foreach (AppUser user in Model)
{
<tr>
<td>@user.Id</td>
<td>@user.UserName</td>
<td>@user.Email</td>
</tr>
}
</table>
https://localhost:44347/admin

@model IEnumerable<AppUser>
@{
ViewData["Title"] = "All Identity Users";
}
<h1 class="bg-light text-black">All Identity Users</h1>
<a asp-action="Create" class="btn btn-secondary">Create a User</a>
<br />
<br />
<table class="table table-sm table-bordered">
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Update</th>
</tr>
@foreach (AppUser user in Model)
{
<tr>
<td>@user.Id</td>
<td>@user.UserName</td>
<td>@user.Email</td>
<td>
<a class="btn btn-sm btn-primary" asp-action="Update" asp-route-id="@user.Id">
Update
</a>
</td>
</tr>
}
</table>
التعديل بكون على UserName، Email، Password .
تمام نرجع نوخذ فكره عن البيانات المخزنه في قاعدة البيانات (شوف الصورة):
اكيد لاحظت ان كلمة المرور مشفرة وبالتالي اي تعديل على كلمة المرور لازم يكون مشفر ايضا. ومشان نعمل التشفير بنستخدم IPasswordHasher
ومشان نستخدم هذا IPasswordHasher لازم نعرف instance خاص به وبعدها نستخدم dependency في constructor وبناء على هذا الكلام لازم نعدل الكود الى :
using Microsoft.AspNetCore.Mvc;
using Identity.Models;
using Microsoft.AspNetCore.Identity;
using System.Threading.Tasks;
namespace Identity.Controllers
{
public class AdminController : Controller
{
private UserManager<AppUser> userManager;
private IPasswordHasher<AppUser> passwordHasher;
public AdminController(UserManager<AppUser> usrMgr, IPasswordHasher<AppUser> passwordHash)
{
userManager = usrMgr;
passwordHasher = passwordHash;
}
}
}
public async Task<IActionResult> Update(string id)
{
AppUser user = await userManager.FindByIdAsync(id);
if (user != null)
return View(user);
else
return RedirectToAction("Index");
}
[HttpPost]
public async Task<IActionResult> Update(string id, string email, string password)
{
AppUser user = await userManager.FindByIdAsync(id);
if (user != null)
{
if (!string.IsNullOrEmpty(email))
user.Email = email;
else
ModelState.AddModelError("", "Email cannot be empty");
if (!string.IsNullOrEmpty(password))
user.PasswordHash = passwordHasher.HashPassword(user, password);
else
ModelState.AddModelError("", "Password cannot be empty");
if (!string.IsNullOrEmpty(email) && !string.IsNullOrEmpty(password))
{
IdentityResult result = await userManager.UpdateAsync(user);
if (result.Succeeded)
return RedirectToAction("Index");
else
Errors(result);
}
}
else
ModelState.AddModelError("", "User Not Found");
return View(user);
}
private void Errors(IdentityResult result)
{
foreach (IdentityError error in result.Errors)
ModelState.AddModelError("", error.Description);
}
لاحظ ان اضفنا نوعين من هذا action
الأول من نوع Get لاستدعاء View الخاص بالتعديل ومن خلاله بتم عرض بيانات المستخدم بناء على Id الخاص بالمستخدم باستخدام الامر FindByIdAsync(id) والنتيجة بتتخزن في في متغير باسم user من نوع AppUser وبعدها بنتأكد من user اذا ما كان Null هذا بيعني ان تم ايجاد بيانات المستخدم وبعدها بنرجع البيانات الى View على شكل user Model
والثاني من النوع Post لاجراء التعديل المطلوب. حيث قمنا بارجاع بيانات المستخدم بناء على Id المرسل باستخدام الامر
await userManager.FindByIdAsync(id)
وحتي نعمل التعديل المطلوب اول اشي تأكدنا من وجود بيانات راجعه باستخدام الامر
if (user != null)
وبعدها عملنا تحقق من القيم المدخلة،
الايميل ما يكون فاضي(الكود) :
if (!string.IsNullOrEmpty(email))
user.Email = email;
else
ModelState.AddModelError("", "Email cannot be empty");
والباسورد عملنا تشفير الها
if (!string.IsNullOrEmpty(password))
user.PasswordHash = passwordHasher.HashPassword(user, password);
else
ModelState.AddModelError("", "Password cannot be empty");
واذا كانت القيم صحيحه بنستخدم الامر لاجراء التعديل المطلوب
await userManager.UpdateAsync(user);
والنتيجة بتتخزن في متغير باسم result من نوع IdentityResult وحسب النتيجة بتم اتخاذ القرار اذا كان العملية ناجحه بنرجع لصفحة Index واذا في خطأ بنعمل استدعاء ل Errors function الي بنعمل تخزين الاخطاء في Model وبعدها بنرجع هذه الأخطاء الى View
انشاء View
اكيد حتي نعدل على البيانات بنحتاج الى عرض هذه البيانات في شاشة لذا المطلوب انشاء View لهذا action مشان هيك انقر يمين فوق Update action واختر Add new View وبعدها نضيف الكود التالي :
@model AppUser
@{
ViewData["Title"] = "Update User";
}
<h1 class="bg-light text-black">Update User</h1>
<a asp-action="Index" class="btn btn-secondary">Back</a>
<div asp-validation-summary="All" class="text-danger"></div>
<form asp-action="Update" method="post">
<div class="form-group">
<label asp-for="Id"></label>
<input asp-for="Id" class="form-control" disabled />
</div>
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input name="password" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
https://localhost:44347/admin


@model IEnumerable<AppUser> @{ ViewData["Title"] = "All Identity Users"; } <h1 class="bg-light text-black">All Identity Users</h1> <a asp-action="Create" class="btn btn-secondary">Create a User</a> <br /> <br /> <table class="table table-sm table-bordered"> <tr> <th>ID</th> <th>Name</th> <th>Email</th> <th>Update</th> <th>Delete</th> </tr> @foreach (AppUser user in Model) { <tr> <td>@user.Id</td> <td>@user.UserName</td> <td>@user.Email</td> <td> <a class="btn btn-sm btn-primary" asp-action="Update" asp-route-id="@user.Id"> Update </a> </td> <td> <form asp-action="Delete" asp-route-id="@user.Id" method="post"> <button type="submit" class="btn btn-sm btn-danger"> Delete </button> </form> </td> </tr> } </table>
asp-action="Delete"
asp-route-id="@user.Id"
method="post"
userManager.DeleteAsync(user);
[HttpPost]
public async Task<IActionResult> Delete(string id)
{
AppUser user = await userManager.FindByIdAsync(id);
if (user != null)
{
IdentityResult result = await userManager.DeleteAsync(user);
if (result.Succeeded)
return RedirectToAction("Index");
else
Errors(result);
}
else
ModelState.AddModelError("", "User Not Found");
return View("Index", userManager.Users);
}
AppUser user = await userManager.FindByIdAsync(id);
IdentityResult result = await userManager.DeleteAsync(user);
if (result.Succeeded)
return RedirectToAction("Index");
else
Errors(result);
https://localhost:44347/admin

اترك تعليقك