# برنامه نویسی با محصولات مایکروسافت > برنامه نویسی مبتنی بر Microsoft .Net Framework > ASP.NET MVC > آموزش: آموزش استفاده از AutoMapper و رهایی از بند تکرار

## hakim22

در محیط ASP.MVC کار با مدل یکی از ارکان اصلی برنامه نویسی است. در بسیاری موارد مدلی که در بانک استفاده کرده اید برای نمایش به کاربر در قسمت View مناسب نیست. معمولا مدلها شامل اطلاعات خاصی هستند که بهتر است کاربر آنها را مشاهده نکند. در این مواقع ما یک مدل میانجی میسازیم با عنوان ViewModel که جهت نمایش مدل در View از آن استفاده کنیم(البته با تعریف آن در MVVM فرق دارد)
فرض کنید یک مدلی که برای کاربران سایت داریم به صورت زیر باشد.



*دانلود متن کامل مقاله به همراه پروژه ASP.MVC در VS2012*





  public class User
        {

        public int ID { get; set; }
        
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Name { get; set; }
        public string Password { get; set; }

        public DateTime TimeCreated { get; set; }

        }


حالا برای نمایش مشخصات یک کاربر قبل از ارسال مدل به View باید خصوصیت Password را برداریم. برای این منظور یک مدل دیگر میسازیم.

public class UserView
        {

        public int ID { get; set; }

        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Name { get; set; }
        
        }

توجه : اگر اینکار نکنید و مدل را مستقیما به View بفرستید به راحتی با ابزار برنامه نویسی درون Chrome یا IE میشود محتویات کامل مدل ارسالی را مشاهده کرد و عدم نمایش یک خاصیت به صورت تگ HTML باعث محو شدن آن خصوصیت نمیشود. دیگر اینکه در اینجا ممکن است ساده تر این باشد که مقدار password را قبل از ارسال رو رشته ی خالی تنظیم کنیم. اما در بسیاری موارد مدلها خیلی شلوغتر از آن است که با خط خطی کردن کارمان پیش برود.

کنترلر(بدون AutoMapper)

در گام بعدی کنترلر مورد نظر خود را می سازیم و اطلاعات را از بانک بارگذاری می کنیم. 
   public ActionResult Index()
        {

            var user = GetUserInfo(Id: 10);
            //--- TODO: Map User to UserView

            return View(userView);
           }
 


اطلاعات هر کاربر با استفاده از متد GetUserInfo() خوانده میشود و درون متغیر user ذخیره میگردد. در اینجا با دو چالش روبرو هستیم. 

1.	مدل User باید به مدل UserView تبدیل شود.
*2.	وقتی اطلاعات از بانک SQL بازگردانده میشوند رشته ها نه به اندازه ی محتوایشان بلکه به اندازه ی طول 
پیشفرض مقدار دهی شده اند. مثلا اگر در بانک SQL طول فیلد Name را روی nchar(20) تنظیم کرده باشید. SQL  همیشه رشته ای با طول 20 باز میگرداند. حتی اگر رشته ی ذخیره شده درون فیلد یک کلمه ی 5 یا 10 حرفی باشد.*

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


public ActionResult Index()
            {

            var user = GetUserInfo(Id: 10);
          
            var userView = new UserView()
            {
                ID = user.ID,
                Name = user.Name.Trim(),
                FirstName = user.FirstName.Trim(),
                LastName = user.LastName.Trim()
            };
            

            return View(userView);
            }



حالا برای یک لحظه تصور کنید که مدل User در ابعاد واقعی باشد که چیزی نزدیک به 20 فیلد لازم دارد. کپی تک تک خصوصایت و Trim کردن رشته ها (در بسیاری موارد الزامی است) یک کار سرسام آور است. حالا این کار را در تعداد همه ی View ها ضرب کنید و ببینید که با چه حجم انبوهی از کدهای تکراری روبرو میشوید. در اینجا است که ابزار AutoMapper به دادمان میرسد.
کنترلر(با AutoMapper)
بدون شک دنیا بعد از ابدای AutoMapper جای قشنگتری برای زیستن است! کافی است یک نگاه دوباره به کد مربوط به کنترلر بعد از استعمال AutoMapper بیاندازید.


        public ActionResult Index()
        {

            var user = GetUserInfo(Id: 10);

            var userView = Mapper.Map<User, UserView>(user);

            return View(userView);
            }

        }

میبینید که عملیات Map کردن خصوصیات یک کلاس به سرعت و به زیبایی هرچه تمامتر انجام شد. البته راه اندازی AutoMapper کمی دردسر دارد ولی زمانی که صرف پیاده سازی آن می کنید به همه چیزهای دیگرش می ارزد.



*دانلود متن کامل مقاله به همراه پروژه ASP.MVC در VS2012*

----------


## Alirs1

خیلی ممنون خیلی خوب توضیح داده شده بود

----------


## forestasphalt

سلام  با تشکر از شما
یک سوال دارم این auto mapper رو برای لیستی از اشیا چگونه عمل میکنه؟
مثلا میخوایم لیستی از اشیا a رو به لیستی از اشیا b انتقال بدیم؟
باید حلقه گذاشت  و کد زیر رو توش نوشت 
 var userView = Mapper.Map<User, UserView>(user);
یا راه دیگه ای وجود داره؟
با تشکر از شما

----------


## hakim22

> سلام  با تشکر از شما
> یک سوال دارم این auto mapper رو برای لیستی از اشیا چگونه عمل میکنه؟
> مثلا میخوایم لیستی از اشیا a رو به لیستی از اشیا b انتقال بدیم؟
> باید حلقه گذاشت  و کد زیر رو توش نوشت 
>  var userView = Mapper.Map<User, UserView>(user);
> یا راه دیگه ای وجود داره؟


مسلما راه دیگری وجود داره. در آموزش نحوه ی ساختن تبدیل های Custom نشان داده شده است. همان روشی که برای تبدل رشته به رشته ! استفاده شده است می تواند برای هر شی دیگری استفاده شود. 
در ضمن کتابخانه ی دستورات گسترده ای در AutoMapper طراحی شده است و کارهای زیادی از جمله جستجو بین خصوصیت ها و Igonre کردن اشیایی با اسامی خاص و ساختن پروفایل عمومی و ... را میتوانید با آن اجا م دهید.

اما دو مسئله وجود دارد.
1- مشکل بزرگی که این Framework ها دارند ضعف در Documentation است. راهنمای خوبی که جامع و کامل محتوای دستورات و روش کار را توضیح داده باشد برای آن نوشته نشده است. یا حداقل در دسترس نیست.
2- ابزار AutoMapper برای کپی خاصیت ها به خوبی عمل میکند و من فکر میکنم این تنها جایی است که باید از این ابزار استفاده کرد. اینکه شما یک حقله درون برنامه داشته باشید و درون حلقه از AutoMapper استفاده کنید روش بهتری است تا اینکه کل کار حلقه را نیز به AutoMapper بسپارید . مسلما AutoMapper هم در درونش برای کپی کردن خاصیت های List ها و Array ها از یک حلقه استفاده می کند و هیچ تضمینی وجود ندارد این حلقه ها بازدهی بیشتری داشته باشند. 

نکته ی دیگر اینکه AutoMapper یک فریم ورک open source است و میتوانید سورسش را دانلود کنید و تغییر دهید.

----------

