عنوان:

‫نحوه استفاده از ViewModel در ASP.NET MVC


نویسنده: سیروان عفیفی
تاریخ: ۱۳۹۱/۱۲/۱۳ ۱۴:۲۵
آدرس: www.dntips.ir

یک Model چیست؟

·   قسمتی از Application است که Domain Logic را پیاده سازی می‌کند.

·   همچنین با عنوان Business Logic نیز شناخته می‌شود.

·   Domain Logic داده‌هایی را که بین UI و دیتابیس پاس داده می‌شود، مدیریت می‌کند.

·   برای مثال، در یک سیستم انبار،Model   کارش ذخیره سازی اقلام در حافظه و Logic تعیین کننده موجود بودن یک آیتم در انبار میباشد.


یک ViewModel چیست؟

·   ViewModel به ما این امکان را میدهد تا از چندین Entity، یک شیء واحد بسازیم.

·   بهینه شده برای استفاده و رندر توسط یک View

 

چرا باید از ViewModel استفاده کنیم؟

  • اگر شما بخواهید چندین Model را به یک View پاس دهید، استفاده از ViewModel ایده بسیار خوبی است.
  • همچنین امکان Validate کردن ViewModel را به روشی متفاوت‌تر از Domain Model برای سناریوهای اعتبارسنجی attribute-based را در اختیارمان قرار میدهد.
  • برای قالبندی داده‌ها نیز استفاده میشود.
        o برای مثال به یک داده یا مقدار پولی قالبندی شده به یک روش خاص نیاز داریم؟
ViewModel بهترین مکان برای انجام این کار است.
  • استفاده از ViewModel تعامل بین Model و View را ساده‌تر می‌کند.  


مکان قرارگیری ViewModel در پروژه بهتر است کجا باشد؟

  1. می‌تواند در یک پوشه با نام ViewModel در ریشه پروژه باشد.

  2. به صورت یک dll ارجاع داده شده به پروژه. 
  3. در یک پروژه جدا به عنوان یک Service Layer.


Best Practice هایی در زمان استفاده از ViewModelها 

  1. داده‌هایی را که قرار است در View رندر شوند، داخل ViewModel قرار دهید.
  2. View باید خصوصیاتی را که نیاز دارد، مستقیما از ViewModel بدست بیاورد.
  3. وقتی که ViewModel شما پیچیده‌تر می‌شود، بهتر است از یک Mapper استفاده کنید.

اجازه دهید مثالی را در این رابطه براتون بیارم :

در یک View می‌خواهیم هم لیست اخبار سایت و هم لیست سخنرانان سایت (مثال مربوط به یک پروژه برای همایش است) را نمایش دهیم. خوب طبق مطالب فوق استفاده از ViewModel بهترین راه حل است. ViewModel مربوطه به صورت زیر تعریف شده است :

public class SpeakerAndNewsViewModel
    {
        public IEnumerable<News> News { get; set; }
        public IEnumerable<Speaker> Speakers { get; set; }
    }
و در اکشن متد Index هم بدین صورت Model‌ها را به ViewModel ساخته شده پاس می‌دهیم :
public ActionResult Index()
        {
            var news = db.News.OrderBy(r=>r.Date)
                        .Take(3);
            var speakers = db.Speakers.Take(4);
            var model = new SpeakerAndNewsViewModel { 
                News=news,
                Speakers=speakers
            };
            return View(model);
        }
و یک View را به صورت Strongly Typed از نوع ViewModel خود که در اینجا SpeakerAndNewsViewModel  است ایجاد می‌کنیم :

و View مربوطه را به شکل زیر تغییر می‌دهیم :  
@model  Project.Models.SpeakerAndNewsViewModel
@{
    ViewBag.Title = "Home Page";
}
@section news
{
@foreach (var item in Model.News)
{
    //..
}
}
@section speakers
{
@foreach (var item in Model.Speakers)
{
    //...
}
}

نظرات

  • شاهین کیاست در ۱۳۹۱/۱۲/۱۳ ۱۴:۴۶
    ·ViewModel به ما این امکان را میدهد تا از چندین Entity یک شیء واحد بسازیم.

    من فکر می‌کنم ViewModel ، مدل مورد نیاز برای یک View را فراهم می‌کند و لزوما برای این نیست از چند موجودیت دیتابیسی یک شیء بسیازیم و به View پاس دهیم.

     البته در ادامه‌ی مطلب به این مورد اشاره شده . اما به غلط در برخی آموزش‌ها ViewModel اینگونه ایجاد می‌شود که شامل چند Entity هست.
    • امیر بختیاری در ۱۳۹۱/۱۲/۱۴ ۱۷:۳۲
      با تشکر از مطلب خوبتان
      فقط یه سوال اینکه  View Model فقط در جاهایی مثل این که مثال زدید کاربرد دارد یا در جایی که الان در برنامه‌های وب انجام میدیم و چند تا جدول که با هم ارتباط دارند و یک view از روی آنها ایجاد می‌کنیم و در پروژه از این View ساخته شده استفاده می‌کنیم برای اعمال مختلف نیز می‌توان استفاده کرد . برای مثال دانشجو با نمرات و درس‌ها و رشته که با هم در ارتباط دارند را یک  View Model کرد و در هر قسمت پروژه که نیاز داشتیم از این استفاده کنیم؟
      یه سوال دیگه هم اینکه خیلی جاها دیدم که نوشته از Model به صورت مستقیم استفاده نکنید و یک View Model  این وسط برای ارتباط داشته باشیم می‌خواستم ببینم آیا درسته و دلیلش چیه ؟

      • شاهین کیاست در ۱۳۹۱/۱۲/۱۴ ۱۷:۴۰
        سلام ؛ 
        برای درک بهتر ViewModel و علت استفاده از آن این مطلب  را مطالعه بفرمایید .
  • مهمان در ۱۳۹۱/۱۲/۱۴ ۱۰:۵

    ·قسمتی از Application است که Domain Logic را پیاده سازی می‌کند.

    ·همچنین با عنوان Business Logic نیز شناخته می‌شود. 

    برای مثال، در یک سیستم انبار،Model   کارش ذخیره سازی اقلام در حافظه و Logic تعیین کننده موجود بودن یک آیتم در انبار میباشد. 

    مگه مدل Entity‌های ما نیستند که توی سیستم استفاده میشن؟ یا دید من اشتباه بوده نسبت به مدل.
    مثلا ما یه مدل به نام  Person  داشته باشیم  من اونو به این صورت می‌بینم  و هیچ منطقی توش پیاده سازی نمی‌کنم
    Public Class PersonModel
    {
        long Id{get;set;}
        string Name{get;set;}
    
    }
    اما با حرف شما مدل Person به این صورت هستش
    Public Class PersonModel
    {
        long Id{get;set;}
        string Name{get;set;}
    
       int SavePerson(person p);
       Person Finde(long personId);
    
     
    
    }
    من حرف شما رو بد برداشت کردم یا اینکه دیدم نسبت به مدل اشتباه بوده؟
    • سیروان عفیفی در ۱۳۹۱/۱۲/۱۴ ۱۰:۴۲
      ببنید Model به گفته آقای Scott Allen ، در توسعه نرم افزار میتونه صدها مفهوم رو پوشش بده، در کل Model رو میتونیم به این صورت تعریف کنیم : مجموعه ایی از کلاسها که تعریف کننده داده‌ها و همچنین Business Ruleها هستند Business Rule هم همون قواعد یا Business Logic مربوطه هستند که در بالا تعریف شده که مشخص میکنه دیتا چطور میتونه ذخیره بشه و یا تغییر پیدا کنه. 
      • مهمان در ۱۳۹۱/۱۲/۱۴ ۱۱:۳۱
        برای جدا سازی کد بهتر نیست که مثلا Business     نرم افزار تو یه لایه جدا پیاده سازی بشه؟
        • وحید نصیری در ۱۳۹۱/۱۲/۱۴ ۱۲:۱۶
          البته عنوان کردند که در این زمینه بین علما اختلاف هست.
          برای مثال الگویی وجود دارد به نام Active record که دقیقا با تعریف عنوان شده مطابقت دارد (یک شیء می‌تواند متدهای مثلا افزودن و به روز رسانی و غیره را هم داشته باشد). مزایا و معایب خاص خودش را هم دارد. مطالعه در مورد این‌ها جهت آشنایی با سلایق و دیدگاه‌های مختلف طراحی خوب است. اما وجود آن‌ها به معنای الزام استفاده از روش‌های مطرح شده نیست.
          • یزدان در ۱۳۹۲/۰۱/۱۲ ۲:۱۶
            لطف میکنید نحوه ارتباط viewmodel  رو زمانی که بین model  و view  قرار میگیره توضیح بدین .
            اینکه در آخر ViewModel  رو چطور به Model  مرتبط میکنیم ؟
            آیا امکان این که هم Model  و هم    ViewModel اعتبار سنجی کنیم کار درستیه ؟
            بیشتر قسمت ربط ViewModel  به Model  برام اهمیت داره که متوجهش نمیشم .
            با تشکر
            • مهمان در ۱۳۹۲/۰۱/۱۲ ۱۰:۳۴

              برای اتصال ViewModel به مدل می‌نویسیم: یک خاصیت viewmodel ،خودت رو به یک خاصیت model انتساب بده پدرجان! همین! (البته حالت پیشرفته‌تر استفاده از AutoMapper هست که نخوای این‌ها رو اگه سختت هست دستی بنویسی)

              خواص مدل رابطه یک به یک داره با جدول شما در بانک اطلاعاتی. اون هم اطلاعاتش نیاز به اعتبار سنجی داره. ViewModel هم نیاز داره چون یک سری خاصیت اضافی عموما داره که در بانک اطلاعاتی نیست و فقط در View تعریف شده.

              • یزدان در ۱۳۹۲/۰۱/۱۲ ۱۱:۴۰
                «یک خاصیت viewmodel ،خودت رو به یک خاصیت model انتساب بده پدرجان! همین!»
                این رو با مثال و یه مدل و viewmodel  ساده نشون بده . اینو که شما گفتی میدونم ، شما زحمت بکش نحوه انتساب رو بگو . با کد
                • مهمان در ۱۳۹۲/۰۱/۱۲ ۱۲:۲۳
                  انتساب از طریق عملگر مساوی انجام میشه. مثلا user.Name = userViewModel.Name
                  • یزدان در ۱۳۹۲/۰۱/۱۲ ۱۳:۸
                    این انتساب کجا انجام میشه ؟ توی اکشن ؟
                    اگه مقدوره یک مثال ساده با ViewModel  و Model  و مکانی که این انتساب صورت میگیره بیان کنید .
                    • مهمان در ۱۳۹۲/۰۱/۱۲ ۱۳:۱۳
                      در همین مقاله بالا از قسمت «اجازه دهید مثالی را در این رابطه براتون بیارم :» به بعد رو مطالعه کنید.  این مثال در مورد HttpGet هست. در حالت HttpPost هم همینه. فرقی نمی‌کنه.         
                    • علیرضا پایدار در ۱۳۹۲/۰۱/۱۲ ۱۳:۴۱
                      شما اگر که از Automapper استفاده می‌کنی باید ابتدا یک Map ایجاد کنی و بهتر است که این کار در متد Application_Start  انجام بگیرد.به طور مثال:

                      protected void Application_Start()
                              {
                                //مپ کردن مدل به ویومدل
                                Mapper.CreateMap<DomainClasses.Product, ProductListVM>();
                                //مپ کردن ویومدل به مدل  
                                Mapper.CreateMap<ProductCreateVM,DomainClasses.Product>();
                              }
                      حال فرض بگیر دیتایی داری که میخوای انتصاب بدی به ViewModel به این شکل عمل میکنی:
                      public ActionResult ShowList()
                      {
                      var productList = _cotext.Products.ToList();
                      //انتصاب
                       var viewmodel = Mapper.Map<List<domain.Products>, List<ProductListVM>>(productList);
                       return View(viewmodel);
                      }
                      حال برعکس میخوای ViewModel انتصاب بدی به Model :
                      [HttpPost]
                              public virtual ActionResult Create(ProductCreateVM product)
                              {
                                  try
                                  {
                                      if (ModelState.IsValid)
                                      {
                                          var model = Mapper.Map<ProductCreateVM, domain.Product>(product);
                                          _cotext.Products.Add(model);
                                          _cotext.SaveChanges();
                                          return RedirectToAction(ShowList);
                                      }
                                      return View(product);
                                  }
                                  catch
                                  {
                                      
                                  }
                              }
                      امیدوارم به درد بخوره.قبل از هر چیز مطالب مربوط به AutoMapper سایت را مطالعه کن مثل:
                      اگرم خواستی میتونی دستی این انتصاب‌ها را انجام بدی البته من پیشنهاد نمیکنم.
                      • یزدان در ۱۳۹۲/۰۱/۱۲ ۱۴:۵۰
                        تشکر مهندس پایدار بابت جواب و توضیح کاملی که ارائه دادین
  • علی حق جو در ۱۳۹۲/۰۱/۳۰ ۱۶:۴۲
    با سلام.
    فرض کنید یک مدل با عنوان category داریم.
    اگر نیاز به نمایش تعداد محصولات آن category در ویومدل داشته باشیم، به نظر شما بهترین راه کدام است؟
    آیا باید یک کوئری جدا برای یافت تعداد محصولات بزنیم و به خاصیت موجود در ویومدل پاس دهیم.
    یا باید این خاصیت را درون مدل در نظر بگیریم؟
    با تشکر.
    • وحید نصیری در ۱۳۹۲/۰۱/۳۰ ۲۰:۴۲
      - هر دو مورد رو می‌تونید انجام بدید.
      - برای نمونه در این سایت و در همین صفحه‌ای که ملاحظه می‌کنید، «تعداد نظرات» فیلد محاسباتی است. یا در جایی دیگر، تعداد مطالب یک برچسب هم فیلد محاسباتی است. این‌کار برای بالا بردن سرعت نمایشی سایت انجام شده.
  • مهمان در ۱۳۹۲/۰۲/۲۲ ۰:۱۸
    سلاام ...
    من تاجاییکه میتونستم چیزهایی که درباره viemodel  و automapper توی سایت بود رو خوندم ولی چیزی که میخواستم را پیدا نکردم شاید هم درک درستی ازش نداشتم در کل سوال سوال من از شما دوستان اینه : 
    یک viewmodel دارم که از چندین جدول توی db ایجاد شده که در زیر نوشتمش : 
    public class ResumeViewModel
        {
            public ResumeViewModel()
            {
                
            }
            public ResumeViewModel(IEnumerable<Resume> resum, IEnumerable<Work_Experience_Job_Seeker> workExperienceJobSeekerOfViewModel, IEnumerable<Job_Expertises> jobExpertisesOfViewModel, IEnumerable<Degrees_Work_Experience_Required> degreesWorkExperienceRequiredOfViewModel, IEnumerable<Specialized_Course> specializedCourseOfViewModel, IEnumerable<Book_Published> bookPublishedOfViewModel, IEnumerable<Basic_Table> basicTable)
            {
                ResumeOfViewModel = resum;
                WorkExperienceJobSeekerOfViewModel = workExperienceJobSeekerOfViewModel;
                JobExpertisesOfViewModel = jobExpertisesOfViewModel;
                DegreesWorkExperienceRequiredOfViewModel = degreesWorkExperienceRequiredOfViewModel;
                SpecializedCourseOfViewModel = specializedCourseOfViewModel;
                BookPublishedOfViewModel = bookPublishedOfViewModel;
                BasicTable = basicTable;
            }
            public IEnumerable<Resume> ResumeOfViewModel { get; set; }
            public IEnumerable<Work_Experience_Job_Seeker> WorkExperienceJobSeekerOfViewModel { get; set; }
            public IEnumerable<Job_Expertises> JobExpertisesOfViewModel { get; set; }
            public IEnumerable<Degrees_Work_Experience_Required> DegreesWorkExperienceRequiredOfViewModel { get; set; }
            public IEnumerable<Specialized_Course> SpecializedCourseOfViewModel { get; set; }
            public IEnumerable<Book_Published> BookPublishedOfViewModel { get; set; }
            public IEnumerable<Basic_Table> BasicTable { get; set; }
    
            public int NumberForm { get; set; } // EditResumes.chtml & ShowResumes.chtml  ===> baraye select kardan formha :D 
    
            }
    و این viewmodel رو توی متد Edit Resume  استفاده کردم که متد get  بصورت زیر ::
            [HttpGet]
            public ActionResult EditResumes(int id)
            {
                var contex = new Final_My_ProjectEntities2();
                var res1 = contex.Resumes.Where(rec => rec.Resume_ID == id);
                var res2 = contex.Work_Experience_Job_Seeker.Where(rec => rec.Resume_ID == id).ToList();
                var res3 = contex.Job_Expertises.Where(rec => rec.Resume_ID == id).ToList();
                var res4 = contex.Degrees_Work_Experience_Required.Where(rec => rec.Resume_ID == id).ToList();
                var res5 = contex.Specialized_Course.Where(rec => rec.Resume_ID == id).ToList();
                var res6 = contex.Book_Published.Where(rec => rec.Resume_ID == id).ToList();
                var res12 = contex.Basic_Table.ToList();
                var viewModel = new ResumeViewModel(res1, res2, res3, res4, res5, res6,res12);
                var items = new SelectList(
                     new[]
                        {
                            new {Value = "1", Text = "فرم مهارت ها"},
                            new {Value = "2", Text = "فرم کتاب/مقالات منتشر شده"},
                            new {Value = "3", Text = "فرم سابقه کاری"},
                            new {Value = "4", Text = "فرم دوره‌های تخصصی گذرانده"},
                            new {Value = "5", Text = "فرم تخصص‌های شغلی"},
                            new {Value = "6", Text = "فرم مدارک تحصیلی"}
                        },
                 "Value", "Text");
    
                ViewBag.Form = new SelectList(items, "Value", "Text");
    
                var res7 = contex.Basic_Table.Where(rec => rec.Domain == "MilitaryStatus").ToList();
                ViewBag.MilitaryStatus = new SelectList(res7, "Value", "Meaning",res1);
    
                var res8 = contex.Basic_Table.Where(rec => rec.Domain == "Sex");
                ViewBag.Sex = new SelectList(res8, "Value", "Meaning", res1);
    
                var res9 = contex.Basic_Table.Where(rec => rec.Domain == "MartialStatus").ToList();
                ViewBag.MartialStatus = new SelectList(res9, "Value", "Meaning", res1);
    
                var res10 = contex.Basic_Table.Where(rec => rec.Domain == "Degree").ToList();
                ViewBag.Degree = new SelectList(res10, "Value", "Meaning");
    
                var res11 = contex.Basic_Table.Where(rec => rec.Domain == "Ability").ToList();
                ViewBag.Ability = new SelectList(res11, "Value", "Meaning");
    
    
                return View(viewModel);
            }
    و view  این متد بصورت زیر هست البته قسمتی از آن :: 
    @model Final_My_Project.ViewModels.ResumeViewModel
    
    @{
        ViewBag.Title = "ویرایش رزومه";
        ViewBag.PartOne = "فرم مهارت ها";
        ViewBag.PartTwo = "فرم کتاب/مقالات منتشر شده";
        ViewBag.Part3 = "فرم سابقه کاری";
        ViewBag.Part4 = "فرم دوره‌های تخصصی گذرانده";
        ViewBag.Part5 = "فرم تخصص‌های شغلی";
        ViewBag.Part6 = "فرم مدارک تحصیلی";
    
    }
    <h2 style="font-family:  Arial;">@ViewBag.Title</h2><br/>
       <script type="text/javascript">
           $(function () {
               $('#Gender').change(function () {
                   var selectKind = $(this).find('option:selected').text();
                   var divMilitary;
                   if (selectKind == "زن") {
                       divMilitary = $('#Military');
                       divMilitary.hide();
                       divMilitary.css('display', 'none');
                   }
                   else if (selectKind == "مرد") {
                       divMilitary = $('#Military');
                       divMilitary.show();
                       divMilitary.css('display', 'block');
    
                   }
               });
           });
    </script>
    
    <script type="text/javascript">
        $(function () {
            $('#SelectForm').change(function () {
                var selectFrom = $(this).find('option:selected').text();
    
                if (selectFrom == "فرم مهارت ها") {
                    $('#PartOne').show();
                    $('#PartOne').css('display', 'block');
                    $('#PartTwo').hide();
                    $('#PartTwo').css('display', 'none');
                    $('#Part3').hide();
                    $('#Part3').css('display', 'none');
                    $('#Part4').hide();
                    $('#Part4').css('display', 'none');
                    $('#Part5').hide();
                    $('#Part5').css('display', 'none');
                    $('#Part6').hide();
                    $('#Part6').css('display', 'none');
    
    
                }
                if (selectFrom == "فرم کتاب/مقالات منتشر شده") {
                    $('#PartTwo').show();
                    $('#PartTwo').css('display', 'block');
                    $('#PartOne').show();
                    $('#PartOne').css('display', 'none');
                    $('#Part3').hide();
                    $('#Part3').css('display', 'none');
                    $('#Part4').hide();
                    $('#Part4').css('display', 'none');
                    $('#Part5').hide();
                    $('#Part5').css('display', 'none');
                    $('#Part6').hide();
                    $('#Part6').css('display', 'none');
    
                }
                if (selectFrom == "فرم سابقه کاری") {
    
                    $('#Part3').show();
                    $('#Part3').css('display', 'block');
                    $('#PartTwo').hide();
                    $('#PartTwo').css('display', 'none');
                    $('#PartOne').show();
                    $('#PartOne').css('display', 'none');
                    $('#Part4').hide();
                    $('#Part4').css('display', 'none');
                    $('#Part5').hide();
                    $('#Part5').css('display', 'none');
                    $('#Part6').hide();
                    $('#Part6').css('display', 'none');
    
    
                }
                if (selectFrom == "فرم دوره‌های تخصصی گذرانده") {
    
                    $('#Part4').show();
                    $('#Part4').css('display', 'block');
                    $('#PartTwo').hide();
                    $('#PartTwo').css('display', 'none');
                    $('#PartOne').show();
                    $('#PartOne').css('display', 'none');
                    $('#Part3').hide();
                    $('#Part3').css('display', 'none');
                    $('#Part5').hide();
                    $('#Part5').css('display', 'none');
                    $('#Part6').hide();
                    $('#Part6').css('display', 'none');
    
                }
                if (selectFrom == "فرم تخصص‌های شغلی") {
    
                    $('#Part5').show();
                    $('#Part5').css('display', 'block');
                    $('#PartTwo').hide();
                    $('#PartTwo').css('display', 'none');
                    $('#PartOne').show();
                    $('#PartOne').css('display', 'none');
                    $('#Part3').hide();
                    $('#Part3').css('display', 'none');
                    $('#Part4').hide();
                    $('#Part4').css('display', 'none');
                    $('#Part6').hide();
                    $('#Part6').css('display', 'none');
    
                }
    
                if (selectFrom == "فرم مدارک تحصیلی") {
    
                    $('#Part6').show();
                    $('#Part6').css('display', 'block');
                    $('#Part5').show();
                    $('#Part5').css('display', 'none');
                    $('#PartTwo').hide();
                    $('#PartTwo').css('display', 'none');
                    $('#PartOne').show();
                    $('#PartOne').css('display', 'none');
                    $('#Part3').hide();
                    $('#Part3').css('display', 'none');
                    $('#Part4').hide();
                    $('#Part4').css('display', 'none');
                }
    
            });
        });
    
    </script>
    
    @Html.DropDownListFor(m=>m.NumberForm, (SelectList)ViewBag.Form, new { id = "SelectForm" })
    
    
    @using (Html.BeginForm())
    {
        @Html.ValidationSummary(true)
    
            <div id="PartOne" >
        <h3 style="font-family: Arial; color: #008080; font-weight: bold; ">@ViewBag.PartOne</h3><br/>
        @foreach (var item in Model.ResumeOfViewModel)
        {
            <table dir="rtl">
                <tr>
                    <td>
                        @Html.Label("عنوان رزومه")
                    </td>
                    <td>
                        @Html.TextBoxFor(model =>item.Title_Of_Resume  , new {@class = "text", style = "width:100 px"})
                        @Html.ValidationMessageFor(model => item.Title_Of_Resume)
                    </td>
                </tr>
                <tr>
                    <td>
            <div id="Gender" >
            @Html.Label("نوع جنسیت")
             @Html.DropDownList("نوع جنسیت", new SelectList(ViewBag.Sex, 
                           "Value", "Text", item.Sex_ID == 0 ? 0 : item.Sex_ID))
            @Html.ValidationMessageFor(model => item.Sex_ID)
            </div>
        </td>
    
                    <td>
                        <div >
                            @Html.Label("وضعیت تاهل")
             @Html.DropDownList("وضعیت تاهل", new SelectList(ViewBag.MartialStatus, 
                           "Value", "Text", item.Martial_Status_ID == 0 ? 0 : item.Martial_Status_ID))
                            @Html.ValidationMessageFor(model => item.Martial_Status_ID)
                        </div>
    
                    </td>
                </tr>
    
                <tr id="Military" style="display: none;">
                    <td>
                        @Html.Label("وضعیت نظام وظیفه")
                    </td>
                    <td>
             @Html.DropDownList("وضعیت نظام وظیفه", new SelectList(ViewBag.MilitaryStatus,
                               "Value", "Text", item.Military_Status_ID == 0 ? 0 : item.Military_Status_ID), new { id = "Gender" })
                        @Html.ValidationMessageFor(model => item.Military_Status_ID)
                    </td>
    
                </tr>
    
                <tr>
                    <td>
                        @Html.Label("آشنایی با رایانه")
                    </td>
                    <td>
                        @Html.DropDownListFor(model => item.Knowledge_Of_Computers_ID, (SelectList)ViewBag.Ability)
                        @Html.ValidationMessageFor(model => item.Knowledge_Of_Computers_ID)
                    </td>
                </tr>
    
                <tr>
                    <td>
                        @Html.Label("آشنایی با امور اداری و دفتری")
                    </td>
                    <td>
                        @Html.DropDownListFor(model => item.Knowledge_Administrative_and_Clerical_ID, (SelectList) ViewBag.Ability)
                        @Html.ValidationMessageFor(model => item.Knowledge_Administrative_and_Clerical_ID)
                    </td>
                </tr>
    
                <tr>
                    <td>
                        @Html.Label("آشنایی با زبان انگلیسی")
                    </td>
                    <td>
                        @Html.DropDownListFor(model => item.Knowledge_Of_English_ID, (SelectList) ViewBag.Ability)
                        @Html.ValidationMessageFor(model => item.Knowledge_Of_English_ID)
                    </td>
                </tr>
    
                <tr>
                    <td>
                        @Html.Label("آشنایی با زبان عربی")
                    </td>
                    <td>
                        @Html.DropDownListFor(model => item.Knowledge_Of_Arabic_ID, (SelectList) ViewBag.Ability)
                        @Html.ValidationMessageFor(model => item.Knowledge_Of_Arabic_ID)
                    </td>
                </tr>
    
                <tr>
                    <td>
                        @Html.Label("آشنایی با ماکروسافت آفیس")
                    </td>
                    <td>
                        @Html.DropDownListFor(model =>item.Knowledge_Of_Office_ID, (SelectList) ViewBag.Ability)
                        @Html.ValidationMessageFor(model => item.Knowledge_Of_Office_ID)
                    </td>
                </tr>
    
                <tr>
                    <td>  
                        @Html.Label("آشنایی با امور مالی و حسابداری")
                    </td>
                    <td>
                        @Html.DropDownListFor(model =>item.Knowledge_Of_Finance_ID, (SelectList) ViewBag.Ability)
                        @Html.ValidationMessageFor(model => item.Knowledge_Of_Finance_ID)
                    </td>
                </tr>
    
                <tr>
                    <td>
                        @Html.Label("آشنایی با مدیریت")
                    </td>
                    <td>
                        @Html.DropDownListFor(model =>item.Knowledge_Of_Manage_ID, (SelectList) ViewBag.Ability)
                        @Html.ValidationMessageFor(model =>item.Knowledge_Of_Manage_ID)
                    </td>
                </tr>
    
                <tr>
                    <td>
                        @Html.Label("گواهینامه رانندگی پایه یک")
    
                    </td>
                    <td>
                        @Html.DropDownListFor(model =>item.Driving_license_One_ID, (SelectList) ViewBag.Ability)
                        @Html.ValidationMessageFor(model =>item.Driving_license_One_ID)
                    </td>
                </tr>
    
                <tr>
                    <td>
                        @Html.Label("گواهینامه رانندگی پایه دو")
                    </td>
                    <td>
                        @Html.DropDownListFor(model =>item.Driving_license_Two_ID, (SelectList) ViewBag.Ability)
                        @Html.ValidationMessageFor(model =>item.Driving_license_Two_ID)
                    </td>
                </tr>
    
                <tr>
                    <td>
                        @Html.Label("گواهینامه رانندگی پایه موتورسیکلت")
                    </td>
                    <td>
                        @Html.DropDownListFor(model =>item.Certificate_Motor_ID, (SelectList) ViewBag.Ability)
                        @Html.ValidationMessageFor(model =>item.Certificate_Motor_ID)
                    </td>
                </tr>
    
                <tr>
                    <td>
                        @Html.Label("ماشین شخصی")
                    </td>
                    <td>
                        @Html.DropDownListFor(model =>item.Personal_Vehicle_ID, (SelectList) ViewBag.Ability)
                        @Html.ValidationMessageFor(model =>item.Personal_Vehicle_ID)
                    </td>
                </tr>
    
                <tr>
                    <td>
                        @Html.Label("روابط عمومی")
                    </td>
                    <td>
                        @Html.DropDownListFor(model =>item.Public_Relationship_ID, (SelectList) ViewBag.Ability)
                        @Html.ValidationMessageFor(model =>item.Public_Relationship_ID)
                    </td>
                </tr>
    
                <tr>
                    <td>
                        @Html.Label("دیگر توانایی ها")
    
                    </td>
                    <td>
                        @Html.EditorFor(model =>item.Etc_Ability)
                        @Html.ValidationMessageFor(model =>item.Etc_Ability)
                    </td>
                </tr>
    
            </table>
        }
            </div>
    
        
            <p>
                <input type="submit" value="Save" onclick="return confirm('از ثبت اطلاعات مطمئن هستید؟')" />
            </p>
    }
    
    <div>
        @Html.ActionLink("بازگشت به مدیریت رزومه ها", "ManageOfResumes")
    </div>
    
    @section scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }
    و مشکل اینجاست که بعد از ثبت اطلاعات وقتی به متد post میره مقدارش null  هستش ... درحالیکه فقط در صورت edit  اینجوریه وقتی از همین viewmodel  برای مشاهده رزومه که فقط گزارشگیریه استفاده میکنم نتیجه را میبینم ولی اینجا نه !
    متد پست بصورت زیر هستش ... اگر میدونید چطور و چی کار کنم که این درست شه ممنون میشم ... چون دیگه نمیدونم تو متد پست چی بنویسم ... منتظر جوابم ... که چرا null میده و اینکه تو متد پست چطور اینارو ذخیره کنم توی db .../؟
            [HttpPost]
            public ActionResult EditResumes(ResumeViewModel model) // model null mishe ! CHERAA??!
            {
                var contex = new Final_My_ProjectEntities2();
                try
                {
                    if (ModelState.IsValid)
                    {
    
                        // Code... che cody?
                        contex.SaveChanges();
                    }
    
                }
                catch (Exception)
                {
    
                    ViewBag.wrong = "لطفا داده‌های ورودی را بررسی نمایید";
                }
                return View(model);
    
            }

    • وحید نصیری در ۱۳۹۲/۰۲/۲۲ ۰:۳۶
      - شما هم از ViewModel استفاده کردی و هم از ViewBag با هم در یک View. از یکی بهتره استفاده کنید. ترجیح هم با ViewModel است تا به خواص آن به صورت strongly typed در یک View دسترسی داشته باشید و تحت کنترل کامپایلر هم باشد (تمام ViewBagها رو حذف و تبدیل به خواص ViewModel کنید).
      - کلاس ViewModel ایی که تدارک دیدید، دارای سازنده‌ای است که باید مقدار دهی شود پیش از استفاده. خوب ... MVC از کجا باید تشخیص بده که در زمان Post اطلاعات به سرور چطور باید این‌رو به صورت خودکار وهله سازی کنه؟ به عبارتی ViewModel شما باید بدون سازنده، قابل وهله سازی باشد. سازنده رو حذف و صرفا از خواص استفاده کنید.
      - برای ثبت نهایی هم باید اطلاعات خواص ViewModel رو (اون‌هایی رو که در Model یا جدول خاص شما وجود دارند) به Model انتساب بدی. بعد این وهله Add شود به Context و دست آخر هم ذخیره.
       (البته کار شما به نظر لایه بندی صحیحی نداره وگرنه جای این مسایل در لایه سرویس برنامه است؛ چه بازگشت ViewModel و چه ذخیره سازی اطلاعات آن)
      • مهمان در ۱۳۹۲/۰۲/۲۲ ۱:۲۸
        من چندتایی سوال پیش اومد برام ::: چرا از نظر لایه بندی مورد داره ؟
        جای کودوم مسائل ؟ viewmodel ؟
        یعنی الان ذخیره سازی اطلاعات کجا باشه ؟ مگه نباید تو قسمت کنترلر اینکار انجام شه ؟ 
        من سازنده‌ها رو حذف کردم و viewmodel  رو صدا زدم ولی بعد از تغییرات وقتی به متد پست فرستاده میشه همچنان مقدارش null  هست ... چرا ؟ :(
        • وحید نصیری در ۱۳۹۲/۰۲/۲۲ ۸:۵۰
          - در مورد اصول اولیه لایه بندی یک دوره 11 قسمتی در سایت هست. بحث مفصلی است و نیاز به پایه تئوری داره.
          - مشکل بعدی کدهای شما به Html.BeginForm بر می‌گرده. زمانیکه پارامتری رو عنوان نکنید به اکشن متد پیش فرض مشخص شده در سیستم مسیریابی اشاره می‌کنه. بهتره که این موارد رو صریحا ذکر کنید تا مشکل نداشته باشید؛ مانند کد زیر. به علاوه شما نمی‌تونید کل یک حلقه رو داخل یک فرم قرار بدید. الان در صفحه، چندین و چند کنترل دریافت اطلاعات دارای یک Id پیدا کردید. اعضای داخل حلقه باید یک فرم را تشکیل بدن؛ در این حالت شیء ارسالی به سرور مثلا Resume خواهد بود و نه ResumeOfViewModel شما که در عمل یک لیست است. بهتر است داخل حلقه این View شلوغ رو Refactor کنید به یک Partial view با مدلی از جنس Resume تا بهتر بتونید مسایل رو مدیریت کنید.
          @using (Html.BeginForm(actionName: "EditResume", controllerName: "SomeName"))  
          {  
          }
          • مهمان در ۱۳۹۲/۰۲/۲۲ ۱۳:۵۸
            مرسی از جوابتون ...
            اینجا یه حلقه هست با اینکه باید 6تا حلقه باشه چون اطلاعات از 6 جدول جدا میاد برای ویرایش شدن با اینکه اینجا فقط مقادیر یه جدول نشون میده 5تا جدول دیگه مونده ... در اینصورت هم از partialview  استفاده کنم ؟
            اگر آره ... لینکی که دراینباره بتونه من رو کمک کنه دارید ؟(خوندن اطلاعات و ...) 
            • وحید نصیری در ۱۳۹۲/۰۲/۲۲ ۱۴:۴
              استفاده از PartialView یکی از روش‌های Refactoring یک View شلوغ هست. اطلاعات بیشتر

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

  • ایلیا اکبری فرد در ۱۳۹۲/۰۴/۲۳ ۲۰:۲۵
    با سلام.
    ویو مدل من دارای چند لیست است که هرکدام از یک جدول خاص از دیتابیس اطلاعاتشان را بدست می‌آورند. حالا اگر کاربر اطلاعات را اشتباه وارد کرد و ما دوباره قرار است فرم را به او با همان اطلاعات قبلی نمایش دهیم ، آیا منطقی است که برای پرکردن لیست‌های مورد نیاز دوباره به دیتابیس کوئری بزنیم یا روش بهتری وجود دارد؟ با تشکر.
    • محسن خان در ۱۳۹۲/۰۴/۲۴ ۹:۳۸
      روش با سربار کم استفاده از Ajax است و به روز رسانی فقط قسمتی از صفحه بجای به روز رسانی کل یک صفحه شلوغ.
  • محمد آزاد در ۱۳۹۲/۰۴/۲۴ ۱۳:۵۵
    من می‌خواستم بدونم ViewModel با  DTO فرقی داره؟
    الان اگه من یک ویو دارم که با اطلاعات چند Dto  کار میکنه آیا تعریف یک viewModel بصورت زیر صحیح هستش؟    
     public class ProjectViewModel{
            public ProjectDto Project{ get; set; }
            public ProjectProgramDto ProjectProgram { get; set}
            public IEnumerable<SelectListItem> PriorityListItems { get; set; }
         }
    • محسن خان در ۱۳۹۲/۰۴/۲۴ ۱۴:۴

      یک رای‌گیری در این مورد در حال انجام است

      «در ASP.NET MVC آیا ViewModel همان DTO است؟ »

      • محمد آزاد در ۱۳۹۲/۰۴/۲۴ ۱۴:۱۵
        یعنی جواب قطعی براش نیست؟چون رای گیری نمیتونه ملاک خوبی باشه بنظرم
  • حمیدرضا م در ۱۳۹۲/۱۱/۲۴ ۱۳:۴۴
    با سلام؛ لطفا درباره @section speakers  یکم توضیح بدین. این @Section به چه کار آید ؟
    حدس من اینه که با این دستور بشه توی یک مدل کلی بخش (مثل ماژول) رو تعریف کرد و توی یک ویو بتونیم در جاهای مختلف این Section‌ها رو نمایش بدیم ؟ (عدم نیاز به چند Partial View و نوشتن همه توی یک ویو)
  • مجتبی فخاری در ۱۳۹۲/۱۲/۱۵ ۰:۲
    با سلام؛ برای استفاده از ViewModel در زمان اجرا بعد از این که روی دکمه جدید کلیک می‌کنم این خطا را می‌دهد:
    Either ErrorMessageString or ErrorMessageResourceName must be set, but not both.
    میشه راهنمایی کنید؟
  • منصور جعفری در ۱۳۹۲/۱۲/۲۶ ۲۰:۵۷
    سلام؛ وقتی رو صفحه اصلی سایت کاربر روی ادامه مطلب کلیک میکنه و وارد صفحه مربوط به اون مطلب میشه، صفحه جدید از یک پارشال ویوو تشکیل شده که دارای یک تگ فرم هست برای ارسال نظرات کاربران و هم چنین یک پارشال ویوو دیگر برای نمایش مطلب کامل اون لینک میباشد. برای استفاده هردو مدل یک view model تعریف شده که شامل هر دو موجودیت‌ها است. وقتی توی ویوو اصلی دکمه ادامه مطلب زده میشه این ارور داده میشه:

    The model item passed into the dictionary is of type 'Class.Domain.Enities.Product', but this dictionary requires a model item of type 'WebAli.ViewModel.ProductCommentListViewModel'. 

    • وحید نصیری در ۱۳۹۲/۱۲/۲۶ ۲۳:۱۲
      این خطا به این معنا است که در اکشن متد کنترلر متناظر، خروجی نهایی و مدل ارسال شده به View، از جنس تک شیء Product است؛ اما این View نیاز به دریافت مدلی از کنترلر، از جنس ProductCommentListViewModel دارد (نوع خروجی اکشن متد را بررسی کنید).
      حتی در حالت RenderPartial هم ممکن است این خطا را دریافت کنید. کلا در هر جایی که شیء‌ایی به یک View برای رندر ارسال می‌شود، نوع آن و نوع مدل تعریف شده View را تطابق دهید.
      • اسدی در ۱۳۹۳/۰۲/۰۲ ۸:۳۳
        سلام، من توی مدل پراپرتی از نوع DateTime? دارم که توی view اون رو با کنترل datepicker نمایش میدم. مشکل اینجاست که مقداری که به مدل پاس میشه، تاریخ شمسی هستش و مدل انتظار datetime رو داره. نهایتا توی uow.SaveChanges با این خطا مواجه میشم:
        the conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value

  • جمشیدی فر در ۱۳۹۳/۰۵/۲۹ ۱۸:۱۶
    من یک پروژه چندلایه دارم که شامل لایه‌های Domain که همه Entity‌ها درون آن تعریف شده اند و لایه سرویس و لایه Presentation.  مشکلی در مورد Validation سمت کلاینت دارم. هنگامی که برای یک View  از مدلی که در لایه Domain تعریف شده استفاده میکنم، Validation سمت کلاینت و بدون رفرش صفحه انجام میشه اما هنگامی که از ViewModel تعریف شده در لایه Presentation استفاده می‌کنم، Validation با رفرش صفحه انجام میشه. دلیلش چیه؟
  • مهمان در ۱۳۹۳/۰۷/۲۱ ۱۹:۵۸
    با سلام و درود به شما عزیزان
    من  یه مشکلی  دارم و  اون هم اینکه من می‌خواهم یک select new   روی  مدلم بزنم ولی  چون نام فیلدها جدید به همیم خاطر در Partial View   یا  View   اون ‌ها رو نمی‌شناسه   آیا  راهکاری   دارید؟
            var models = from x in db.tblFinalProjects
                             select x; 
                           {
                                PTitle=x.xProjectTitle,
                                ZTitle=x.tblZone.xCaption,
                                 PLastProgress=x.xLastProgress,
                                PStatus=x.tblCurrentStatu.xCaption,
                                PMasool="",
                             };
    این    متغیر   من هستش ولی  مدل  من tblFinalProject  هست که  بصورت Strongly Type  به   View  پاس میدم  اما  نمی‌تونم روی فیلدهای جدید  کار  کنم . چون مدل  اصلی  رو  میذاره ولی سلکت جدید  من تلفیقی از  جداولی است  که  به هم ارتباط  دارن
    مرسی
    • محسن خان در ۱۳۹۳/۰۷/۲۱ ۲۱:۵۳
      معادل فیلدهایی که select کردی، یک کلاس جدید ViewModel درست کن. بعدی این select رو روی اون انجام بده (بجای اینکه مثل الان anonymous type باشه). نوع View رو هم از نوع لیستی از همین ViewModel جدید تعیین کن. به این نکته LINQ projection می‌گن.
      public class MyViewModel
      {
        public string PTitle {set;get;}
        // مابقی خواص در اینجا
      }
      
      var list = from x in db.tblFinalProjects
                       select new MyViewModel
                     {
                          PTitle=x.xProjectTitle,
                          ZTitle=x.tblZone.xCaption,
                           PLastProgress=x.xLastProgress,
                          PStatus=x.tblCurrentStatu.xCaption,
                          PMasool="",
                       };