Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How share ViewData between ViewComponent in Asp.net core

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();
    }
}
like image 408
Mohammad Akbari Avatar asked May 07 '17 06:05

Mohammad Akbari


People also ask

How do I pass ViewData to view?

To pass the strongly-typed data from Controller to View using ViewData, we have to make a model class then populate its properties with some data and then pass that data to ViewData dictionary as Value and selecting Key's name is the programmer's choice.

How do I pass TempData to view?

Passing the data from Controller to View using TempData Go to File then New and select “Project” option. Then create the ASP.NET web application project as depicted below. Then select “Empty” and tick “MVC” then click OK. The project is created successfully.

How do you pass value from view to controller using ViewData?

ViewData itself cannot be used to send data from View to Controller and hence we need to make use of Form and Hidden Field in order to pass data from View to Controller in ASP.Net MVC Razor.

When should we use ViewData in asp net core?

All three objects are available as properties of both the view and controller. As a rule of thumb, you'll use the ViewData, ViewBag, and TempData objects for the purposes of transporting small amounts of data from and to specific locations (e.g., controller to view or between views).


2 Answers

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.
like image 172
CodeNotFound Avatar answered Nov 15 '22 21:11

CodeNotFound


Imho this is an indicator that ViewComponents 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.

like image 20
Tseng Avatar answered Nov 15 '22 21:11

Tseng