Edited
I have an ASP.NET Core 2.1 website which I've scaffolded all of its Identity items. The scaffolding process created a layout file in this location:
/Areas/Identity/Pages/Account/Manage/_Layout.cshtml
As I wanted to use the layout globally, I have moved the layout file (with cut-paste) to this new location:
/Views/Shared/AdminLayout/_Layout.cshtml
Then created a _ViewStart.cshtml
file in the first location to use the layout in the 2nd location. The content of _ViewStart
file is this:
@{
Layout = "/Views/Shared/AdminLayout/_Layout.cshtml";
ViewData["ThisOneWorks"] = "some value";
}
Now the problem is, ViewData
s that I set from scaffolded pages (e.g. SetPassword.cshtml
, ExtenalLogins.cshtml
, ...) are not working in the layout file. For example ViewData["Title"]
is always empty, but the ViewData
that I've set in the _ViewStart
is working.
The question is, How can I use ViewData
from scaffolded identity files when I'm using a layout from the shared view folder?
Edit 1:
It seems the problem is with this line:
ViewData["ThisOneWorks"] = "some value";
When I remove it from the _ViewStart
, all other ViewData
s work correctly, but why?
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.
In MVC, when we want to transfer the data from the controller to view, we use ViewData. It is a dictionary type that stores the data internally. ViewData contains key-value pairs which means each key must be a string in a dictionary. The only limitation of ViewData is, it can transfer data from controller to view.
The ControllerBase class has a ViewData dictionary property that can be used to populate data on controller and view. ViewData is a derivative of the ViewDataDictionary class, so you can access by the familiar "key/value" syntax, in other words it is a dictionary of objects that are accessible using strings as keys.
Well , it take me quite a lot of time to reproduce the same issue and debug . And finally , I find out it's a known bug .
If you try to render a page that has an associated _ViewStart.cshtml
, and if you set the ViewData
within the ViewStart
at the same time , the _Layout.cshtml
will not render its ViewData
correctly .
In short , the reason is that the ViewData
within the Layout
is the ViewContext.ViewData
, instead of the this.ViewData
that you set in your page . See the detailed explanation here
The bug has been fixed in 2.2.0-preview1
, and unfortunately there's no plan to fix it in 2.1.x
. If you don't want to update your sdk , you can use the HttpContext.Items
. Set Items
in your RazorPage :
@{
ViewData["Title"] = "Profile"; // not working
HttpContext.Items["Title"]="Workaround - Title"; // workaround
}
render Items
in your _Layout
:
<h1>@Context.Items["Title"]----render in layout</h1>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With