تفاوت ViewData و ViewBag و TempData و Session در MVC
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: یک دقیقه

در MVC راه‌های متفاوتی برای ارسال اطلاعات از controller به view و در redirect‌ها وجود دارد. در این مقاله سعی شده تفاوت‌های آنها به صورت مختصر نمایش داده شود. این مقاله در حقیقت یک ترجمه آزاد از این  مقاله  است که امیدوارم خوب ترجمه شده باشد.
ViewData:
  • ViewData یک نوع دیکشنری ویژه است که از ViewDataDictionary ارث بری کرده است.
  • برای ارسال اطلاعات از controller به view استفاده می‌شود.
  • مدت زمان اعتبار مقادیر آن تنها در request جاری است.
  • اگر redirect بین صفحات رخ دهد، مقدار آن null خواهد شد.
  • به دلایل امنیتی باید قبل از استفاده، null بودن آن تست شود.
  • برای بهره برداری باید cast صورت پذیرد.

ViewBag:
  • یک نوع dynamic است (این نوع در c# 4 معرفی شده است).
  • مانند ViewData برای ارسال اطلاعات از کنترلر به view استفاده می‌شود.
  • مدت زمان اعتبار مقادیر آن تنها در request جاری است.
  • اگر redirect بین صفحات رخ دهد، مقدار آن null خواهد شد.
  • به دلایل امنیتی باید قبل از استفاده، null بودن آن تست شود.
  • برای بهره برداری، cast نیاز نیست. بنابراین سریعتر عمل می‌کند.

TempData:
  • نوع خاصی از دیکشنری است که از TempDataDictionary مشتق شده است.
  • مدت عمر کوتاهی دارد و برای ارسال اطلاعات بین صفحات (در redirect) قابل استفاده است.
  • وقتی view‌ها به صورت کامل اجرا شود، مقادیر آن null می‌شود.
  • به دلایل امنیتی باید قبل از استفاده، null بودن آن تست شود.
  • برای بهره برداری باید cast صورت پذیرد.

Session:
  • برای ارسال اطلاعات بین request‌های مختلف مورد بهره برداری قرار می‌گیرد.
  • مقادیر آن null نمی‌شود. تنها پس از گذشت زمان مشخصی (session expire) مقادیر آن null می‌شود.
  • به دلایل امنیتی باید قبل از استفاده null بودن آن تست شود.
  • برای بهره برداری، باید cast صورت پذیرد.  
  • #
    ‫۱۰ سال و ۳ ماه قبل، یکشنبه ۲۵ خرداد ۱۳۹۳، ساعت ۰۳:۵۰
    سلام
    برای متغیرهای سراسری که در طول اجرای برنامه لازم است مقدار آنها حفظ شود کدام یک را پیشنهاد می‌کنید
    مثلا نگهداری سال مالی جاری در یک سیستم مالی
    • #
      ‫۱۰ سال و ۳ ماه قبل، یکشنبه ۲۵ خرداد ۱۳۹۳، ساعت ۱۵:۵۱
      چون این اطلاعات سراسری به ازای یک کاربر معنا پیدا می‌کنند و به ازای هر کاربر لاگین شده به سیستم می‌توانند متفاوت باشند، استفاده از سشن، کوکی و یا HTML5 local storage برای اینکار مفید هستند.
      • #
        ‫۱۰ سال و ۳ ماه قبل، یکشنبه ۲۵ خرداد ۱۳۹۳، ساعت ۲۰:۱۸
        من از Session استفاده می‌کنم. ولی در زمان اجرا پس از مدتی خالی میشه. چیکار کنم مقدارش رو حفظ کنه.
        • #
          ‫۱۰ سال و ۳ ماه قبل، یکشنبه ۲۵ خرداد ۱۳۹۳، ساعت ۲۲:۴۱

          می‌تونید محل ذخیره سشن رو بجای حافظه، یک بانک اطلاعاتی SQL Server تعیین کنید: http://support.microsoft.com/kb/317604

          یا اخیرا بجای SQL Server از بانک‌های اطلاعاتی NoSQL از نوع key/value store هم برای اینکار استفاده می‌کنند: ASP.NET Session State Provider for Redis

  • #
    ‫۱۰ سال و ۳ ماه قبل، چهارشنبه ۲۸ خرداد ۱۳۹۳، ساعت ۱۶:۱۹

    مطلب خوب و جالبی بود، کاش تصویر  موجود در مقاله منبع رو توی مقاله تون میاوردین، به نظرم خیلی تصویر گویا و جالبی هست 

  • #
    ‫۶ سال و ۷ ماه قبل، یکشنبه ۲۹ بهمن ۱۳۹۶، ساعت ۱۲:۴۵
    ممنون.
     لیستی از ویو مدل را در یک اکشنی به صورت زیر در TempData ذخیره کرده ام:
    TempData["PaymentMethodsWithshippingMethods"]= await _paymentMethodService.FindAllWithShippingMethodsAsync();
    حال میخواهم که در یه اکشن متد دیگری محتویات آن را بخوانم برای این کار راه‌های مختلفی را امتحان نمودم ولی هر کدام از آنها با error زیر مواجه میشدم یکی از روش هایی که امتحان نمودم به صورت زیر است:
    var paymentMethodsWithshippingMethods = TempData
                    .Where(x => x.Key.Contains("PaymentMethodsWithshippingMethods"))
                    .Select(x => new { value = (PaymentMethodViewModel)x.Value })
                    .Select(x => new PaymentMethodViewModel
                    {
                        PaymentMethodId = x.value.PaymentMethodId,
                        Type = x.value.Type,
                        ShippingMethods = x.value.ShippingMethods.Select(y =>
                        new ShippingMethodViewModel
                        {
                            ShippingMethodId = y.ShippingMethodId,
                            DiscountPrice = y.DiscountPrice,
                            ProductPrice = y.ProductPrice,
                            Tax = y.Tax,
                            Type = y.Type,
                            Cost = y.Cost,
                        }).ToList()
                    }).ToList();
     ولی روش فوق در هنگام cast کردن ارور زیر را می‌دهد:
    Unable to cast object of type 'System.Collections.Generic.List`1[MeMarketShop.ViewModel.PaymentMethod.PaymentMethodViewModel]' to type 'MeMarketShop.ViewModel.PaymentMethod.PaymentMethodViewModel'.
    لطفا راهنمایی نمایید که چطور می‌توان لیستی از ویو مدل را از TempData خواند. ممنون
    • #
      ‫۶ سال و ۷ ماه قبل، یکشنبه ۲۹ بهمن ۱۳۹۶، ساعت ۱۶:۰۳
      به این صورت عمل نمودم مشکل برطرف شد:
      viewModel.PaymentMethods = (List<PaymentMethodViewModel>)TempData["PaymentMethodsWithshippingMethods"];

  • #
    ‫۶ سال و ۵ ماه قبل، یکشنبه ۱۹ فروردین ۱۳۹۷، ساعت ۲۰:۵۶
    سلام؛ مواقعی که سیستم ناوبری و منوی برنامه بصورت داینامیک و RoleBase  هست و به ازای هر کاربر منوی خاصی فعال میشود. برای اینکه کاربر در ابتدای ورود به سیستم لیست منوی مربوط به خود را از دیتابیس واکشی کند و تا زمان خروج این لیست در دسترس بماند و نیاز به مراجعه مجدد به دیتابیس نباشد چه روشی پیشنهاد میشود.