امیر مددی
تماس با من
پروفایل من
نویسنده (های) وبلاگ امیر مددی
آرشیو وبلاگ
      بازار آی تی (این وبلاگ آینه ای از وبلاگ اصلی من در بلاگر (itbazaar.blogspot.com) در زمینه برنامه نویسی تحت وب است که بدلیل مشکلات فیل‌ترینگ در پرشین بلاگ نیز کپی شده است.)
سایر نوشته های من

 

 


آموزش MVC
Model - View - Controller

MVC3 آخرین تکنولوژی مایکروسافت در زمینه تولید صفحات وب (تا این لحظه ، یعنی مارچ 2011) می باشد که کم کم جایگزین روش قبلی تولید صفحات وب (Web Forms) می شود و جالب اینجاست که به شدت از سوی مایکروسافت تبلیغ می شود و منابع آن به سرعت انتشار می یابند. این تکنولوژی که در حال حاضر نسخه 3 آن منتشر شده است دارای مزیتهای زیر نسبت به تکنولوژی قبلی (Web Forms) می باشد(در واقع موارد ذیل مشکلات وب فرمها هستند).

  • در وب فرمها ، برنامه نویس کنترل زیادی روی خروجی HTML تولید شده توسط ASP.NET ندارد و اگر شما سورس کد صفحه را ببینید ، شاهد کد HTML شلوغی هستید که مشکل می توانید از آن سر در بیاورید
  • در وب فرمها با رد و بدل شدن ViewState در هنگام ارسال به سرور ، حجم آن زیاد می شود و صفحه به اصطلاح پف می کند 
  • ایجاد واحد تست (Unit Test) در وب فرمها مشکل است 
  • چرخه رد و بدل شدن فایل بین کلاینت و سرور پیچیده است

 تکنولوژی MVC تمام مشکلات فوق را حل می کند و مزایایی نیز دارد از جمله :

  • Method Request است یعنی شما می توانید به جای فراخوانی کل یک صفحه ، یک متد را فراخوانی کنید
  • Partly Open Source است . یعنی بخشی از کدهای اصلی آن "باز" است و می توانید تحت استاندارد نرم افزارهای متن باز ، آن را ویرایش کنید

من در ابتدا تصمیم داشتم که در 5 الی 6 مقاله کل مبحث را خلاصه کنم ولی ترجیح دادم تا به جای آن ، بصورت گام به گام یک پروژه MVC را شروع کنم و در طی آن مطالب جدید را بیان کنم. اما قبل از شروع :

- نصب برنامه :

 MVC2 در ویژال استودیو 2010 نگارش Ultimate از پیش نصب شده است ولی اگر بدنبال نصب MVC3 هستید ، از آدرس http://www.microsoft.com/web  ابزار WebMatrix را نصب کنید. این ابزار پس از نصب ، پنجره Web Platform Installer 3 را در اختیار شما می گذارد که نه تنها می توانید MVC3 را نصب کنید ، بلکه می توانید برنامه های مفید دیگه ، مثل تنظیمات توصیه شده مایکروسافت برای IIS7 یا موتور (engine) بسیاری از CMS های معروف مثل DotNetNuke ، Drupal , Joomla , Umbarco را نیز نصب کنید (یکی به عجایب هفت گانه دنیا اضافه شده !!!)

- مبانی MVC:

من چون نمی خواهم خیلی وارد مباحث تئوریک شوم بصورت خلاصه توضیح می دهم و زمانی که پروژه را شروع کردیم ، خودتان این مفاهیم را بهتر متوجه می شوید . برای شروع از MVC2 آغاز می کنیم و پس از طرح مباحث اصلی MVC3 را نیز شرح می دهم .

در MVC سه جزء اصلی وجود دارد :

  • Model
  • Controller
  • View

Model کلاسهایی برای ارتباط با دیتابیس و استفاده از تکنیک هایی مثل Linq و Entity Framework هستند

Controller قلب MVC است و کنترل کننده درخواستهای کاربر است ، کلاسهایی هستند که در آنها ، متدهای (اکشن های) مختلف جهت پاسخگویی به درخواست کاربر و انتخاب Model و یا View (خروجی) مناسب ، وجود دارد.

View رابط کاربری است یعنی آنچه کاربر باید ببیند را در آن نمایش می دهیم.

- ایجاد پروژه جدید : برای ایجاد پروژه جدید مطابق معمول از منوی File ویژال استودیو ، گزینه New و سپس Project را انتخاب کنید و سپس یکی از قالبهای زیر را انتخاب کنید :

  • ASP.NET MVC2 Web Application
  • ASP.NET MVC2 Empty Web Application

(البته اگر MVC3 را نصب کرده باشید ، MVC3 را هم می بینید) تفاوت دو قالب فوق در این است که اولی شامل یک سری الگوهای آماده ، مثل Membership دات نت فریم ورک ، مراجع Jquery ، کلاسهای CSS از پیش ساخته شده است ولی دومی (Empty) اینها را ندارد و خودتان باید آنها را اضافه کنید برای شروع ، قالب اول را انتخاب کنید، نام و مسیر مناسبی برای آن انتخاب کنید و پروژه را ایجاد نمایید ، از شما سوال می شود که آیا تمایلی به ایجاد واحد تست دارید یا خیر (که من برای شروع خیر را انتخاب می کنم، توی شکل زیر Yes انتخاب شده !) :



پس از ایجاد باید شکل Solution Explorer شما به صورت زیر باشد :



 همانطور که می بینید پوشه های مجزایی برای هر دسته از فایلها وجود دارد : مثل Controller , View , Model , ... پوشه Script شامل فایلهای جاوا اسکریپت و Jquery و MicrosoftAjax است . پوشه Conetnt هم محلی برای نگهداری فایلهای CSS و تصاویر است. اگر برنامه را اجرا کنید (F5) باید صفحه ای آبی رنگ با پیام Welcome to ASP.NET MVC! مشاهده کنید.

برای شروع کار فایل HomeController.cs از فولدر Controllers را باز کنید . کدهای زیر را در آن می بینید :

namespace _30Sharp_com_MVC.Controllers
{
    public class HomeController : Controller
    {
        [HandleError]
        public class HomeController : Controller
        {
            public ActionResult Index()
            {
                ViewData["Message"] = "Welcome to ASP.NET MVC!";

                return View();
            }

            public ActionResult About()
            {
                return View();
            }
        }

    }
}

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

هر فایل از نوع Controller با کلمه دلخواهی شروع می شود و بدنبال آن کلمه Controller می آید و این نام دلخواه در URL سایت تاثیر می گذارد . قالب URL در MVC به فرم زیر است :

Web site address/Controller/Action

اکشن / کنترلر / آدرس اصلی سایت

برای مثال برنامه را اجرا کنید ، روی لینک About  کلیک کنید و URL صفحه را ببینید ، چیزی شبیه این می بینید (به جز شماره پورت که متفاوت است)

http://localhost:34256/Home/About

به متدها و رخدادهای صفحه در ام وی سی ، Action می گویند و در هر کنترلر می توانید چندین اکشن بیاورید و یا Overload کنید خروجی اکشن ها ، به صورت پیش فرض ActionResult است ولی می تواند هر نوع دیگری باشد (مثلا string) . در یک کنترلر شما ممکن است چندین اکشن داشت که برای هر اکشن یک View ایجاد می کنید و در آن ، مشخص می کنید که کاربر چه خروجی را باید مشاهده کند . برای مثال زیر اکشن About ، من اکشن دیگری به نام Contact ایجاد می کنم و در آن اطلاعات خود را در Message ذخیره می کنم :

public ActionResult Contact()
{
    ViewData["Message"] = "My Email : Amir.Madadi@hotmail.com and My Contact is 0422760153";
    return View();
}


توضیح اینکه شئی ViewData از نوع دیکشنری است که در آن می توانید کلید تعریف کنید و به آن مقدار دهید که من در اینجا کلیدی یه نام Message تعریف کرده ام و اطلاعات تماس را درون آن ریخته ام .

حال باید برای این اکشن یک View ساخت تا مشخص کنیم کاربر چه چیزی را ببیند. برای این کار روی اکشن کلیک راست می کنیم و گزینه Add View را انتخاب می کنیم :

سپس پنجره زیر ظاهر می شود :

در مورد امکانات این پنجره بعدا صحبت می کنیم ، فعلا پیش فرضها را قبول کنید و روی Add کلیک کنید . خواهید دید که فایلی به نام Contact.aspx در فولدر View ایجاد می شود . در تگ Asp:Contect id="Content2" خط زیر را اضافه کنید :

<h2><%: ViewData["Message"%>h2>

کد صفحه Contact.aspx شما باید شبیه این باشد :



حال برنامه را اجرا کنید و بعد از شماره پورت تایپ کنید : Home/Contact/ یعنی چیزی شبیه این :

http://localhost:34256/home/contact

اگر متن تایپ شده را در صفحه می بینید، به خود تبریک بگویید ، چون اولین صفحه وب خود را با تکنولوژی MVC ساخته اید.

قبل از پایان ، نگاهی به ساب فولدرهای View بیندازید ، خواهید دید که به ازای هر Controller یک فولدر وجود دارد که در آن View های مربوطه نگهداری می شوند (در حال حاضر باید Account ، Home و Shared را ببینید) که فولدر Shared برای ذخیره کردن اجزای مشترک مثل Master Page ها استفاده می شود.

خب تا اینجای کار یک پروژه جدید MVC ایجاد کردیم ، کمی در مورد ساختار MVC صحبت کردیم و یک View جدید به پروژه اضافه کردیم . در مقاله بعدی صفحاتی با کارایی بیشتر ایجاد می کنیم، تا آن موقع مروری بر دانسته های خود درباره Linq to SQL داشته باشید ، چرا که بزودی از آن در صفحات Model استفاده می کنیم

 

------

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

- چرخه کار MVC :

به طور کلی فرآیند درخواست و پاسخ بین کلاینت و سرور در MVC به صورت زیر می باشد :

  1.  یک درخواست از طرف کاربر ( کلاینت ) به سرو ارسال می شود (مثل مشاهده یک صفحه یا یک رویداد خاص مثل Button_click)
  2. بخشی از MVC که به آن موتور مسیر یاب ( Routing Engine ) می گویند، کنترلر متناسب با آن درخواست را پیدا می کند .
  3. اکشن متناسب با درخواست اجرا ( Invoke ) می شود و در صورت لزوم داده ها را از Model مناسب می خواند.
  4.  View متناسب با اکشن ، به همراه داده های خوانده شده از Model به سمت کاربر ارسال می شود .

پس به زبان ساده تر :

اگر قصد دارید در برنامه خود رویدادی مثل Button_Click  را فراخوانی کنید ، باید اول در کنترلر خود ، اکشنی را برای آن ایجاد کنید که این اکشن ممکن است داده ها را از کلاس ها یا از Model مربوطه بخواند. سپس برای این اکشن یک صفحه ( View ) مناسب ایجاد کنید. برای هر رویداد دیگری باید همین مراحل را تکرار کنید، یعنی صفحه ای که مثلا 5 دکمه دارد، باید یک کنترلر که درون آن 5 اکشن است و 5 view متناظر با آن داشته باشد و این به شما کمک می کند تا صفحات اختصاصی  ، کاراتر و خلوت تری داشته باشید.

 برای اینکه قالبی که Routing Engine از آن استفاده می کند را ببینید ، فایل Global.asax.cs را از درون Solution Explorer خود باز کنید و به بخش RegisterRoutes آن توجه نمایید. قالب URL  و اینکه کدام پارامترها اختیاری ( Optional ) هستند ( در اینجا id ) مشخص شده است :

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default"// Route name
        "{controller}/{action}/{id}"// URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );

}

اما مثالهای عملی :

مثال اول: در این مثال ، چند اکشن مختلف با پارامتر و بدون پارامتر آورده شده تا تاثیر آن را در URL صفحه ببینید. در این مثال چون خروجی اکشن ها از نوع string است نیازی  به ساختن View نیست . برای اینکار با کلیک راست روی فولدر Controller یک کنترلر جدید به نام SecondController ایجاد کنید : 

سپس در این کنترلر ، سه اکشن زیر را ایجاد کنید :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace _30Sharp_com_MVC.Controllers
{
    public class SecondController : Controller
    {
        //          // GET: /Second/ 
        public string Index()
        {
            string message = "hello !";
            return Server.HtmlEncode(message);
        }
        public string testAction(string id)
        {
            string message = "Hello " + id;
            return Server.HtmlEncode(message);
        }
        public string SayHello(string name)
        {
            string message = "Say hello to: " + name + " " + Server.HtmlEncode(Request.QueryString["family"]);
            return Server.HtmlEncode(message);
        }
    }
}

در هنگام نوشتن اکشن ها به خروجی اکشن و پارامترهای آن توجه کنید. در اکشن Index فقط یک متن ساده نوشته شده است. در اکشن دوم، متغیر id از ورودی خوانده می شود و به همراه پیام نمایش داده می شود . در اکشن سوم علاوه بر متغیر name متغیر دیگری از طریق QueryString خوانده می شود.

 در اینجا چون خروجی یک رشته ساده است ، View برای آن تعریف نمی کنیم و خروجی آن را از طریق خط آدرس URL مشاهده می کنیم ( به ترتیب خروجی اکشن اول تا سوم )

( فالب آدرس را که فراموش نکرده اید : ControllerName/ActionName/Parameter )

نکته : در این مورد چون نام اکشن Index است ( پیش فرض ) ، نیازی به تایپ آن نیست

مثال 2 : در این مثال چگونگی انتقال یک list از نوع string را به View ( خروجی ) خواهیم دید. برای این کار ابتدا مانند مثال قبل یک Controller جدید به نام ThirdCintroller ایجاد کنید و درون آن لیستی از نوع string ایجاد کنید و مقدار دهی کنید :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace _30Sharp_com_MVC.Controllers
{
    public class ThirdController : Controller
    {
        //          // GET: /Third/  
  
        public ActionResult Index()
        {
            List<string> StudentName = new List<string> { "Houman""Amir""Neda" };
            ViewData["SName"] = StudentName.ToList();
            return View();
        }
    }
}

سپس برای آن یک View جدید ایجاد کنید ، یعنی روی نام اکشن ( Index ) کلیک راست کنید و Add view را انتخاب و گزینه های پیش فرض را بپذیرید :

سپس در صفحه ایحاد شده ، کد زیر را وارد کنید :

<asp:content id="Content2" contentplaceholderid="MainContent" runat="server">
        <h2>Indexh2>
              <% foreach (var s in (IEnumerable)ViewData["Sname"]) { %>
                    <%: s%> 
                    <br />  
              <% } %>  
asp:content>

همانگونه که مشاهده می کنید ، در کد فوق ، یک حلقه foreach وجود دارد که لیست ذخیره شده در متغیر Sname را می خواند ، آن را به نوع IEnumerable تبدیل می کند و چاپش می کند .

توضیح اینکه علامت :%> را وفتی بکار می بریم که بخواهیم مقداری را چاپ کنیم ( در اینجا مقدار s ) . خروجی بصورت زیر خواهد بود :

3- خب برای تمرین مطالب بیان شده ، مثال بعدی را خودتان بنویسید . سعی کنید در یک کنترلر جدید ، با مقدار دادن به یک متغیر از نوع list در هنگام چاپ ، طول رشته را هم چاپ کنید .

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

 لطفا برای ارتقای کیفی این سری از مقالات ، نظرات خود را ارسال فرمایید.

 

---

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

در بخش دوم درباره چگونگی نوشتن چند اکشن در یک کنترلر و ارتباط آن با URL صفحه دیدید، در این بخش درباره Model و نحوه استفاده از آن صحبت می کنیم.

- Model

مدل در MVC  ، محلی برای ایجاد کلاسهای مرتبط با بانک اطلاعاتی است. در مدل ها نیز می توانید از تمام الگوهای ارتباط با بانک اطلاعاتی مثل Linq یا Entity Framework استفاده کنید.

برای اینکه بتوانیم مثالی از Model  ها بیاوریم ، ابتدا یک بانک اطلاعاتی SQL  با یک جدول ساده شامل فیلدهایی مثل نام ، فامیل و سن ایجاد کنید ، یعنی باید جدولی به فرم زیر داشته باشیم :

سپس برای ارتباط با بانک اطلاعاتی یک DataContex از نوع Linq to SQL ایجاد می کنیم . برای این کار روی Solution خود کلیک راست کرده و از قسمت Data گزینه Linq to SQL را انتخاب کنید :

سپس جدول ساخته شده در بانک اطلاعاتی را به داخل آن Drog&Drop کنید :

و Solution را Build کنید.

حال در Solution Explorer روی Controllers کلیک راست کرده و یک کنترلر جدید ایجاد می کنیم و نام آنرا PersonController می گذاریم و کد زیر را درون آن وارد می کنیم:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using _30Sharp_com_MVC.Models;

namespace _30Sharp_com_MVC.Controllers
{
    public class PersonController : Controller
    {
     
        MVCDataContexDataContext db = new MVCDataContexDataContext();
        public ActionResult Index()
        {
            var list = (from m in db.Persons select m ).ToList();
            return View(list);
        }

    }
}

همانطور که می بینید در این کنترلر یک نمونه از شئی Data Context با نام db ایجاد کرده ایم و سپس با استفاده از Linq to Sql لیست کلیه سطرهای جدول Person را استخراج کرده ایم . توجه نمایید که خروجی اکشن از نوع ActionResult() است که لیستی از جدول Person را به View ارسال می کند ( اگر در مفاهیم Linq to Sql مشکل دارید ، توصیه می شود که قبل از ادامه این مبحث آن را مطالعه کنید)

پس تا اینجا نتایج را به View ی مربوطه انتقال دادیم . خب زمان آن رسیده که View مناسب برای نمایش این فیلدها ایجاد کنیم . با کلیک راست روی اکشن Index گزینه Add view را انتخاب می کنیم و آنرا Index نام می نهیم. در هنگام ایجاد View به پارامترهایی که با فلش مشخص شده اند توجه فرمایید.

 کد View بصورت زیر ایجاد می شود :

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Index
asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>
        Indexh2>
    <table>
        <tr>
            <th>
            th>
            <th>
                ID
            th>
            <th>
                Name
            th>
            <th>
                Family
            th>
            <th>
                Age
            th>
        tr>
        <% foreach (var item in Model)
           { %>
        <tr>
            <td>
                <%: Html.ActionLink("Edit""Edit"new { id=item.ID }) %>
                |
                <%: Html.ActionLink("Details""Details"new { id=item.ID })%>
                |
                <%: Html.ActionLink("Delete""Delete"new { id=item.ID })%>
            td>
            <td>
                <%: item.ID %>
            td>
            <td>
                <%: item.Name %>
            td>
            <td>
                <%: item.Family %>
            td>
            <td>
                <%: item.Age %>
            td>
        tr>
        <% } %>
    table>
    <p>
        <%: Html.ActionLink("Create New""Create"%>
    p>
asp:Content>

همانگونه که مشاهده می کنید ، در کد فوق ، یک حلقه foreach وجود دارد که لیست ذخیره شده را چاپ می کند . اما چند نکته در مورد View فوق :

  1.  در خط اول می بینید که در Inherit نام جدول Person آورده شده و منظور این است که از Model استفاده شده در این صفحه از نوع Person می باشد. این خط به این دلیل ایجاد شده که در هنگام ایجاد این View ، در قسمت View data class گزینه _30Sharp_com_MVC.Person را انتخاب کرده ایم . اگر دیدید که چنین گزینه ای وجود ندارد ، دلیلش آن است که پروژه را Build نکرده اید.
  2.  در هنگام اضافه کردن View در قسمت View Content گزینه های دیگری مثل Create ، Delete ، Edit وجود دارد که با انتخاب هر کدام ، کد تولید شده در View متفاوت خواهد بود.
  3.  پس از اجرا برای دیدن خروجی به آدرس زیر بروید : 
    Localhost:0000/Person/index
    که به جای 0000 شماره پورتی که ویژال استودیو از آن استفاده می کند قرار می گیرد.
  4.  وقتی برنامه را اجرا کنید ، متوجه خواهید شد که لیست سطرهای جدول نمایش داده می شود ولی لینکهای Edit /Details/ Delete / و همچنین Create New کار نمی کند. چرا؟ چون هنوز Action متناظر با آنها ایجاد نشده است .
  5. کلاس Html دارای متدهای مختلفی است از جمله ActionLink که برای لینک دادن بکار میرود . و دارای 10 حالت مختلف ( Overload ) است که در این حالت یعنی :
<%: Html.ActionLink("Create New""Create"%>

پارامتر اول متن لینک و پارامتر دوم نام Action ی است که اجرا می کند.

در این جلسه با ایجاد Data Contex ، اولین کوئری ارتباط با بانک اطلاعاتی را نوشتیم و طبیعی است که می توانیم سایر کوئری های مورد نظر را بنویسیم و View متناظر با آنها را ایجاد نماییم. این کار را در جلسه آینده با ایجاد Action هایی برای Edit , Delete دنبال می کنیم .

 لطفا برای ارتقای کیفی این سری از مقالات ، نظرات خود را ارسال فرمایید.

--

 


در بخش سوم نحوه ایجاد یک مدل و برقراری ارتباط با دیتا بیس را دیدید و همینطور لیستی از اطلاعات درون جدول Persons را نمایش دادیم . در این جلسه می خواهیم نحوه ویرایش و حذف اطلاعات  را ببینیم :

- ویرایش و حذف اطلاعات

همانطور که دیدید پس از ایجاد یک لیست از جدول Person  ، در View ایجاد شده کد زیر را داریم که درواقع لینکی است به اکشن هایی که باید عملیات ویرایش و حذف را باید انجام دهند :

<td>
        <%: Html.ActionLink("Edit""Edit"new { id=item.ID }) %>
        |
        <%: Html.ActionLink("Details""Details"new { id=item.ID })%>
        |
        <%: Html.ActionLink("Delete""Delete"new { id=item.ID })%>
td>

پارامتر اول در دستور Html.ActionLink ، متن ظاهر شده برای لینک به صفحه مورد نظر است ( Edit ) . پارامتر دوم نام اکشنی است که آن عملیات را انجام می دهد ( Edit ) و پارامتر سوم مقداری است که در هنگام انتقال به آن اکشن پاس داده می شود ( id=item.ID )

پس در کنترلر PersonController اکشن Edit را بصورت زیر اضافه می کنیم :

public ActionResult Edit(int? id)

    Person CurrentPerson = (from m in db.Persons where m.ID == id select m).FirstOrDefault();
    return View(CurrentPerson);
}

به متغیر CurrentPerson دقت کنید، از نوع Person است ، یعنی از نوع آبجکتی که در هنگام ایجاد DataContex ، ویژال استودیو در فایل designer مربوطه ایجاد می کند. اگر می خواهید آن را ببیند کافیست روی آن اشاره کنید و کلید F12 را بزنید .

 سپس View مورد نظر برای ویرایش عضو را آماده می کنیم، روی اکشن Edit کلیک راست می کنیم و :

 

دقت کنید که تمام گزینه ها مانند شکل فوق انتخاب شده باشند. با این کار کد زیر توسط ویژال استودیو تولید می شود :

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
Inherits="System.Web.Mvc.ViewPage<_30Sharp_com_MVC.Person>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Edit
asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>
        Edith2>
    <% using (Html.BeginForm())
       {%>
    <%: Html.ValidationSummary(true%>
    <fieldset>
        <legend>Fieldslegend>
        <div class="editor-label">
            <%: Html.LabelFor(model => model.ID) %>
        div>
        <div class="editor-field">
            <%: Html.TextBoxFor(model => model.ID) %>
            <%: Html.ValidationMessageFor(model => model.ID) %>
        div>
        <div class="editor-label">
            <%: Html.LabelFor(model => model.Name) %>
        div>
        <div class="editor-field">
            <%: Html.TextBoxFor(model => model.Name) %>
            <%: Html.ValidationMessageFor(model => model.Name) %>
        div>
        <div class="editor-label">
            <%: Html.LabelFor(model => model.Family) %>
        div>
        <div class="editor-field">
            <%: Html.TextBoxFor(model => model.Family) %>
            <%: Html.ValidationMessageFor(model => model.Family) %>
        div>
        <div class="editor-label">
            <%: Html.LabelFor(model => model.Age) %>
        div>
        <div class="editor-field">
            <%: Html.TextBoxFor(model => model.Age) %>
            <%: Html.ValidationMessageFor(model => model.Age) %>
        div>
        <p>
            <input type="submit" value="Save" />
        p>
    fieldset>
    <% } %>
    <div>
        <%: Html.ActionLink("Back to List""Index"%>
    div>
asp:Content>

بگذارید کمی بیشتر این فایل را بررسی کنیم :

  1.  دقت کنید که این فایل در حال حاضر فقط اطلاعات کاربر ویرایش شده را نشان می دهد و در صورت کلیک روی Save ، اطلاعات را ذخیره نمی کند ، مگر اینکه اکشن Save را نیز بنویسیم . می بینید که در MVC برای هر کاری باید اکشن جداگانه نوشت ، برای نمایش سطرهای جدول ، نمایش یک رکورد، جهت ویرایش ، ذخیره تغییرات و هر عملیات دیگری یک اکشن جداگانه نیاز است.

  2.  عبارت Html.BeginForm بیانگر ایجاد فرمی برای نمایش اطلاعات و ارسال تغییرات به اکشنی که باید تغییرات را ذخیره کند ، می باشد . این سطر را بزودی تغییر می دهیم تا نام اکشن مربوط به ذخیره اطلاعات را مشخص نماییم .

  3.  کلاس Html دارای متدهای زیادی می باشد از جمله : 

    برای نمایش خطاهای ورود اطلاعات Html.ValidationSymmary
    جهت نمایش نام یک فیلد ( دقت کنید : نام ، نه مقدار ) با پارامتر متنی Html.Label
    جهت نمایش نام یک فیلد ، با نگارش Lambda Html.LabelFor
    برای نمایش یک مقدار در TextBox Html.TextBox
    برای نمایش یک مقدار در TextBox با نگارش Lambda Html.TextBoxFor
    نمایش خطای ورود اطلاعات برای یک فیلد (نگارش Lambda  ) Html.ValidationMessageFor

     

در مثال زیر تفاوت استفاده از متدهایی که فقط در یک For با هم تفاوت دارند را می بینید ، هر دو یک عمل را نشان می دهند فقط نحوه نگارش متفاوت است :

Html.TextBoxFor(model => model.Name)

در اینجا نام TextBox بصورت اتوماتیک تولید می شود


 Html.TextBox("txtName" , Model.Name )

در اینجا پارامتر اول نام TextBox است

برای مطالعه در مورد شیوه نگارش در Lambda Expression به لینک زیر مراجعه نمایید :

http://msdn.microsoft.com/en-us/library/bb397687.aspx

خب حال باید تغییراتی در Html.BeginForm بدهیم تا پس از ویرایش اطلاعات و کلیک روی دکمه Save فرم به اکشن مورد نظر ( Save ) ارسال شود :

Html.BeginForm("Save""Person"FormMethod.Post)

این تغییر اطلاعات را به اکشن Save از کنترلر Person ارسال می کند . پس باید اکشن جدید Save  را نیز ایجاد کنیم :

public ActionResult Save(FormCollection form)
{
    int id = Int32.Parse(form["id"]);
    var EditPerson = (from m in db.Persons
                        where m.ID == id
                        select m).FirstOrDefault();

    EditPerson.Name = form["Name"];
    EditPerson.Family = form["Family"];
    EditPerson.Age = Int32.Parse(form["Age"]);
    db.SubmitChanges(); return RedirectToAction("Index""Person");
}

خب ، در این اکشن نیز نکات جدیدی وجود دارد :

  1.  پارامتر دریافتی توسط اکشن Save  از نوع FormCollection است که در فضای نام System.Web.MVC تعریف شده است . و حاوی اطلاعات فرمی است که به آن ارسال شده است.
  2.  برای دریافت اطلاعات تغییر یافته در فرم از form استفاده می کنیم و نام فیلد مورد نظر را بدان پاس می دهیم مثل :

    form["Name"]
  3. برای ذخیره تغییرات از db.SubmitChanges استفاده کردیم . ( Linq to SQL )
  4.  بعد از ذخیره می خواهیم مجددا لیست رکوردهای جدول را نمایش دهیم تا از انجام تغییرات مطمئن شویم ، برای این کار از دستور RedirectToAction استفاده شده است که پارامتر اول نام اکشنی است که باید اجرا شود و پارامتر دوم نام کنترلر است .

حال سعی کنید اکشن Delete  را خودتان بنویسید . به چه چبزهایی نیاز دارید ؟ یک اکشن که id رکورد را دریافت کند و با استفاده از Linq to sql ، دستور حذف را در آن بنویسید.

در این جلسه با نحوه ویرایش یک رکورد از بانک اطلاعاتی آشنا شدیم . در جلسه آینده در مورد امکانات جدید MVC 3 توضیح خواهم داد .

 

 

--


Razor ، ماژول (یا قطعه برنامه) جدید مایکروسافت برای استفاده از یک قالب جدید جهت نوشتن View  ها در 3 MVC  می باشد. درحال حاضر به طور پیش فرض از ماژول aspx/ascx  استفاده می شود، یعنی همانگونه که در مثالهای قبلی دیدید ، پسوند View ها مانند سایر صفحات وب قرم ها ، .aspx  یا .ascx بود. یکی از مشکلاتی که صفحات aspx/ascx  داشتند، سخت بودن نوشتن آنها زمان نوشتن کد بود ، مثلا کد زیر را از مثال قبلی که برای چاپ یک فیلد بود در نظر بگیرید : 

  

همانطور که می بینید قبل و بعد از هر فطعه کدی لازم است علامتهای   <% , %>  قرار داده شود واین در بسیاری از مواقع خیلی گیج کننده خواهد شد.

در Razor  فقط کافیست قبل از متغیر یا قطعه کد مورد نظر یک علامت @ قرار داد و سایر بخشهای غیر کد (یعنی HTML) بصورت عادی و مشابه قبل نوشته می شوند . قطعه فوق در صورت استفاده از Razor  بصورت زیر در می آید :

که ملاحظه می کنید که چقدر ساده تر خوانده می شود. 

به طور کلی Razor  مزیتهای زیر را نسبت به aspx/ascx دارد : 

  •  فشرده ، واضح و روان است
  •  یادگیریش ساده است
  •  یک زبان جدید نیست 
  •  با هر ادیتور متنی کار می کند
  •  قابلیت Intellisense استفاده می کند
  • قابلیت تست دارد

برای استفاده از Razor  کافیست هنگام ایجاد View گزینه Razor  را انتخاب کنید : 

 

 پسوند صفحات Razor  اگر از زبان #C استفاده می کنید csHtml و اگر از زبان VB  استفاده  می کنید vbHtml  می باشد.

چند مثال از Razor : 

در aspx/ascx می نویسیم:

Hello  <%=name %> . the year is   <%= DateTime.Now.Year  %>

در Razor  می نویسیم: 

Hello  @name,  the year is   @DateTime.Now.Year

در Razor  برای نوشتن  ایمیل ، چون ایمیل خودش یک علامت @ دارد باید یکی دیگر نیز اضافه کرد : 

My email address is  Madadi@@inbox.com

چگونه از MasterPage  در صفحات Razor استفاده کنیم : 

ابتدا فایلی که قصد دارید بعنوان MasterPage باشد را ایجاد نمایید و نامی دلخواه برایش انتخاب کنید ، مثلا SiteMaster.csHtml ، این فایل می تواند شامل عناصر Html  و مکانی برای نمایش سایر صفحاتی باشد که از آن استفاده می کنند ، یعنی به جای تگ  asp:ContentPlaceHolder  که در فایلهای قدیمی aspx/ascx استفاده می شد ، تنها عبارت RenderBody@  را بنویسید: 

 

حال در صفحه ای که  قصد دارید  از این قالب استفاده کنید ، عبارت 

@{ LayoutPage=”SiteMaster.cshtml”;  }

و در این صفحه با قالب Razor  کدهای خود را بنویسید: 

 

همچنین می توانید Title  صفحه خود را نیز با عبارت زیر بعد از LayoutPage  مشخص کنید :

View.Title= “product Page” ;

در صورتی که بخواهیم به فایل MasterPage  خود ، مکانی دیگر ، مثلا برای اضافه کردن منو ، درنظر بگیریم یا بعبارتی یک placeholder  دیگر اضافه کنیم ، این کار را با استفاده از @RenderSection انجام می دهیم :

@RenderSection(“menu” , optional:true )

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

کد زیر صفحه ای است که دارای دو بخش اضافه شده به نامهای menu  و footer  است . 

حال در صفحه ای که قرار است محتویات menu  را نشان دهیم، با عبارت  Section@  آن را مشخص می کنیم : 

  

در MVC  استفاده زیادی از کلاس Html Helper  می شود که  Razor  به خوبی از پشتیبانی می کند و می توان براحتی از آن استفاده کرد مثل :

@Html.LabelFor(item => item.Name)

@Html.TextBox(“txtFamily” )

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

برای Razor  در اینترنت مثالهای بسیار زیادی دارد که با یک جستجوی ساده می توان آنها را پیدا کرد از جمله مثالهای خوب به این مثال توجه کنید.

http://haacked.com/archive/2011/01/06/razor-syntax-quick-reference.aspx

چند نکته مهم :

1-      دقت داشته باشید که وقتی یک پروژه از نوع MVC  ایجاد می کنید ، فایلی به نام _Layout.cshtml  در مسیر Views/Shared بعنوان MasterPage  پیش فرض در نظر گرفته شده است که در صورتی که بخواهید آن را تغییر دهید باید فایل  _ViewStart.cshtml  را در مسیر ریشه فولدرViews باز کنیم و در عبارت layout  نام فایلی که می خواهیم MasterPage باشد را مشخص نماییم. 

2-اگر View  جدیدی ایجاد کردید و تصمیم داشتید که یک خروجی از داده های استخراج شده از جدولی در بانک اطلاعاتی را در آن نشان دهید ، باید در ابتدای فایل View  خود Model  داده خود را که از Action  مورد نظر به این View  انتقال می دهید ، مشخص نمایید . مثلا فرض کنید شما در پروژه ای به نام Sample یک کلاس ( یا همان Model  ) به نام Category  ساخته اید و در Action آن را خوانده و به View انتقال داده اید . در اینصورت برای چاپ سطرهای جدول ، (فیلد CategoryName ) در صورت مشخص کردن مدل قالب ، با یک حلقه ساده می توانیم این کار را انجام دهیم.  باید کد زیر را بنویسید : 

به مکان نوشتن کارکتر @ دقت کنید. 

شما می توانید برای تمرین پروژه قسمت چهارم را مجددا با Razor ایجاد نمایید.

 


اعتبار سنجی مدل با استفاده از DataAnnotaions
حتما به یاد دارید که در صفحات قدیمی aspx/ascx در ویژال استودیو، ابزارهای Validation وجود داشت مثل Asp:RequiredFieldValidator که باعث می شدند اطلاعات  وارد شده توسط کاربر ارزیابی شود و داده ها با قالب (فرمت ) صحیح برای ذخیره در بانک طلاعاتی ارسال شوند . این کار در MVC  با استفاده از Model Validation انجام می شود . در واقع با این کار، کنترل می کنیم که کاربران وقتی اطلاعاتی در فرم وارد می کنند، این اطلاعات از لحاظ قالب داده، صحیح باشند، مثلا ایمیل با فرمت صحیح وارد شود، جایی که قرار است عدد وارد ، حروف وارد نشود و .... 
در MVC اعتبار سنجی با استفاده از DataAnnoations  صورت می پذیرد. در واقع می خواهیم :  
1- اعتبارسنجی در هر دو سمت Server و Client انجام شود.
2- قاعده DRY  را رعایت کنیم ( Don't Repeat Yourself ) و این بدان معناست که کد ارزیابی را تکرار نکنیم، در یک جا بنویسیم و تمامی بخشها ( Controller ، Model و View ) آن را بپذیرند.
از آنجایی که در MVC برای هر فرمی ابتدا یک کلاس ایجاد می کنیم ، اعتبارسنجی نیز در هنگام ساختن Model ها (کلاس ها) ، اعمال می شود . برای این کار فضای نام ( name space ) زیر را به کلاسی که قصد داریم بسازیم اضافه می کنیم : 
using System.ComponentModel.DataAnnotaions;
 حال قبل از تعریف هر فیلد در مدل، ارزیابی خود را انجام می دهیم . متداولترین عبارتهای ارزیابی عبارتند از :
Required : مشخص می کند که ورود فیلد اجباری است 
Range: برای تعیین محدوده ای از اعداد 
StringLenght: برای تعیین طول یک رشته 
RegularExpression: برای ارزیابی عبارات منظم مثل ایمیل 
مثال زیر یک کلاس ساده را نشان می دهد که شامل نام ،فامیل ، سن و ایمیل است . 


در مثال فوق فیلدهای FirstName و LastName اجباری هستند و در صورت عدم ورود پیغامی مناسب نمایش داده خواهد شد و طول هر کدام حداکثر 50 کارکتر می تواند باشد. فیلد Ageنیز اجباری و بین صفر تا 120 می تواند باشد. فیلد ایمیل نیز اجباری و برای آن یک قاعده منظم تعریف شده است . (برای درک بهتر قواعد منظم این مقاله را بخوانید و یا #Regular Expression in C را جستجو کنید)
خروجی این فرم هنگامی که شما کاربر اطلاعات نامعتبر وارد می کند به شکل زیر است: 


اما کار دیگری که لازم است انجام شود این است که در Controller مربوطه ، در Action ی که قرار است اطلاعات ذخیره شود ، قبل از ذخیره اطلاعات ، بررسی شود که آیا اطلاعات وارد شده مطابق با مدل ( کلاس ) هست یا نه ؟ برای اینکار از شرط   (if(modelState.IsValid استفاده می کنیم. مثال زیر را ببینید: 


نکته جالب اینکه وقتی ما در مدل ، از اعتبارسنجی استفاده می کنیم ، در هنگام ساختن View از روی Model ( که به آن Strongly Type View می گویند ) ، به صورت اتوماتیک ، متد validationMessageFor از کلاس Html فراخوانی می شود که باعث چاپ همان پیغامی می شود که ما در مدل برای آن فیلد نوشته ایم : 


برای اجرای اعتبارسنجی در سمت Client  باید رفرنسهای MicrosoftAjax.js و MicrosoftMVCValidation.js را نیز به view  خود اضافه کنید : 


اعتبار سنجی سفارشی : 
بسیاری از اوقات لازم است که یک اعتبارسنجی سفارشی را پیاده سازی کنید که تا بتوانید فیلدی را آنگونه که می خواهید، بسنجید. برای این کار باید کلاسی از نوع اعتبارسنجی مورد نظر مشتق کنید و base constructor  آن را دوباره نویسی کنید. مثال زیر نحوه ارزیابی فیلد email  را توسط RegularExpression  بازتعریف می کند : 


نمایش ندادن یا تغییر نام برخی فیلدها : 
بسیاری از اوقات شما نمی خواهید در View  یک فیلد به کاربر نشان داده شود، مثلا اگر کاربری مشغول وارد کردن اطلاعات خود برای ثبت نام است،شما نمی خواهید اجازه دهید که فیلد Id  را خودش وارد کند ، چون باید توسط بانک اطلاعاتی تعیین شود. برای این کار در هنگام تعریف مدل ، آن فیلد (ها ) را با عبارت  [BindExclude="fieldName" ]  مشخص می کنیم و قبل از فیلد هم از عبارت [ScaffoldColumn(false)] استفاده می کنیم . 
گاهی اوقات نیز می خواهیم نام دیگری برای فیلد خود در هنگام نمایش در View  انتخاب کنیم . برای تغییر نام نمایشی فیلد از displayName استفاده می کنیم. مثال زیر از پروژه معروف Music Store  است که می توانید آن را بعنوان یک مثال خوب دانلود کنید و مطالعه نمایید.         


lazy-Load در EntityFramwork : 
اگر از Entityframework  برای ارتباط با بانک اطلاعاتی استفاده می کنید ، با اضافه کردن عبارت Virtual  به تعریف فیلد، امکان استفاده از lazy-load را در صورت نیاز فراهم می آوریم . (اگر از EntityFramework استفاده نمی کنید، از این قسمت صرفنظر کنید )

بسیار خوب، در این مقاله با روش اعتبارسنجی اطلاعات فرم آشنا شدیم. تقریبا تمامی پروژه های وب به این اعتبارسنجی ها نیاز دارند. به مثال Music Store  مایکرسافت نگاهی بیندازید و بخشهای مختلف آن را برای خود آنالیز کنید. 

--

--


Extension Methods :

قبل از هر چیز باید از تاخیر بوجود آمده در ارسال قسمتهای جدید عذر خواهی کنم و این نکته را متذکر شوم که در این قسمت سعی کرده ام از JQuery  و JSON  به عنوان مکملی برای MVC  استفاده کنم.  با یک جستجوی ساده در اینترنت خواهید دید که مثالی که در آخر این مقاله آمده است ، مورد سئوال در بسیاری از فارومهای معروف و بین المللی برنامه نویسی مثل StackOverFlow و ASP.Net بوده است که متاسفانه تا آنجا که من دیدم جوابهای مناسبی هم داده نشده بود.

همانطور که در بخشهای قبلی این سری مقالات دیدید، با استفاده از متدهای کلاس Helper  می توانید بسیاری از ابزارها یا عناصر Html ی مورد نیاز را استفاده کنید. مثال زیر  برای ایجاد یک لینک به کار می رود که متن آن Create  است و به اکشن  CreateUser لینک شده است  :

   @Html.ActionLink("Create""CreateUser ")
یا مثال زیر برای ایجاد یک CheckBox بکار می رود، نام آن cb1 است ، به طور پیش فرض تیک خورده و از کلاس class1 استفاده می کند: 
 @Html.CheckBox("cb1" , true , new {@class = "class1"}) 
 ، مثال زیر یک DropDownList است ، نامش ddl1 است. مقددار پیش فرض --select -- به آن اضافه شده و از کلاس class1 ( منظور کلاس استایل شیت ، Css است) استفاده می کند: 
  @Html.DropDownList("dd1","--Select--",new { @class="class1" }) 

بسیاری از نمونه های اینچنینی را  می توانید در این لینک ببینید.

اما مسئله ای که وجود دارد این است که در کلاس HtmlHelper متد یا متدهایی برای نمایش ابزارهایی که یک گروه از مقادیر را نشان می دهند ، مثل CheckListBox  یا RadioButtonList  وجود ندارد . برای ایجاد آنها باید خودمان در متدهای که به Extension Methods  معروف هستند ، آنها را ایجاد کنیم . این متدها به ما کمک می کنند تا ابزارهای مورد نیاز خود را به صورت سفارشی ایجاد و  به کلاس HtmlHelper  اضافه کنیم. (مقاله ای مفید در مورد Extension Method )

در ادامه می خواهیم یک CheckBoxList را از طریق Extension Method  ها به کلاس HtmlHelper  اضافه کنیم. قبل از نوشتن کد آن ، لازم است یاد آور شوم که         معمولا یک checkBocList برای نمایش لیستی از اطلاعات ( مثلا لیست علاقه‌مندیها ) به کار می رود. ابتدا من اکشنی که این لیست را می‌خواند، می‌نویسم. این اکشن بسیار ساده است و قبلا نمونه آن را در همین سری مقالات دیده‌ایم:

 public ActionResult Index()         {             Dictionary<Int32string> interests = new Dictionary<Int32string>();             interests.Add(2, "Sport");             interests.Add(3, "Travel");             interests.Add(4, "Music");             ViewBag.Cities = interests;             return View();         }
توضیح اینکه من به این دلیل متغیر از نوع دیکشنری انتخاب کردم که بتوانم علاوه بر اسم علاقه مندی، مقداری نیز به آن پاس دهم. البته شما ممکن است که این مقادیر را در بانک اطلاعاتی خود ثبت کرده باشید که مشکلی نیست و می توانید آن ها را براحتی درون متغیر دیکشنری بریزید
 

نویت به  ایجاد Extention Method رسید . برای این کار در پروژه خود فولدری به نام دلخواه ، مثلا CommonClasses  ایجاد کنید، سپس کلاسی به نام CheckBoxListHelper در آن بسازید. سپس کد زیر را در آن تایپ کنید :

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; 
 public static class CheckBoxListHelper     {         public static MvcHtmlString CheckListBox(this HtmlHelper helper, string Name, Dictionary<Int32string> citiesList, bool IsVertical, string cssClass)         {             StringBuilder sb = new StringBuilder();             sb.Append(string.Format(""));             foreach (var item in citiesList)             {                 sb.Append(helper.CheckBox(item.Value,true , new { @class = cssClass, value = item.Key }));                 sb.Append(helper.Label("RadioButtonItems", item.Value));                 sb.Append(" ");                 if (IsVertical) sb.Append("
"
);                             }             sb.Append(" ");             return MvcHtmlString.Create(sb.ToString());         }     }
 توضیح و تذکر:

1-   name space ها فراموش نشود.

2- به آرگومانها  دقت کنید: Name نام هر Checkbox را تشکیل می دهد . interestList همان دیکشنری است که نام علاقه‌مندیها و مقادیرشان در آن ذخیره شده است. IsVertical مشخص کننده این است که CheckBox ها افقی یا عمودی در صفحه قرار بگیرند. cssClass نام کلاس css هر CheckBox است .

3- کلاس از نوع Static  است

حال کافی است در صفحه (View یی )  که می خواهیم از CheckBoxList  استفاده کنیم ، ابتدا این کلاس را معرفی کنیم (در اینجا نام پروژه نیز Extention_Methods است ):

@using Extention_Methods.CommonClasses 

و سپس آن را فراخوانی کنیم :

@Html.CheckBoxList("cb1" , (Dictionary<intstring>) ViewBag.Cities , false , "myCssClas" ) 

همانطور که می بینید من کلاس myCssClas  را به همه عناصر CheckBoxList انتصاب کرده ا م ، به این ترتیب باعث ایجاد تگهای input با خصوصیت class="myCssClass" خواهیم شد. خروجی نیزبه صورت زیر به نمایش در خواهد آمد:

اما مهمترین قسمت :

یک مسئله باقی می ماند: چگونه مقدار گزینه‌های را که کاربر تیک زده ، بدست بیاوریم؟ برای این کار از JQuery  استفاده می کنیم. من دکمه ای به فرم اضافه کردم که با کلیک روی آن مقدار value گزینه انتخابی به اکشن save از کنترلر home ارسال می شود. ابتدا دکمه ای را به صفحه اضافه می کنم  و آن را درون یک فرم با مدل Razor می گذارم :

@using (Html.BeginForm("SaveCities""Home")) {      @Html.CheckListBox("clb1", (Dictionary<intstring>)ViewBag.Interest, false"myCssClass")     <input type="submit" name="btnSubmit" id="btnSubmit" value="Save" /> }

حال با نوشتن یک بخش JQuery در همان View کار را دنبال می کنیم و مقدارValue هر CheckBox ی که تیک خورده است را ابتدا در یک آرایه ذخیره می کنیم و سپس با استفاده از ajax آن را به اکشن Save از کنترلر Home ارسال می کنیم:

<script src="../../Scripts/jquery-1.5.1.js" type="text/javascript">script> <script src="../../Scripts/jquery.json.js" type="text/javascript">script> <script type="text/javascript">     $(document).ready(function () {         $("#btnSubmit").click(sendValues);     });     function populateValues() {         var data = new Array();         $('.myCssClass').each(function () {             if ($(this).attr('checked')) {                 var x = $(this).attr("value");                 data.push(x);             }         }); // of each         return data;     }     function sendValues() {         event.preventDefault();         var data = populateValues();         $.ajax({             type: 'POST',             url: '@Url.Content("~/Home/Save")',             data: $.json.encode(data),             dataType: 'json',             contentType: 'application/json; charset=utf-8',             success: function () { alert("1"); }         });     }  // of sendValues                  script>

توضیح: در کد فوق با کلیک روی btnSubmit تابع sendValues را فراخوانی می کنیم. در این تابع ابتدا با preventDefault از ارسال فرم به کنترلر خودداری می کنیم (چون هنوز مقادیر CheckBox ها را دریافت نکرده‌ایم) و سپس تابع populateValues هستیم که با استفاده از همان کلاس myCssClass مقدار value همه CheckBox ها را می گیرد و در آرایه ای به نام data ذخیره می کند. این آرایه سپس توسط ajax با فرمت json به اکشن svae از کنترلر Home ارسال می شود. 


اگر در مورد نحوه فراخوانی ajax در Jquery اطلاعاتی می خواهید به این لینک مراجعه کنید. 

اگر می خواهید  JQuery یاد بگیرید از این لینک شروع کنید.

در اکشن Save  مقادیر ارسال شده از View  توسط آرگومان خوانده می شوند ( int[] val ) : 

          

--

اکنون برای ادامه و تمرین به کلاس Helper یک RadioButtonList اضافه کنید و مقدار انتخابی را در کنترلر دریافت کنید.

--


تصمیم گرفتم برای سرعت بخشیدن به ارائه مطالب ، مقالات را کمی خلاصه تر بیان کنم و نوشتن کامل پروژه را به شما واگذار کنم، امیدوارم به این روش بتوانم مطالب بیشتری را ارائه دهم.
در این مقاله قصد دارم چگونگی استفاده از JQuery UI را جهت نمایش یک Autocomplete DropDownList در یک پروژه MVC بیان کنم. با اجرای این تکنیک شما یک TextBox خواهید داشت که درآن می توانید لیستی از موارد مشابه (مثلا ایمیل افراد ) را تنها با تایپ چند حرف ببینید. چیزی شبیه آنچه که الان شما در گوگل می بینید که با تایپ تنها چند حرف از یک کلمه ، موارد مشابه را به شما نمایش می دهد. 
- در این مقاله من از نگارش Razor برای صفحات View  استفاده می کنم.
روش کار:   
1- ابتدا کتابخانه JQuery Ui را از آدرس http://jqueryui.com/ دانلود کنید. آن را به فولدر Scripts پروژه خود اضافه کنید و در Viewیی که می خواهید ، با دستور Script به آن اشاره کنید: ( خود JQuery نیز را طبیعتا لازم داریم )
<script src="@Url.Content("~/scripts/jquery-1.7.js")" type="text/javascript" />
<script src="@Url.Content("~/scripts/jquery-ui-1.8.16.js")" type="text/javascript" />
نکته: 1- توجه داشته باشید نام فایلی که شما دانلود می کنید و یا نسخه آن ممکن است متفاوت با این چیزی باشد که من اینجا نوشته ام ، چون هر چند روز یکبار این فایلها بروز می شوند. 2- عبارت @Url.Content باعث می شود که نیازی نداشته باشید برای آدرس دهی از .. استفاده کنید. 3- اگر می خواهید در سایر صفحات نیز از این تکنیک استفاده کنید، دو خط فوق را به فایل Layout.cshtml_ که در فولدر Views/Shared وجود دارد ، اضافه کنید (در قسمت head ) 
2- در View یی که می خواهید textbox  را قرار دهید ، علاوه بر textbox  سایر ملزومات form را نیز قرار دهید ( با نگارش Razor به صورت زیر) :
@using (Html.BeginForm("Search""Home"FormMethod.Post, new { id = "ID" })) {         <input id="txtSearch"  name="txtSearch" type="text" />         <input type="submit" value="show" />     }
توضیح: 1- در کد فوق Search نام اکشن ، Home نام کنترلر است. 2- خصوصیت idو name جعبه متنی ( textbox ) باید یکی باشد.
3- این فرم به ما می گوید که اگر متنی در این textbox تایپ شد و دکمه Enter فشار داده شد، اکشن Search اجرا شود، ولی ما به قطعه کدی نیاز داریم که بتواند با فشار دادن هر کلید ، عملیات جستجو را انجاه دهد و لیست موارد مشابه را به ما برگرداند. برای این کار از JQuery  کمک می گیریم و در همان View یی که این فرم را گذاشتیم ، اسکریپت زیر را اضافه می کنیم :
<script type="text/javascript">     $(function () {         $("#txtSearch").autocomplete({             source: "/Home/AutocompleteSearch",             minLength: 3,             select: function (event, ui) {                 if (ui.item) {                     $("#txtSearch").val(ui.item.value);                     $("form").submit();                 }             }         });     }); script>
در کد فوق ابتدا عنصر txtSearch انتخاب شده ، که همان textbox است و سپس متد autocomplete اجرا شده است. در این متد پارامتر minLenght مشخص می کند که با تایپ چند کاراکتر توسط کاربر، عملیات جستجو شروع شود. وقتی بیش از 3 کاراکتر در textbox تایپ می شود این متد فراخوانی می شود و با هر بار فراخوانی اکشن AutocompleteSearch از کنترلر Home را اجرا می کند و پارامتر val این textbox را به عنوان آرگومان به اکشن ارسال می کند :  
 $("#txtSearch").val(ui.item.value);
                    $("form").submit();
4- حال باید به پیاده سازی متد AutocompleteSearch بپردازیم که بسیار راحت است و می تواند هر نوع جستجویی که شامل عبارت like ( یا Contain در Linq ) روی هر فیلد دلخواهی که مد نظر ما است ، باشد. قطعه زیر با توجه به نام بانک اطلاعاتی ، جداول و فیلدهای شما ممکن است تغییر کند:
 public JsonResult AutoCompleteSearch(string txtValue)         {             var suggestions = (from m in db.aspnet_Membership where m.Email.Contains(txtValue) select m.Email).Take(10).ToList(); 
            return Json(suggestions, JsonRequestBehavior.AllowGet);                      }
توضیح : خروجی این تابع از نوع JsonResult است (سعی می کنم در آینده آن را توضیح دهم ) - ورودی تابع نیز همان مقدار textbox است که توسط JQuery ارسال شده است یعنی txtValue
5- تا اینجا، اجرای AutoComplete DropDownList کامل شده و شما باید جستجوی اصلی را که پس از فشار دادن دکمه Enter صورت می پذیرد را در اکشن Search که در بند 2 توضیح داده شد ، انجام دهید و در view مربوط به خودش نتیجه را نشان دهید. 

در این مقاله با نحوه استفاده  از یکی از دهها امکانات Jquery Ui در MVC آشنا شدید، با نگاهی به سایت JQuery UI  می توانید از سایر ابزارهای مفید آن در پروژه های MVC استفاده کنید.

--


WebGrid ابزار جدید و ساده ای است در MVC 3 که برای نمایش داده ها در View  بکار می رود و امکاناتی چون صفحه بندی، مرتب سازی ، متمایز سازی سطرها و ... را داراست. در این جلسه با این ابزار و مزایای آن آشنا خواهیم شد.یکی از مزایای استفاده از WebGrid  این است که نیاز به اضافه کردن هیچ چیزی به صفحه (مثل رفرنس JQuery یا غیره ) نیست. WebGrid در فضای نام  System.Web.Helpers قرار دارد که با ایجاد یک پروژه ازنوع MVC  بصورت اتوماتیک در پروژه شما وجود دارد.

در ساده ترین حالت ، شما می توانید در کنترلر خود، با هر کوئری دلخواهی داده ها را از بانک اطلاعاتی بخوانید، مثل این مثال:

 Database1Entities db = new Database1Entities();
 
 public ActionResult Index()
 
        {
 
            var list = (from n in db.Students select n);
 
 
 
          return View(list);       }

 

(توضیح اینکه برای ارتباط با بانک اطلاعاتی در این مثال از Entityfarmework  و LinqToSql استفاده شده است.)

سپس در View به صورت زیر webGrid را فراخوانی کنید:

@{     var grid = new WebGrid(Model); } <div>     @grid.GetHtml(columns:                         grid.Columns(                                         grid.Column("Name""Student Name"),                                         grid.Column("Family""Student Family"),                                         grid.Column("Age""AGE")                                      )                   ) div>
در کد فوق ابتدا یک نمونه از WebGrid ایجاد شده است و سپس ستونهای آن مشخص شده اند. grid.GetHtml مشخص کننده مشخصات گرید است مثل ستونها ، خصوصیتها و استایلها. ستونها با grid.Column مشخص 
می شوند . پارامتر اول در grid.Column نام فیلد بانک اطلاعاتی است و پارامتر دوم نام سرستون آن موقع نمایش می باشد. 

نتیجه بصورت زیر خواهد بود:

حالتهای مختلفی برای نمایش فیلهای جدول اطلاعاتی وجود دارد. مثلا اگر بخواهید دو فیلد را در یک ستون نمایش دهید (مثلا فیلد نام و فامیل را در یک سلول نمایش دهید و با یک خط فاصله از هم جدا کنید)

 grid.Column(format: item => item.Name + " - " + item.Family , header: "Name" ) 
در کد فوق از نحوه نگارش لامبدا استفاده شده است که شما متغیر دلخواهی را در نظر می گیرید و با علامت => و تکرار آن متغیر ، به فیلدهای بانک اطلاعاتی دستیابی پیدا می کنید. مثل x => x.Name
زمان ایجاد نمونه از روی WebGrid نیز می توانید از سایر پارامترهای مفید آن استفاده کنید. پارامتر اول که همان Model است و داده های شما را در بر دارد ولی پارامترهای دیگری نیز دارد که ساده ترین آنها عبارتند از : 
 var grid = new WebGrid(source: Model , rowsPerPage: 10, defaultSort: "NAME" , canPage: true, canSort: true);  
پارامترها به ترتیب 1- source نگه دارنده داده ها، 2- rowsPerPage تعداد سطر جدول در هر صفحه، 3- defaultSort نام فیلدی که مرتب سازی بر اساس آن انجام می شود 4- CanPage صفحه بندی شود یا نه 5- canSort 
مرتب شود یا نه پارامترهای تقریبا مشابهی را نیز می توانید بعد از grid.GetHtml بیاورید مثل :
 1: gridItens.GetHtml(
 2: tableStyle: "webgrid",
 3: headerStyle: "webgrid-header",
 4: footerStyle: "webgrid-footer",
 5: alternatingRowStyle: "webgrid-alternating-row",
 6: selectedRowStyle: "webgrid-selected-row",
 7: rowStyle: "webgrid-row-style")
 
 

همانطور که از نام پارامترها مشخص است ، tableStyle  نام کلاس CSS مربوط به خود جدول است. ، headerStyle کلاس قسمت هدر جدول ، footerStyle نام کلاس مربوط به فوتر جدول و alternatingRowStyle مربوط به استایل سطرها بصورت یک در میان است تا از یکدیگر تشخیص داده شوند. selectedRowStyle نام کلاس سطر انتخاب شده است و rowStyle نام کلاس همه سطرها می باشد. شما می توانید همه این کلاسها را در فایل View (و یا یک فایل css جداگانه ) خود یکجا بیاورید، مثل :

 1: .webgrid
 2: {
 3: width: 50%;
 4: border: 0px;
 5: border-collapse: collapse;
 6: }
 7: 
 8: .webgrid a
 9: {
 10: color: #000;
 11: }
 12: 
 13: .webgrid-header
 14: {
 15: padding: 6px 5px;
 16: text-align: center;
 17: background-color: #e8eef4;
 18: border-bottom: 2px solid #3966A2;
 19: height: 40px;
 20: 
 21: border-top: 2px solid #D6E8FF;
 22: border-left: 2px solid #D6E8FF;
 23: border-right: 2px solid #D6E8FF;
 24: }
 25: 
 26: .webgrid-footer
 27: {
 28: padding: 6px 5px;
 29: text-align: center;
 30: background-color: #e8eef4;
 31: border-top: 2px solid #3966A2;
 32: height: 30px;
 33: 
 34: border-bottom: 2px solid #D6E8FF;
 35: border-left: 2px solid #D6E8FF;
 36: border-right: 2px solid #D6E8FF;
 37: }
 38: 
 39: .webgrid-alternating-row
 40: {
 41: height: 30px;
 42: background-color: #f2f2f2;
 43: border-bottom: 1px solid #d2d2d2;
 44: 
 45: border-left: 2px solid #D6E8FF;
 46: border-right: 2px solid #D6E8FF;
 47: }
 48: 
 49: .webgrid-row-style
 50: {
 51: height: 30px;
 52: border-bottom: 1px solid #d2d2d2;
 53: 
 54: border-left: 2px solid #D6E8FF;
 55: border-right: 2px solid #D6E8FF;
 56: }
 57: 
 58: .webgrid-selected-row
 59: {
 60: font-weight: bold;
 61: }
 

اگر در یک View بخواهید بیش از یک WebGrid داشته باشید، آنگاه باید هنگام ایجاد نمونه WebGrid خصوصیت  feildNamePerfix را نیز ذکر کنید تا در هنگام ارجاع درخواستها ، نام آن را با این پیشوند از نام بقیه WebGrid ها متمایز کند:

 1: var gridItens = new WebGrid(source: Model,
 2: defaultSort: "Title",
 3: rowsPerPage: 5,
 4: canPage: true,
 5: canSort: true,
 6: fieldNamePrefix: "gridItens_",
 7: pageFieldName: "inside",
 8: selectionFieldName: "selectedRow");
 

همانطور که می بینید در خط 6 پیشوندی به نام _gridItens مشخص شده که باعث می شود هنگام ارسال یک درخواست  نام این WebGrid با نامی که ما مشخص کرده ایم جایگزین شود و  URL صفحه  به چیزی شبیه شکل زیر تبدیل شود:

اما خطوط 7 و 8 چه چیزهایی را تعریف می کنند؟ به نظر می رسد که آنها هم دارند اسم پارامترهایی را جایگزین می کنند؟!

بله ، از آنجایی که برای همه WebGrid ها دو پارامتر مشترک به نامهای page  و row در هنگام تشکیل query string (پارامترهای موجود در URL ) وجود دارد، باید نام این دو پارامتر را به هنگام ساخت نمونه جدید تغییر داد تا هر WebGrid بتواند پارامتر page  و row  مختص خود را پیدا کند، بنابراین پارامتر pageFieldName برای جایگزین کردن page  با یک عبارت دیگر در این WegGrid و عبارت selectionFieldName برای جایگزینی row استفاده شده است.

بهینه سازی ستونها :

اگر بخواهید در ستونی یک  مقدار را به واحد پولی تبدیل کنید، بخش خاصی از یک فیلد را نمایش دهید، دو یا چند فیلد را با هم ترکیب کنید یا هر بهینه سازی دیگری ، می توانید از :format استفاده کنید. به مثال زیر توجه فرمایید:

 1: columns: gridItens.Columns(
 2: 
 3: gridItens.Column(
 4: columnName: "Title",
 5: header: "Título",
 6: style: "text-align-left"),
 7: 
 8: gridItens.Column(
 9: columnName: "Price",
 10: header: "Preço",
 11: style: "text-align-center",
 12: format: (item) => string.Format("{0:C}", item.Price)),
 13: 
 14: gridItens.Column(
 15: columnName: "Quantity",
 16: header: "Qtd em Estoque",
 17: style: "text-align-center")
 18: )

در خط 11 فیلد Price به واحد پولی تبدیل شده ، بنابراین موقع چاپ علامت واحد پولی ( $ ) کنار آن قرار می گیرد.

انتخاب یک سطر:

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

@grid.GetHtml(columns:                         grid.Columns(                grid.Column(format: item => item.Name + " - " + item.Family , header: "Name" ),                                      grid.Column("", format: (item) => item.GetSelectLink("select row")),                                      grid.Column("Age""AGE")                                      )                   )

با کلیک روی عبارت Select row شماره سطری که روی آن کلیک شده برگردانده می شود.

توجه داشته باشید که عددی که در متغیر row قرارمی گیرد شماره سطر است نه ID .

          * : این مقاله گزیده ای بود از مجموعه مقالات زیر: 

 

http://weblogs.asp.net/andrebaltieri/archive/2010/11/01/asp-net-mvc-3-working-with-webgrid.aspx

http://weblogs.asp.net/andrebaltieri/archive/2010/11/02/asp-net-mvc-3-working-with-webgrid-part-2.aspx

http://weblogs.asp.net/shijuvarghese/archive/2010/10/08/using-the-webgrid-helper-in-asp-net-mvc-3-beta.aspx

 

       ** همچنین لینک مربوط به WebGrid در MSDN : 

http://msdn.microsoft.com/en-us/library/system.web.helpers.webgrid(v=vs.99).aspx



 

 

 



لینک
مطالب اخیر خطای Collation هنگام مقایسه دو فیلد متفاوت در MSSQL دهها قطعه کد کاربردی بسیار مفید در سایت css-tricks چگونه در یک فرم MVC مانع حملات از نوع CSRF شویم؟ آموزش MVC - قسمت نهم - WebGrid در 3 MVC ویژگی Name در عناصر Html هنوز مهم است. چگونه دکمه like را به سایت یا وبلاگ خود اضافه کنیم؟ افزودنیهای مرورگر کروم متد ()on. در JQuery 1.7 مشاهده صفحات طراحی شده در چند مرورگر بخش هفتم سری مقالات آموزش MVC (فارسی)
کلمات کلیدی وبلاگ mvc (۳) برنامه نویسی وب (۳) برنامه نویسی (٢) c# (٢) جاوااسکریپت (٢) html (۱) طراحی وب (۱) ajax (۱) css (۱) csrf (۱) mssql (۱) jquery (۱) لایک (۱) آی تی بازار (۱) mvc (۱) آموزش ++c در pluralsight (۱) ویرایشگر متنی (۱) جستجوی جدوال تحت وب با yui (۱) window resizer plugin (۱) آموزش jquery (۱) ابزار چارت (۱) highcharts (۱) collation (۱) جامعه برنامه نویسان افغانستان (۱) wovs default browser switcher (۱) افزودنیهای کرورگر کروم (۱) webgrid (۱) هک در mvc (۱) css-tricks (۱) collate (۱)
دوستان من مقالات آموزشی من MVC وبلاگ فنی من سیاره وردپرس فارسی .NET Tips (وحید نصیری) سایت آموزشی سی شارپ مهرداد کیانیان افشار محبی آرش آقاجانی مجتبی صحرایی خانه برنامه نویسان افغانستان مصطفی دیندار مقالات آموزشی برنامه نویسی رحمت رضایی ( ToString ) اخبار فناوری اطلاعات طراح قالب