آموزش ASP.NET MVC5 – فصل۱ – بخش۳
آموزش ASP.NET MVC5 - فصل1 - بخش3 : در این مقاله، ارسال درخواست Http به سرور توسط متدهای Get و Post، تعریف دو اکشن با نام یکسان در یک کنترولر، مفهوم کش (Cache) در MVC5، تشخیص هویت کاربران توسط اتریبیوت Authorize، نوع داده‌ای JSON بعنوان خروجی اکشن و نحوه تعریف لینک دانلود در MVC را آموزش می دهیم.

آموزش MVC –> جلسه اول –> قسمت سوم

 

در بخش دوم از جلسه اول آموزش MVC مواردی مانند: شرایط اکشن بودن یک تابع، نحوه تغییر نام یک اکشن، تعریف خروجی رشته (string) برای اکشن، ریدایرکت از اکشنی به اکشن دیگر و غیره را بررسی کردیم. در این بخش ارسال درخواست Http به سرور توسط متدهای Get و Post، تعریف دو اکشن با نام یکسان در یک کنترولر و … را آموزش می دهیم.

 

ارسال درخواست Http به سرور توسط متدهای Get و Post

ورژن قبلی HTTP 1.0 بود که دو مدل مهم Request به سمت سرور داشت که Get و Post بود . ورژن حال حاضر HTTP 1.1 است که معروفترین Request های آن از سمت server عبارتند از : Get-Post-Put-Delete

 

ارسال Request به سرور به صورت Get:

چه مواقعی بصورت Get به سرور درخواست میفرستیم ؟

  • در مواقعی که آدرس سایت را بصورت دستی در نوار آدرس مرورگر وارد کرده و Enter را میزنیم .
  • وقتی روی یک لینک کلیک میکنیم و به سایت دیگری میرویم .
  • وقتی در تگ Form متد آنرا Get تعریف کنیم (بصورت پیش فرض Post می باشد) .

 

در مواقعی که در تگ فرم (Form) متد را بصورت پیش فرض Post قراردهیم و یک دکمه Submit داشته باشد و روی ان کلیک کنیم . اطلاعات فرم بصورت متد post به سرور ارسال میشود .

 

ویژگی‌های متد Get:

در HTTP 1.0 متد get دارای محدودیت ۲۵۵ کاراکتر دارد و بیش از ۲۵۵ کاراکتر را نمیتوان به سرور فرستاد .

در HTTP 1.1 محدودیت get به ۲۰۴۸ کاراکتر افزایش یافت ولی با اینحال توصیه نمیشود متد فرم (مثلا ثبت نام کاربران) را get قرار دهیم .

اگر متد فرمی را get قرار دهیم پس از submit کردن فرم و ارسال به سرور ، در آدرس بار مروگر تمام اطلاعات و فیلدهای پر شده کاربر نمایش داده می شود(بعنوان مثال https://mohtava.info/username=ehsan&password=12345) 

از این پس در این مقاله آموزشی ، در بالای هر اکشن متد ارسالی را به صراحت بیان میکنیم (بصورت Attribute)

اکنون به دو اکشن زیر دقت کنید :

 
[System.Web.Mvc.HttpGet]
public System.Web.Mvc.ContentResult Learn1230()
{
    return (Content("Hello World!"));
}
[System.Web.Mvc.HttpPost]
public System.Web.Mvc.ContentResult Learn1240()
{
    return (Content("Hello World!"));
}

در اکشن اول متد را get تعریف کرده ایم پس میتوان این اکشن را در آدرس بار مرورگر تایپ کنیم و نتیجه را ببینیم .

 

ارسال درخواست توسط متد Post:

در اکشن دوم متد بصورت post تعریف شده است بنابراین اگر آدرس آنرا (مثلا بصورت https://mohtava.info/Home/Learn1240) در آدرس بار تایپ کنیم با خطای Http Not Found مواجه می شویم . و برای اجرای این اکشن و تست آن باید حتما یک فرم طراحی کنیم که متد آن post باشد که بعد از submit کردن فرم به این اکشن بیاییم .

نکته : نوشتن هر دوی متدهای post و get بی معنی است . اگر Attribute را در بالای اکشن تعریف نکنیم ، پیش فرض آن get است .برای آشنایی بیشتر با متدهای get و post به وب سایت mvc4beginner مراجعه شود .

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

 

تعریف دو اکشن با نام یکسان در یک کنترولر

 

دو تابع با نام یکسان و پارامتر ورودی متفاوت:

در مبحث Object Oriented میتوان دو تابع تعریف کرد با نام یکسان و Signature (پارامتر ورودی) متفاوت . اما در MVC اگر دو اکشن زیر را تعریف و اجرا کنیم پیغام خطا میدهد :

 
[System.Web.Mvc.HttpGet]
public System.Web.Mvc.ActionResult Learn1270()
{
    return (Content("Hello World!"));
}
[System.Web.Mvc.HttpGet]
public System.Web.Mvc.ActionResult Learn1270(string name)
{
    return (Content("Hello World!"));
}

با اینکه اکشن دوم پارامتر ورودی میگیرد و اکشن اول پارامتری ندارد اگر در مرورگر آدرس زیر را وارد کنیم خطا میدهد چون مشخص نیست اکشن اول را صدا زدیم یا دوم را !

http://Mohtava.info/Home/Learn1270

 

تعریف اکشن ها بصورت Get و Post:

برای حل این مشکل یک روش اینست که یکی از اکشن ها را بصورت get تعریف کنیم یکی را post . بنابراین دو اکشن Learn1280 که در ذیل آمده با خطایی روبرو نمیشوند :

 
[System.Web.Mvc.HttpGet]
public System.Web.Mvc.ActionResult Learn1280()
{
    return (Content("[GET] Hello World!"));
}
[System.Web.Mvc.HttpPost]
public System.Web.Mvc.ActionResult Learn1280(string name)
{
    return (Content("[POST] Hello World!"));
}

 

استفاده از اتریبیوت ActionName:

روش دیگر اینست که با اتریبیوت ActionName نام اکشن دوم را تغییر بدهیم . در مثال زیر هم نام اکشن ها یکیست هم متدهای آنان . ولی با اتریبیوت مذکور مشکل را حل کرده ایم :

 
[System.Web.Mvc.HttpGet]
public System.Web.Mvc.ActionResult Learn1290()
{
    return (Content("[GET] Hello Ehsan !"));
}
[System.Web.Mvc.HttpGet]
[System.Web.Mvc.ActionName(“Learn_Mohtava”)]
public System.Web.Mvc.ActionResult Learn1290(string name)
{
    return (Content("[GET] Hello Safari !"));
}

برای کسب اطلاعات بیشتر به وب سایت asp.net مراجعه شود . در بخش بعد با مفهوم کش cache آشنا می شویم . 

 

مفهوم کش (Cache) در ASP.NET MVC5

 

کاربرد Cache در وب سایت:

سناریو : فرض کنید شما یک وب سایتی طراحی کرده اید که در صفحه آن تیتر روزنامه های کشور را نمایش میدهید و نیز وب سایت شما روزی یک میلیون نفر بازدیدکننده دارد . یعنی روزی یک میلیون بار باید به دیتابیس جهت بازیابی داده مراجعه شود .  با توجه به اینکه تیتر روزنامه ها هر صبح به صبح تغییر میکند و نیازی نیست که هر ثانیه آپدیت شود باید دستوری بنویسیم که هر روز صبح به دیتابیس مراجعه کند و دیتای لازم را fetch کند . در اینگونه موارد از مفهوم کش(caching) استفاده میکنیم .

 

افزودن Cache به اکشن در MVC :

بدین منظور باید یک اتریبیوت(Attribute) به بالای اکشن اضافه کنیم :

[System.Web.Mvc.OutputCache(Duration = 10)]

پارامتر Duration مدت زمان کش شدن به واحد ثانیه است . مثلا اگر میخواهیم هر یکساعت یکبار اطلاعات از دیتابیس خوانده شود باید ۲۴*۶۰*۶۰ ثانیه نوشته شود .

در مثال زیر هر ده ثانیه یکبار زمان نمایش داده شده در صفحه تغییر میکند(با refresh کاربر) یعنی در طول ده ثانیه ، کاربر هر چقدر صفحه را لود کند همان زمان قبلی را نشان میدهد :

 
[System.Web.Mvc.HttpGet]
[System.Web.Mvc.OutputCache(Duration = 10)]
public System.Web.Mvc.ContentResult Learn1330()
{
    string strContent =
        System.DateTime.Now.ToString("yyyy/MM/dd – HH:mm:ss");
    return (Content(strContent));
}

در صورتی که اکشن کش شده دارای پارامتر ورودی باشد ، به ازای هر پارامتر کش مجزا صورت میگیرد . مثال زیر را داریم :

 
[System.Web.Mvc.HttpGet]
[System.Web.Mvc.OutputCache(Duration = 120)]
public System.Web.Mvc.ContentResult Learn1340(int id)
{
    switch (id)
    {
        case 1:
        {
            return (Content("Hello World (1)!"));
        }
        case 2:
        {
            return (Content("Hello World (2)!"));
        }
        default:
        {
            return (Content("Hello World!"));
        }
    }
}

اگر اکشن بالا را با پارامتر ۱ صدا بزنیم تا دو دقیقه کش میشود و اگر با ۲ صدا بزنیم دو دقیقه جدا محاسبه میشود . بنابراین توصیه میشود اکشن هایی را کش کنیم که تعداد پارامتر محدودی دارند .

پاک کردن کش یک اکشن خاص :

در مثالی که زده شد ، فرض میکنیم در وسط یک روز خاص ، یک روزنامه به نشریات کشور اضافه شود . اگر با همان کش قبلی کار کند تا فردای آنروز تیتر آن روزنامه در وب سایت ما نمایش داده نمیشود . روش ناقص و پر خطر برای حل این مشکل اینست که کش IIS را پاک کنیم . این روش کار/امد نیست چون در لحظه پاک شدن کش IIS هر کاربری که لاگین است و در حال کار با سایت است را LogOut میکند و نیز تمام کش های اکشن های دیگر را هم از بین میبرد . پس اصلا توصیه نمیشود . روش موثر و مفید برای پاک کردن کش اینست که فقط کش آن اکشن مربرط به نمایش تیتر روزنامه های کشور را پاک کنیم تا همان لحظه به دیتابیس برود و اطلاعات روزنامه جدید را نیز بخواند و نمایش دهد .

 

استفاده از دستور RemoveOutputCacheItem:

این روش در اکشن زیر نشان داده شده است :

 
[System.Web.Mvc.HttpGet]
public void Learn1360()
{
    string strUrl =
        Url.Action(actionName: "Learn1350");
    Response.RemoveOutputCacheItem(strUrl);
}

دستور RemoveOutputCacheItem باید در تمام متدهای Insert , Update , Delete مربوط به روزنامه ها نوشته شود .

برای تکمیل آموخته های خود درباره cashing in MVC به سایت مایکروسافت مراجعه نمایید .

در بخش بعد، با مبحثی بنام Authorize آشنا میشویم.

 

تشخیص هویت کاربران توسط اتریبیوت Authorize

 

کاربرد اتریبیوت Authorize:

اگر بخواهیم دسترسی به یک اکشن را برای کاربر یا کاربرانی محدود کنیم (پیام Access Denied بدهیم) باید از اتریبیوت Authorize استفاده کنیم . مثلا هنگامی که میخواهیم دسترسی کاربر را به صفحه مدیریت ببندیم . در اکشن زیر وقتی کاربر لاگین کرده باشد وارد اکشن میشود وگرنه او را به فرم لاگین هدایت میکند :

 
[System.Web.Mvc.HttpGet]
[System.Web.Mvc.Authorize]
public System.Web.Mvc.ContentResult Learn1380()
{
    return (Content("Hello World!"));
}

برای تعریف فرمی که کاربر به آن ریدایرکت میشود باید به فایل Web.config برویم و دستور زیر را در زیرمجموعه system.web بنویسیم :

<authentication mode="Forms">
   <forms loginUrl="~/Account/Login"/>
</authentication>

در loginUrl میتوان آدرس فرم موردنظر خود را بنویسیم .

 

بررسی نقش کاربر توسط Roles:

علاوه بر اتریبیوت Authorize مورد دیگری داریم بنام Roles که نقش کاربر را بررسی میکند . این مفهوم با مثال زیر واضح تر میشود :

 
[System.Web.Mvc.HttpGet]
[System.Web.Mvc.Authorize(Roles = "Supervisor,Manager")]
public System.Web.Mvc.ContentResult Learn1390()
{
    return (Content("Hello World!"));
}

به این معنی است که نه تنها کاربر باید برای دیدم اکشن Learn1390 لاگین کرده باشد بلکه باید رول یا نقش او هم یا Supervisor باشد یا Manager .

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

در بخش بعد با نوع داده ای Json آشنا می شویم .

 

نوع داده‌ای JSON بعنوان خروجی اکشن

 

تعریف فرمت Json در اکشن:

اگر بخواهیم نوع خروجی اکشن ما بصورت Json باشد یا باید بصورت دستی داده های موردنظرمان را به فرمت json در بیاوریم :

 
[System.Web.Mvc.HttpGet]
public string Learn1400()
{
    string strResult =
        "{\"FullName\":\"Ehsan Safari\",\"Age\":28}"; 
    return (strResult);
}

 

تعریف JsonResult قبل از نام اکشن:

بدین منظور باید بجای ActionResult یا ContentResult یا هر چیز دیگری ، قبل از نام اکشن بنویسیم JsonResult و در هنگام بازگرداندن خروجی (return) بعد از کلمه return کلمه Json و سپس پرانتز باز و بسته را مینویسیم و سپس داده یا داده هایی که میخواهیم بفرستیم را بصورت شئ مینویسیم :

 
[System.Web.Mvc.HttpGet]
public System.Web.Mvc.JsonResult Learn1410()
{
    return (Json(new { FullName = "Ehsan Safari", Age = 28},
        System.Web.Mvc.JsonRequestBehavior.AllowGet));
}

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

در بخش بعد با نحوه چگونگی دانلود فایل در MVC آشنا می شویم.

 

چگونگی دانلود فایل در MVC

 

قرار دادن لینک دانلود یک فایل در ASP.NET MVC:

به منظور قرار دادن لینک دانلود یک فایل روش اول اینست که میتوانیم آدرس فایل را مستقیما با لینک بدهیم و کاربر با کلیک کردن روی آن ، آنرا دانلود کند . بعنوان مثال فایل مربوطه در فولدر Uploads قرار دارد و نام فایل هم myFile.pdf می باشد :

http://Mohtava.info/Uploads/myFile.pdf

کاربر با نوشتن این آدرس در مرورگر میتواند آنرا بطور مستقیم دانلود کند و این امر از لحاظ امنیتی اصلا جالب نیست .

 

برقراری امنیت فایل دانلودی در MVC:

بنابراین باید فایلهای مهم (اعم ازعکس-داکیومنت-ویدیو یا غیره) را که کاربرعادی نباید آنها را ببیند و یا بابت آنها باید هزینه ای پرداخت کند را داخل فولدر App_Data بریزیم (چرا که فولدر مذکور یک فولدر امن است و دات نت Security محافظ آن است )

بعنوان مثال در اکشن زیر داریم :

 
[System.Web.Mvc.HttpGet]
public System.Web.Mvc.FileResult Learn1420()
{
    // شرایط دریافت فایل
    string strRootRelativePathName =
        "~/App_Data/Images/EhsanSafari.jpg";
    string strPathName =
        Server.MapPath(strRootRelativePathName);
    return (File(strPathName, contentType: "image/jpeg"));
}

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

 

تعریف File بعنوان خروجی اکشن:

خروجی اکشن باید File باشد و قبل از نام اکشن نیز باید FileResult بنویسیم . در هنگام return دستور زیر را داریم :

 return (File(strPathName, contentType: "image/jpeg"));

پارامتر اول آدرس فیزیکی فایل مربوطه است و پارامتر دوم نیز نوع داده فایل دانلودی است .

با اجرای اکشن فوق ، تصویر مربوطه در مرورگر نمایش داده میشود ولی اگر بخواهیم پس از اجرای اکشن مذکور پنجره Save As ظاهر شود باید contentType آنرا مقداری بنویسیم که نا مفهوم باشد از نظر دات نت !

 
[System.Web.Mvc.HttpGet]
public System.Web.Mvc.FileResult Learn1440()
{
    // شرایط دریافت فایل
    string strRootRelativePathName =
        "~/App_Data/Images/Ehsan.jpg";
    string strPathName =
        Server.MapPath(strRootRelativePathName);
    return (File(strPathName, contentType: "salam/chetori"));
}

 

تعریف پارامتر fileDownloadName:

در این حالت فایل با موفقیت دانلود میشود ولی نام فایل دانلود شده همان نام اکشن میشود . برای رفع این مشکل باید به پارامتر fileDownloadName نیز مقدار بدهیم :

 
[System.Web.Mvc.HttpGet]
public System.Web.Mvc.FileResult Learn1450()
{
    // شرایط دریافت فایل
    string strRootRelativePathName =
        "~/App_Data/Images/Safari.jpg";
    string strPathName =
        Server.MapPath(strRootRelativePathName);
    return (File(strPathName, contentType: "googooli/magooli", fileDownloadName: "EhsanSafari.jpg"));
}

این اکشن تقریبا کامل است و می توانید برای قرار دادن امکان دانلود فایل ها در وب سایتتان از آن استفاده کنید .

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

در این قسمت ، جلسه اول از آموزش MVC به پایان میرسد . لطفا با بیان دیدگاه های خودتان درباره نحوه آموزش و کیفیت آن ، ما را بیشتر از پیش مشتاق به ادامه فعالیت و آموزش کنید winksmiley


برچسب‌ها:

GetPostrequestاتریبیوت ActionNameاتریبیوت Authorizeپارامتر fileDownloadNameپاک کردن کشپروتکلتعریف JsonResultخروجی JSONدانلود فایل در MVCدرخواست httpدو اکشن با نام یکسانکش در MVCمتدمتدهای Get و Postمفهوم کش



دیدگاه‌ها :