How share ViewData between ViewComponent in Asp.net core

Mohammad Akbari picture Mohammad Akbari · May 7, 2017 · Viewed 8k times · Source

I have two ViewComponent and i want use ViewData or other technic for share some data between and then use this data in main view, but this is not the way, and ViewData per ViewComponent is null when rich to if condition for both ViewComponent.

public class OneViewComponent : ViewComponent
{
    public async Task<IViewComponentResult> InvokeAsync(Page page, Zone zone)
    {
        //some operation

        string text = "one";

        if(ViewData["data"] != null)
        {
            ViewData["data"] = ViewData["data"].ToString() + text;
        }
        else
        {
            ViewData["data"] = text;
        }

        return View();
    }
}

public class TwoViewComponent : ViewComponent
{
    public async Task<IViewComponentResult> InvokeAsync(Page page, Zone zone)
    {
        //some operation

        string text = "two";

        if(ViewData["data"] != null)
        {
            ViewData["data"] = ViewData["data"].ToString() + text;
        }
        else
        {
            ViewData["data"] = text;
        }

        return View();
    }
}

Answer

CodeNotFound picture CodeNotFound · May 7, 2017

ViewData is just like ViewBag. You use it only if you want to transfer data from Controller to View. For this I always prefer View Model.

For transferring data across component you have the following two options:

Using TempData dictionary instead of ViewData dictionary: you need to install the following package

Install-Package Microsoft.AspNetCore.Mvc.ViewFeatures

In your Startup class, add this line

services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();

to your ConfigureServices method. I use CookieTempDataProvider as impelmentation of ITempDataProvider but you can use SessionStateTempDataProvider.

To store data into TempData dictionary you use this code:

this.TempData["data"] = "my value";

To retrieve data from TempData you use this code:

var data = this.TempData["data"];

To use it in your component view:

@this.TempData["data"]

Using HttpContext.Items dictionary: there is no package to install. In your view component class, store your data in HttpContext.Items dictionary like this:

this.HttpContext.Items["data"] = "my value"; 

And access to the data stored by doing this:

var data = this.HttpContext.Items["data"];

In your component view, you can get the stored data by doing this:

@this.Context.Items["data"]

The difference between TempData and HttpContext.Items: the main difference between HttpContext.Items and TempData dictionary is:

  • HttpContext.Items is cleared when the request ends.
  • By default TempData is cleared when the data is read. To retain the data you need to explicitly call TempData.Keep()
  • You can easily test your view compnent when you use TempData because it is an interface of type ITempDataDictionary which can be mocked without difficulty.