How share ViewData between ViewComponent in Asp.net core
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 callTempData.Keep()
- You can easily test your view compnent when you use
TempData
because it is an interface of typeITempDataDictionary
which can be mocked without difficulty.
Imho this is an indicator that ViewComponent
s are not suitable for your use case. You should use partial views instead.
Partial views are executed in the context of their parent'S view action and additionally you can pass a model to the partial, i.e. a product from a product list.
@Html.Partial("PartialName", customViewData)
In your example above, you'd provide "one"
and "two"
as the partial's model parameter @Html.Partial("PartialName", "one")
, @Html.Partial("PartialName", "two")
ViewComponents are more like reusable blocks of logic and view which act similarly to a controler + action.
But unlike controller + action, the ViewComponent
can be reused in multiple places.
ViewComponents should be self-sufficient and do not depend on data outside of them.
This also further more indicates that you are trying to move application related logic from an action to the view and that your data from your controller action isn't sufficiently prepared for the view to consume.
The controller's action has only 3 simple tasks: Validate user input, call the underlying application code (commonly called services) and prepare the service results for the view to consume it. That being said, a better solution may be, to use a viewmodel in your action (instead of ViewData
which is untyped), prepare all the data you need and then let the view just display that data.