MVC Day 4 Thumb

اعتبار سنجی در ASP.NET MVC ، به روز چهارم از “آموزش MVC  در ۷ روز” خوش آمدید. اگر به طور مستقیم به این مقاله سر زده اید، به شما پیشنهاد می کنیم که ابتدا بخش های قبلی را مطالعه کرده و بعد به سراغ این بخش بیایید.

اعتبار سنجی در ASP.NET MVC:

فهرست مطالب:

  • تمرین پانزدهم – حفظ مقادیر در خطاهای اعتبارسنجی
    • پرسش و پاسخ در تمرین پانزدهم
  • تمرین شانزدهم – اضافه کردن اعتبارسنجی سمت کلاینت
    • پرسش و پاسخ در تمرین شانزدهم
  • تمرین هفدهم – اضافه کردن احراز هویت
    • پرسش و پاسخ در تمرین هفدهم
  • تمرین هجدهم – نمایش UserName در View
  • تمرین نوزدهم – پیاده سازی Logout
  • تمرین بیستم – پیاده سازی اعتبارسنجی در صفحه Login
  • تمرین بیست و یکم – پیاده سازی اعتبارسنجی سمت کلاینت در صفحه Login
    • پرسش و پاسخ در تمرین بیست و یکم
  • جمع بندی

تمرین پانزدهم – حفظ مقادیر در خطاهای اعتبارسنجی

در تمرین سیزدهم، اعتبارسنجی سمت سرور را معرفی کردیم و در تمرین چهاردهم با اضافه کردن Custom Validation آن را یک قدم جلوتر بردیم.

توصیه می کنیم که به تمرین چهاردهم برگشته و دوباره آن را اجرا کنید، کد و خروجی آن را به طور کامل درک کنید.

در تمرین پانزدهم می خواهیم یاد بگیریم، زمانی که اعتبارسنجی با خطا مواجه شد بتوانیم دوباره داده ها را داشته باشیم.

گام ۱: ایجاد کلاس CreateEmployeeViewModel

یک کلاس جدید در فولدر ViewModel به صورت زیر ایجاد می کنیم.

public class CreateEmployeeViewModel

{

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string Salary { get; set; }

}

 

گام ۲: تغییر متد  SaveEmployee

برای دوباره پر کردن داده ها از شی Employee ایجاد شده توسط Model Binder استفاده می کنیم. متد SaveEmployee را به صورت زیر تغییر می دهیم.

public ActionResult SaveEmployee(Employee e, string BtnSubmit)
{
    switch (BtnSubmit)
    {
        case "Save Employee":
            if (ModelState.IsValid)
            {
                EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
                empBal.SaveEmployee(e);
                return RedirectToAction("Index");
            }
            else
            {
                CreateEmployeeViewModel vm = new CreateEmployeeViewModel();
                vm.FirstName = e.FirstName;
                vm.LastName = e.LastName;
                if (e.Salary.HasValue)
                {
                    vm.Salary = e.Salary.ToString();                        
                }
                else
                {
                    vm.Salary = ModelState["Salary"].Value.AttemptedValue;                       
                }
                return View("CreateEmployee", vm); // Day 4 Change - Passing e here
            }
        case "Cancel":
            return RedirectToAction("Index");
    }
    return new EmptyResult();
}

 

گام ۳: پرکردن دوباره مقادیر در View

گام ۳.۱: تبدیل نوع View به strongly type

کد زیر را در قسمت بالای CreateEmployee View قرار می دهیم.

@using WebApplication1.ViewModels
@model CreateEmployeeViewModel

 

گام ۳.۲: نمایش مقادیر در کنترل مربوطه از Model

 

...

...

...

<input type="text" id="TxtFName" name="FirstName" value="@Model.FirstName" />

...

...

...

<input type="text" id="TxtLName" name="LastName" value="@Model.LastName" />

...

...

...

<input type="text" id="TxtSalary" name="Salary" value="@Model.Salary" />

...

...

...

 

گام ۴: تست و اجرا

کلید F5 را فشار داده و برنامه را اجرا می کنیم. با کلیک کردن روی لینک “کارمند جدید” به صفحه AddNew می رویم.

دلیل خطای بالا در پایان این تمرین بحث می شود.

گام ۵: تغییر متد AddNew

public ActionResult AddNew()
{
return View("CreateEmployee&rdquo;, new CreateEmployeeViewModel());
}

 

گام ۶: تست و اجرا

با کلید F5 دوباره برنامه را اجرا می کنیم.

تست ۱:

  • با کلیک روی لینک “کارمند جدید” به صفحه AddNew می رویم.
  • FirstName را خالی می گذاریم.
  • مقدار Salary را ۵۶ قرار می دهیم.
  • روی دکمه “Save ” کلیک می کنیم.

تست بالا دو اعتبارسنجی را با خطا مواجه می کند.

همان طور که مشاهده می کنید، مقدار Salary در textbox حفظ شده است.

تست ۲:

همان طور که می بینید مقادیر FirstName و LastName در textboxها باقی مانده است. جالب تر اینکه مقدار Salary حفظ نشده است. درباره دلیل آن و راه حلی برای آن در انتهای تمرین بحث خواهیم کرد.

پرسش و پاسخ در تمرین پانزدهم:

آیا واقعا مقادیر را در اینجا حفظ کرده ایم؟

خیر، درواقع ما مقادیر را دوباره از داده های post شده پر کردیم.

چرا لازم است که “new CreateEmployeeViewModel()” را در زمان تعریف درخواست در متد “AddNew” ارسال کنیم؟

در View ما سعی داریم که textbox را با مقادیر داخل Model پر کنیم.

مثال:

<input id="TxtSalary" name="Salary" type="text" value="@Model.Salary" />

همان طور که می بینید، در بلاک کد بالا ما به FirstName موجود در Model جاری دسترسی داریم. اگر Model، null باشد، خطای استثنایی به صورت “Object reference not set to an instance of the class” رخ می دهد، به این معنی که این رفرنس به هیچ شی ای اشاره نمی کند. برای حل این مشکل “new CreateEmployeeViewModel()” در زمان تعریف درخواست ارسال می شود.

آیا روش اتوماتیکی وجود دارد که این امکان را به ما بدهد؟

بله، می توانیم از کلاس های HTML Helper استفاده کنیم. درباره این کلاس ها در تمرین های بعدی صحبت خواهیم کرد.

تمرین شانزدهم – اضافه کردن اعتبارسنجی سمت کلاینت

در ابتدا تمام اعتبارسنجی های موردنیاز در این قسمت را مرور می کنیم.

  1. FirstName نباید خالی گذاشته شود.
  2. طول LastName نباید بیش از ۵ کاراکتر باشد.
  3. Salary نباید خالی گذاشته شود.
  4. Salary باید عدد مناسبی باشد.
  5. FirstName نباید شامل کاراکتر “@” باشد.

حال ببینیم که چطور باید آنها را پیاده سازی کنیم.

گام ۱: ایجاد فایل اعتبارسنجی جاوااسکریپت

فایل جاوااسکریپتی با نام “Validation.js” ایجاد کرده و آن را در فولدر Scripts قرار می دهیم.

گام ۲: ایجاد توابع اعتبارسنجی

در فایل “Validation.js” توابع اعتبارسنجی را به صورت زیر ایجاد می کنیم:

 

function IsFirstNameEmpty() {
    if (document.getElementById('TxtFName').value == "") {
        return ' نام کارمند نباید خالی باشد.;
    }
    else { return ""; }
}

function IsFirstNameInValid() {    
    if (document.getElementById('TxtFName').value.indexOf("@") != -1) {
        return 'First Name';
    }
    else { return ""; }
}
function IsLastNameInValid() {
    if (document.getElementById('TxtLName').value.length>=5) {
        return 'نام خانوادگی کارمند نباید بیش از ۵ کاراکتر باشد.;
    }
    else { return ""; }
}
function IsSalaryEmpty() {
    if (document.getElementById('TxtSalary').value=="") {
        return 'فیلد حقوق نباید خالی باشد.';
    }
    else { return ""; }
}
function IsSalaryInValid() {
    if (isNaN(document.getElementById('TxtSalary').value)) {
        return 'برای حقوق، مقدار معتبر وارد نمایید.';
    }
    else { return ""; }
}
function IsValid() {

    var FirstNameEmptyMessage = IsFirstNameEmpty();
    var FirstNameInValidMessage = IsFirstNameInValid();
    var LastNameInValidMessage = IsLastNameInValid();
    var SalaryEmptyMessage = IsSalaryEmpty();
    var SalaryInvalidMessage = IsSalaryInValid();

    var FinalErrorMessage = "Errors:";
    if (FirstNameEmptyMessage != "")
        FinalErrorMessage += "\n" + FirstNameEmptyMessage;
    if (FirstNameInValidMessage != "")
        FinalErrorMessage += "\n" + FirstNameInValidMessage;
    if (LastNameInValidMessage != "")
        FinalErrorMessage += "\n" + LastNameInValidMessage;
    if (SalaryEmptyMessage != "")
        FinalErrorMessage += "\n" + SalaryEmptyMessage;
    if (SalaryInvalidMessage != "")
        FinalErrorMessage += "\n" + SalaryInvalidMessage;

    if (FinalErrorMessage != "Errors:") {
        alert(FinalErrorMessage);
        return false;
    }
    else {
        return true;
    }
}

گام ۳: ارجاع دادن به فایل Validation در View

بسیار ساده، رفرنس “Validation.js” را در قسمت head مربوط به “CreateEmployee” قرار می دهیم.

<script src="~/Scripts/Validations.js"></script>

گام ۴: اضافه کردن اعتبارسنجی ها

تابع IsValid را در رویداد کلیک دکمه “SaveEmployee” به صورت زیر فراخوانی می کنیم.

<input type="submit" name="BtnSubmit" value="Save Employee" onclick="return IsValid();" />

گام ۵: تست و اجرا

با کلید F5 برنامه را اجرا می کنیم. با کلیک روی لینک “کارمند جدید” به صفحه AddNew می رویم.

تست ۱:

تست ۲:

پرسش و پاسخ در تمرین شانزدهم:

چرا کلمه کلیدی return در رویداد کلیک دکمه SaveEmployee لازم است؟

همان طور که در تمرین نهم بحث کردیم، دکمه submit زمانی که کلیک می شود یک درخواست به سرور را ایجاد می کند. زمانی که اعتبارسنجی با خطا مواجه می شود راهی برای ایجاد درخواست به سرور وجود ندارد. با نوشتن “return false” در رویداد کلیک، می توانیم درخواست پیش فرض سرور را متوقف کنیم.

درمثال ما، تابع IsValid مقدار false را برمی گرداند و ما به نتیجه دلخواه دست پیدا می کنیم.

آیا به جای استفاده از alert می توانیم پیام های خطا را در خود صفحه نمایش دهیم؟

بله با ایجاد یک تگ span به سادگی می توان این کار را انجام داد. با استفاده از CSS در ابتدا آن را پنهان(Invisible) می کنیم و در کلیک دکمه submit اگر اعتبارسنجی با خطا مواجه شد، با استفاده از جاوااسکریپت آن را ظاهر(Visible) می کنیم.

آیا روش اتوماتیکی برای اعتبارسنجی سمت کلاینت وجود دارد؟

بله، وقتی ما از HTML Helper استفاده می کنیم، اعتبارسنجی سمت کلاینت را به طور اتوماتیک براساس اعتبارسنجی سمت سرور دریافت می کنیم. در این مورد، در تمرین بعدی صحبت خواهیم کرد.

آیا اعتبارسنجی سمت سرور حتما لازم است؟

بله، در برخی موارد که جاوا اسکریپت غیرفعال می شود، به جای آن اعتبارسنجی سمت سرور همه چیز را کنترل می کند.

تمرین هفدهم – اضافه کردن احراز هویت

در این تمرین، متد GetView خود را امن می کنیم. ما مطمئن خواهیم شد که فقط کاربر مجاز می تواند به action method دسترسی پیدا کند.

در روز اول از این سری آموزشی با معنای واقعی کلمات ASP.Net و MVC آشنا شدیم. متوجه شدیم که ASP.Net MVC بخشی از ASP.Net است. ASP.Net MVC بسیاری از امکانات ASP.Net را ارث بری می کند. یکی از این امکانات Forms Authentication یا احراز هویت در فرم ها می باشد.

قبل از اینکه این تمرین را شروع کنیم، ببینیم که احراز هویت در فرم ها در ASP.Net به چه صورت است.

  1. کاربر به وسیله مرورگر، درخواستی برای سایتی که احراز هویت آن فعال است ارسال می کند.
  2. مرورگر تمام کوکی های ذخیره شده در سیستم کلاینت را با درخواست ارسال می کند.
  3. زمانی که درخواست سمت سرور دریافت می شود، سرور درخواست را جهت یافتن کوکی های خاصی به نام “Authentication Cookie” بررسی می کند.
  4. اگر کوکی احراز هویت معتبری یافت شد، سرور اعتبار هویت کاربر را تأیید می کند یا به زبان ساده، کاربر را به عنوان یک کاربر مجاز به حساب می آورد.
  5. اگر کوکی احراز هویت معتبری یافت نشد، سرور کاربر را به عنوان یک ناشناس یا کاربر غیرمجاز شناسایی می کند. در این مورد، اگر منبع درخواست شده به عنوان منبع محافظت شده (protected/secured) مشخص شده باشد، کاربر به صفحه ورود هدایت می شود.

گام ۱: ایجاد AuthenticationController و متد Login

روی فولدر Controller راست کلیک کرده و Add New Controller را انتخاب کرده و یک Controller به نام “Authentication” ایجاد می کنیم. در این مورد، نام کامل کلاس “AuthenticationController” خواهد بود.

در Controller متدی با نام Login به صورت زیر ایجاد می کنیم.

 

public class AuthenticationController : Controller
{	
    // GET: Authentication
    public ActionResult Login()
    {
        return View();
    }
}

گام ۲: ایجاد Model

یک کلاس Model جدید به نام “UserDetails” در فولدر Models ایجاد می کنیم.

namespace WebApplication1.Models
{
    public class UserDetails
    {
        public string UserName { get; set; }
        public string Password { get; set; }
    }
}

 

گام ۳: ایجاد Login View

یک View جدید به نام Login در فولدر “~/Views/Authentication” ایجاد می کنیم. نوع آن را از نوع strong type از کلاس UserDetails تعریف می کنیم.

کد HTML زیر را در View قرار می دهیم.

 

@model WebApplication1.Models.UserDetails

@{

    Layout = null;

}

<!DOCTYPE html>

<html>

<head>

    <meta name="viewport" content="width=device-width" />

    <title>Login</title>

</head>

<body>

    <div>

        @using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))

        {

            @Html.LabelFor(c=>c.UserName)

            @Html.TextBoxFor(x=>x.UserName)

           

            <br />

            @Html.LabelFor(c => c.Password)

            @Html.PasswordFor(x => x.Password)

            <br />


            <input type="submit" name="BtnSubmit" value="Login" />

        }

    </div>

</body>

</html>

همان طور که مشاهده می کنید، به جای استفاده از HTML از کلاس HtmlHelper استفاده کرده ایم.

  • در View یک شی آماده استفاده از کلاس HtmlHelper به نام Html دریافت می کنیم.
  • توابع کلاس HtmlHelper به سادگی رشته html را برمی گرداند.

مثال ۱:

@Html.TextBoxFor(x=>x.UserName)

کد بالا،  HTML زیر را تولید می کند.

<input id="UserName" name="UserName" type="text" value="" />

مثال ۲:

@using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))
{
}

کد بالا، HTML زیر را تولید می کند.

<form action="/Authentication/DoLogin" method="post">
</form>

گام ۴: تست و اجرا

با کلید F5 برنامه را اجرا می کنیم. در آدرس بار، آدرس action method مربوط به Login را قرار می دهیم. در این مثال، به صورت http://localhost:8870/Authentication/Login خواهد بود.

گام ۵: فعال سازی احراز هویت در فرم ها

فایل Web.config را باز می کنیم و به قسمت System.Web می رویم. قسمت فرزند آن با نام authentication را پیدا می کنیم. اگر وجود نداشت، آن را ایجاد می کنیم. Authentication mode را برای فرم ها تنظیم می کنیم و login URL را متد “Login” که در گام اول ایجاد کردیم، قرار می دهیم.

<authentication mode="Forms">
<forms loginurl="~/Authentication/Login"></forms>
</authentication>

گام ۶: امن کردن action method

EmployeeController را باز کرده و صفت Authorize را به شکل زیر به Index action اضافه می کنیم.

[Authorize]
public ActionResult Index()
{
    EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();
......

گام ۷: تست و اجرا

با کلید F5 برنامه را اجرا می کنیم. در آدرس بار، آدرس Index action موجود در EmployeeController را قرار می دهیم. در این مثال به صورت http://localhost:8870/Employee/Index می باشد.

همان طور که مشاهده می کنید، درخواست به index action به طور خودکار به login action هدایت می شود.

گام ۸: ایجاد امکان Business layer

کلاس EmployeeBusinessLayer را باز کرده و یک متد به نام IsValidUser به شکل زیر ایجاد می کنیم.

public bool IsValidUser(UserDetails u)
{
    if (u.UserName == "Admin" && u.Password == "Admin")
    {
        return true;
    }
    else
    {
        return false;
    }
}

 

توجه داشته باشید که در Business layer ما username و password را با مقادیر نوشته شده در کد مقایسه می کنیم. در حالی که در حالت واقعی می توانیم لایه دیتابیس را فراخوانی کرده و آنها را با مقادیر واقعی مقایسه می کنیم.

گام ۹: ایجاد متد DoLogin

کلاس AuthenticationController را باز کرده و یک متد جدید به نام DoLogin ایجاد می کنیم.

زمانی که دکمه Login در Login View کلیک می شود، این متد DoLogin فراخوانی می شود (گام ۳ را بررسی کنید)

کارهایی که باید در DoLogin باید انجام دهیم در زیر آمده است:

  1. بررسی مجاز بودن کاربر از طریق فراخوانی تابع business layer
  2. اگر کاربر مجاز بود، یک authentication cookie ایجاد می کنیم که باعث می شود درخواست های بعدی معتبر شناخته شوند.
  3. اگر کاربر غیر مجاز بود، یک پیغام خطای جدید به ModelState جاری اضافه می کنیم که این پیام در View نمایش داده می شود.
[HttpPost]

public ActionResult DoLogin(UserDetails u)

{

    EmployeeBusinessLayer bal = new EmployeeBusinessLayer();

    if (bal.IsValidUser(u))

    {

        FormsAuthentication.SetAuthCookie(u.UserName, false);

        return RedirectToAction("Index", "Employee");

    }

    else

    {

        ModelState.AddModelError("CredentialError", "نام کاربری یا پسورد غیر معتبر می باشد.");

        return View("Login");

    }

}

 

اجازه دهید، نگاه دقیق تری به کد داشته باشیم:

  • اگر به خاطر داشته باشید در “روز سوم، تمرین سیزدهم” درباره ModelState صحبت کردیم و متوجه شدیم که حالت کنونی Model را مخفی (encapsulate) می کند. همچنین تمام خطاهای مربوط به این Model را نگه می دارد. در کد بالا، زمانی که کاربر غیرمجاز باشد، یک پیغام خطا به آن اضافه می شود (با کلید “CredentialError” و پیغام “نام کاربری یا پسورد غیر معتبر می باشد.”)
  • SetAuthCookie یک کوکی جدید در سیستم کلاینت موردنظر ایجاد می کند.

گام ۱۰: نمایش خطا در View

Login View را باز کرده و کد زیر را درست بالای @Html.BeginForm قرار می دهیم.

 

@Html.ValidationMessage("CredentialError", new {style="color:red;" })

@using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))

{

 

گام ۱۱: تست و اجرا

کلید F5 را فشار داده و برنامه را اجرا می کنیم. به طور مستقیم درخواستی برای صفحه Login ایجاد می کنیم. من یقین دارم که تا حالا یاد گرفتید چطور این کار را انجام دهید  J.

نکته: اگر می خواهید درخواستی به صفحه Index از EmployeeController داشته باشید، می بینید که به طور اتوماتیک صفحهLogin  هدایت می شوید.

تست ۱:

تست۲:

پرسش و پاسخ در تمرین هفدهم:

چرا صفت [HttpPost] به متد DoLogin اضافه شده است؟

این صفت متد DoLogin را مجبور می کند که تنها برای درخواست های Post باز شود. اگر کاربری سعی کند که درخواست get ارسال کند، این متد کار نخواهد کرد.

 

آیا صفت های دیگری نیز شبیه به صفت گفته شده داریم؟

بله، صفت های HttpGet و HttpDelete نیز داریم. به عنوان بهترین راهکار، هر یک از action methodها باید با یکی از این صفت ها استفاده شود.

توجه داشته باشید که تنها به دلیل ساده کردن روند آموزش و کد نویسی، ما در همه پروژه از این صفات استفاده نمی کنیم. اما توصیه می کنیم که شما حتما در پروژه خود از این صفت ها استفاده نمایید.

همین طور که در آموزش ها پیش می رویم، درباره سایر راهکارهای مفید نیز صحبت خواهیم کرد.

آیا لازم است که حتما “FormsAuthentication.SetAuthCookie” نوشته شود؟

بله.

اجازه دهید که یک فرایند را به طور مختصر بررسی کنیم:

  • کاربر اولین درخواست خود را با استفاده از مرورگر به سرور ارسال می کند.
  • زمانی که درخواست از طریق مرورگر انجام شد، تمام کوکی های جمع آوری شده به همراه درخواست ارسال می شود.
  • سرور درخواست را دریافت کرده و پاسخ را ارسال می کند.
  • حال همانطور که می دانیم، درخواست-پاسخ از طریق پروتکل HTTP انجام می شود و HTTP یک پروتکل بدون وضعیت است. به این معنا که برای سرور، هر درخواستی یک درخواست جدید محسوب می شود بنابراین زمانی که همان کاربر درخواست دوم را برای سرور ارسال می کند، آن را نمی شناسد. برای حل این مشکل، ما یک کوکی به پاسخ آماده شده ضمیمه کرده و ارسال می کنیم.
  • زمانی که مرورگر کاربر پاسخ را به همراه کوکی دریافت می کند، این کوکی را در سیستم کاربر ایجاد می کند.
  • حالا اگر کاربر بار دیگر درخواستی ایجاد کند، سرور کاربر را می شناسد چرا که این درخواست شامل کوکی می باشد.

FormsAuthentication.SetAuthCookie یک کوکی خاص به نام “Authentication cookie” ایجاد می کند.

آیا این به این معناست که FormsAuthentication بدون کوکی ها کار نمی کند؟

خیر اینطور نیست، ما جایگزینی برای آن داریم، می توانیم از URI به جای کوکی ها استفاده کنیم.

Web.Config را باز کرده و بخش “Authentication/Forms” را به شکل زیر تغییر می دهیم:

 

<forms cookieless="UseUri" loginurl="~/Authentication/Login"></forms>

 

به طور پیش فرض ویژگی بدون کوکی روی “َAutoDetect” تنظیم می شود. به این معنی که احراز هویت از طریق کوکی کار می کند و در مواردی که کوکی پشتیبانی نمی شود، URL کارهای موردنیاز را انجام می دهد.

پارامتر دوم FormsAuthentication.SetAuthCookie چه کاری انجام می دهد؟

این پارامتر نشان می دهد که ما می خواهیم یک کوکی پایدار ایجاد کنیم یا خیر. کوکی های غیر پایدار یا موقتی به طور اتوماتیک بعد از بسته شدن مرورگر حذف می شوند. اما کوکی های پایدار به طور اتوماتیک حذف نمی شوند و باید آن ها را به صورت دستی یا از طریق کدنویسی و یا از طریق تنظیمات مرورگر حذف کنیم.

خروج از برنامه با استفاده از کدنویسی چگونه است؟

در یکی از تمرین های آینده آن را یاد خواهیم گرفت.

زمانی که پسورد اشتباه باشد، چگونه مقدار نام کاربری دوباره در textbox قرار می گیرد؟

این امکان را کلاس های HTML helper در اختیار ما قرار می دهند. این کلاس ها کنترل های ورودی را با استفاده از داده های post شده دوباره پر می کنند. این یکی از مزایای استفاده از کلاس های HTML helper می باشد.

@Html.ValidationMessage چه کاری انجام می دهد؟

همان طور که در تمرین سیزدهم بحث کردیم، پیام های ModelState را براساس کلید نمایش می دهد.

صفت Authorize چه کاری انجام می دهد؟

در Asp.Net MVC مفهومی به نام فیلتر وجود دارد، که برای فیلتر کردن درخواست ها و پاسخ ها استفاده می شود. چهار نوع فیلتر وجود دارد. ما در طول این ۷ روز درباره همه آن ها بحث خواهیم کرد. صفت Authorize تحت فیلتر Authorization کار می کند. این صفت مطمئن می شود که تنها کاربران مجاز اجازه دسترسی به action method را دارند.

آیا می توانیم هر دو صفت HttpPost و Authorize را به یک action method اضافه کنیم؟

بله می توانیم.

چرا در این تمرین، هیچ ViewModelای نداریم؟

همانطور که در تمرین ششم بحث کردیم، View نباید به طور مستقیم به Model متصل شود. ما باید همیشه یک ViewModel بین View و Model داشته باشیم. مهم نیست که این View یک View برای نمایش است یا برای ثبت داده، همیشه باید به یک ViewModel متصل شود. دلیل استفاده نکردن از ViewModel در این پروژه فقط ساده سازی روند کار است. در پروژه های واقعی به شدت توصیه می کنیم که ViewModel داشته باشید.

آیا لازم است که صفت Authorize را به همه action method ها اضافه کنیم؟

خیر، می توانیم آن را در سطح Controller یا به صورت Global اضافه کنیم. زمانی که در سطح Controller اضافه می شود، برای همه action methodهای آن Controller قابل استفاده است. اگر به صورت Global اضافه شود، برای همه action method ها در همه Controller ها قابل استفاده می باشد.

سطح Controller:

 

[Authorize]

public class EmployeeController : Controller

{

....

 

به صورت Global:

گام ۱: از فولدر App_start فایل FilterConfig را باز می کنیم.

گام ۲: یک خط جدید RegisterGlobalFilters به صورت زیر اضافه می کنیم.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)

{

    filters.Add(new HandleErrorAttribute());//Old line

    filters.Add(new AuthorizeAttribute());//New Line

}

 

گام ۳: صفت AllowAnonymous را به Authentication Controller اضافه می کنیم.

[AllowAnonymous]

public class AuthenticationController : Controller

{

 

گام ۴: برنامه را به همان صورت قبلی تست و اجرا می کنیم.

Filters.Add(new HandleErrorAttribute()) چه کاری انجام می دهد؟

در این باره، به طور مفصل در تمرین بعدی صحبت خواهیم کرد.

چرا صفت AllowAnonymous برای Authentication Controller مورد نیاز است؟

ما فیلتر Authorize را در سطح Global اضافه کردیم. یعنی همه چیز محافظت شده هستند مانند متدهای Login و DoLogin. AllowAnonymous متد را برای درخواست های بدون احراز هویت باز می کند.

متد RegisterGlobalFilters در کلاس FilterConfig چگونه فراخوانی می شود؟

این متد در Application_Startevent نوشته شده در فایل Global.asax فراخوانی می شود.

تمرین شانزدهم – نمایش نام کاربری در View

در این تمرین می خواهیم نام کاربری کاربر وارد شده را در View نمایش دهیم.

گام ۱: اضافه کردن UserName در ViewModel

EmployeeListViewModel را باز کرده و یک property به نام UserName به شکل زیر اضافه می کنیم.

public class EmployeeListViewModel

{

    public List<EmployeeViewModel> Employees { get; set; }

    public string UserName { get; set; }

}

 

گام ۲: مقداردهی به UserName

EmployeeController را باز کرده و Index را به صورت زیر تغییر می دهیم:

public ActionResult Index()

{

    EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();

    employeeListViewModel.UserName = User.Identity.Name; //New Line

......

 

گام ۳: نمایش UserName در View

Index.cshtml را باز کرده و UserName را به صورت زیر نمایش می دهیم:

 

<body>



  <div style="text-align:right"> Hello, @Model.UserName </div>



  <hr />



  <a  href="/Employee/AddNew">Add New</a>



    <div>



       <table border="1"><span style="font-size: 9pt;">

</span>

 

گام ۴: تست و اجرا

کلید F5 را فشار داده و برنامه را اجرا می کنیم. فرایند ورود را کامل کرده و خروجی زیر را مشاهده خواهیم کرد.

تمرین نوزدهم – پیاده سازی Logout

گام ۱: ایجاد لینک Logout

Index.cshtml را باز کرده و لینک Logout را به صورت زیر ایجاد می کنیم:

<body>



    <div style="text-align:right">Hello, @Model.UserName



    <a href="/Authentication/Logout">Logout</a></div>



    <hr />



    <a  href="/Employee/AddNew">Add New</a>



    <div>



        <table border="1">

 

گام ۲: ایجاد متد logout

AuthenticationController را باز کرده و متد جدیدی با نام Logout می سازیم.

public ActionResult Logout()

{

    FormsAuthentication.SignOut();

    return RedirectToAction("Login");

}

 

گام ۳: تست و اجرا

کلید F5 را فشار داده و برنامه را اجرا می کنیم.

 

تمرین بیستم: پیاده سازی اعتبارسنجی در صفحه Login

گام ۱: اضافه کردن Data Annotation

UserDetails.cs را باز کرده و Data Annotation را به صورت زیر اضافه می کنیم:

public class UserDetails

{



[StringLength(7,MinimumLength=2, ErrorMessage = "UserName length should be between 2 and 7")]

    public string UserName { get; set; }

    public string Password { get; set; }

}

 

گام ۲: نمایش پیغام خطا در View

Login.cs را برای نمایش پیغام خطا به شکل زیر تغییر می دهیم.

@using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))

{

    @Html.LabelFor(c=>c.UserName)

    @Html.TextBoxFor(x=>x.UserName)

    @Html.ValidationMessageFor(x=>x.UserName)

......

 

نکته: این بار به جای استفاده از Html.ValidationMessage از HtmlValidationMessageFor استفاده کرده ایم. هر دو یک کار را انجام می دهند. HtmlValidationMessageFor فقط زمانی که View از نوع Strong type است، استفاده می شود.

گام ۳: تغییر DoLogin

متد DoLogin را به شکل زیر تغیر می دهیم:

[HttpPost]

public ActionResult DoLogin(UserDetails u)

{

    if (ModelState.IsValid)

    {

        EmployeeBusinessLayer bal = new EmployeeBusinessLayer();

        if (bal.IsValidUser(u))

        {

            FormsAuthentication.SetAuthCookie(u.UserName, false);

            return RedirectToAction("Index", "Employee");

        }

        else

        {

            ModelState.AddModelError("CredentialError", "Invalid Username or Password");

            return View("Login");

        }

    }

    else

    {

        return View("Login");

    }

}

 

گام ۴: تست و اجرا

کلید F5 را فشار داده و برنامه را اجرا می کنیم

بعد از Refresh کامل صفحه

تمرین بیست و یکم – پیاده سازی اعتبارسنجی سمت کلاینت در صفحه Login

این بار می خواهیم اعتبارسنجی سمت کلاینت را با روشی دیگر انجام دهیم.

گام ۱: دانلود فایل هایUnobtrusive  jQuery

روی نام پروژه راست کلیک کرده و Manage Nuget packages را انتخاب می کنیم.

روی online کلیک کرده و “jQuery Unobtrusive” را جستجو می کنیم.

سپس “Microsoft jQuery Unobtrusive” را نصب می کنیم.

گام ۲: Include کردن فایل های اعتبارسنجی jQuery در View

مراحل بالا، سه فایل جاوااسکریپت را به فولدر Scripts اضافه می کند.

  • jQuery-Someversion.js
  • Validate.js
  • validate.unobtrusive

Login.cshtml را باز کرده و در قسمت head هر سه فایل js را به همین ترتیب include می کنیم.

<script src="~/Scripts/jquery-1.8.0.js"></script>

<script src="~/Scripts/jquery.validate.js"></script>

<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>

 

گام ۳: تست و اجرا

کلید F5 را فشار داده و برنامه را اجرا می کنیم.

 

بدون Refresh صفحه

پرسش و پاسخ در تمرین بیست و یکم

اعتبارسنجی سمت کلاینت چگونه پیاده سازی می شود؟

همان طور که مشاهده نمودید، بدون هیچ تلاش اضافی اعتبارسنجی سمت کلاینت پیاده سازی می شود. در Login View، عناصر HTML با استفاده از کلاس های HTML helper تولید می شوند. توابع Helper زمانی که تگ های HTML را تولید می کنند برخی صفات مبتنی بر Data Annotation را نیز اضافه می کنند.

مثال:

@Html.TextBoxFor(x=>x.UserName)

@Html.ValidationMessageFor(x=>x.UserName)

 

کد بالا، HTML زیر را تولید می کند.

<input data-val="true" data-val-length="UserName length should be between 2 and 7" data-val-length-max="7" data-val-length-min="2" id="UserName" name="UserName" type="text" value="" />
<span class="field-validation-error" data-valmsg-for="UserName" data-valmsg-replace="true"> </span>

 

این صفات سفارشی HTML توسط فایل های اعتبارسنجی jQuery Unobtrusive استفاده می شوند و بنابراین اعتبارسنجی سمت کلاینت به صورت اتوماتیک پیاده سازی می شود.

اعتبارسنجی اتوماتیک سمت کلاینت، دومین مزیت استفاده از کلاس های HTML Helper می باشد.

Unobtrusive JavaScript به چه معناست؟

متن زیر، توضیحی است که Wikipedia درباره آن می گوید:

 

Unobtrusive JavaScript یک روش عمومی برای استفاده از جاوااسکریپت در صفحات وب می باشد. اگرچه این اصطلاح به طور رسمی تعریف نشده است، اما اصول زیر به طور عمومی از آن استنباط می شود:

·         تفکیک کاربرد ساختار/محتوای یک صفحه سایت از نحوه ارائه و نمایش آن

·         بهترین راهکار جلوگیری از مشکلات برنامه نویسی جاوااسکریپت به روش قدیمی (مانند تناقض های موجود در مرورگر، عدم مقیاس پذیری)

·         ارتقای درحال پیشرفت برای پشتیبانی از کاربرانی که ممکن است امکانات جدید جاوااسکریپت پیشرفته را پشتیبانی نکنند.

 

اجازه دهید که آن را به زبانی ساده تر بیان کنیم:

کدهای جاوااسکریپت خود را به روشی بنویسید که جاوااسکریپت، نتواند به طور مستقیم با HTML در ارتباط باشد. جاوااسکریپت ممکن است به عناصر DOM دسترسی داشته باشد، یا آن ها را دستکاری کند اما به طور مستقیم با آن ها در ارتباط نمی باشد.

در مثال بالا، jQuery Unobtrusive JavaScript به سادگی از برخی صفت های عناصر ورودی استفاده کرده و اعتبارسنجی سمت کلاینت را پیاده سازی نمود.

آیا می توانیم این اعتبارسنجی جاوااسکریپت را بدون کلاس های HTML Helper استفاده کنیم؟

بله، برای این کار باید صفات را به صورت دستی به عناصر اضافه کنیم.

کدام یک توصیه می شود، توابع Html helper یا HTML خالص؟

من شخصا HTML خالص را به توابع HTML helper ترجیح می دهم، چرا که همان طور که پیش از این بحث کردیم،  دوباره کنترل تام بر HTML را از ما می گیرد.

جمع بندی:

خب روز چهارم هم به این ترتیب به پایان رسید. در روز پنجم، کارهای پیشرفته تری که حتما برای شما جالب خواهد بود انجام می دهیم، پس با ما همراه باشید.

تمرین یادتون نره!

دانلود فایل PDF

فاطمه زکایی

فاطمه زکایی هستم. فارغ التحصیل کارشناسی مهندسی نرم افزار، مدت سه سال هست که در زمینه توسعه اپلیکیشن های تحت وب و اندروید و همچنین تولید محتوای تخصصی برنامه نویسی تحت وب و اندروید در مجموعه mspsoft در خدمت شما هستم.

نوشته‌های مرتبط

دیدگاه‌ها

*
*

این سایت از اکیسمت برای کاهش هرزنامه استفاده می کند. بیاموزید که چگونه اطلاعات دیدگاه های شما پردازش می‌شوند.

    یک برنامه نویس پاسخ

    سلام
    مرسی از آموزش های خوبی که گذاشتید. آموزش MVC6 رو کی میذارید؟
    میشه لطفاً برای این دروس امکان خروجی PDF هم قرار بدید؟

    با تشکر.

      باران بزرگمهر پاسخ

      خواهش میکنم.خیلی از این مباحث در نسخه های از MVC به صورت ثایت هستند.
      امکان خروجی نیز در حال پیاده سازی است.

    programmer پاسخ

    سلام
    ممنون یسیار عالی
    ممنون

      باران بزرگمهر پاسخ

      قربانه شما :)

    بصیرتی پاسخ

    سلام
    ممنون از مطلب
    من برای لاگین کردن مث شما کار کردم. اما مشکل اینجاس که وقتی یوزرنیم و پسورد اشتباه وارد میشه مجددا همون صفحه لاگین نمایش داده میشه و پیغام خطا هم نمایش داده میشه ولی url صفحه به آدرس /account/DoLogin تغییر کرده.
    چرا اینجوری میشه؟

    بصیرتی پاسخ

    و یه سوال دیگه:
    من فایل FilterConfig.cs رو به فولدر app_start اضافه کردم و کد شما رو قرار دادم داخلش ولی authorize انجام نمیشه. قبلا ابتدای هر کنترلرم این کارو کرده بودم و کار میکرد. ولی خواستم از روش شما برم جواب نمیده.