-3

I have some data specific to each razor view and and i do not want to hard-code it to each view. So, i want to add view related compile-time data to each view.

  • Custom attributes do not work for me because we cannot add custom attributes to razor views.
  • I do not want to re-fetch/populate this data from the data source(dictionary etc.) for each request or when view reached.

So, is there any way to attach data to each view at once throughout the life time of asp.net application?

Note Actually i want to add scripts/styles generated by webpack for each view statically. Their links include hash values so they change when source scripts/styles change. So, i just want to get them added to each view only once(equivalent to typing them into view) through out the asp.net application, not every time a view loads.

lockedscope
  • 965
  • 17
  • 45
  • 1
    why are you using razor-pages? this really sounds like the job of mvc – Neville Nazerane Jan 20 '18 at 09:07
  • Razor pages or views, it does not matter. – lockedscope Jan 20 '18 at 09:27
  • 1
    I am not sure what you want. Do you want to display different view from the OnGet method or you want to display different razor page depending on the data passed through URL using custom routing? – pitaridis Jan 20 '18 at 19:09
  • Actually i want to add scripts/styles generated by webpack for each view statically. Their links include hash values so they change when source scripts/styles change. So, i just want to get them added to each view only once(equivalent to typing them into view) through out the asp.net application, not every time a view loads. – lockedscope Jan 22 '18 at 08:33
  • 1
    Why not add the hard coded links to a layout page or partial view? If they change at compile time every time, you'll have to have them as a static property in the model as per Neville Nazerane's answer. – zola25 Jan 25 '18 at 17:16
  • It makes little sense to hardcode values which ultimately are the output of a Webpack build process into the view at *compilation time* of the web application. In your normal development flow, you are very likely to invoke your Webpack build without wanting to rebuild your whole application. You might want to look into the `asp-append-version` attribute of the script tag helper which allows you to append a version to the file so it avoids the cache. Other than that, you could use the JavaScriptServices to actually talk with Webpack. – poke Jan 28 '18 at 19:11

3 Answers3

1

I created a demo application for you here.

You will want to use your appsettings.json file, and inject your settings into your view.

In my appsettings.json I added a section called "ViewConfiguration":

"ViewConfiguration": {
    "ExampleKey": "ExampleValue"
}

Your various values will need to go into your ViewConfiguration section.

For example where I have ExampleKey, you will use a generic name like "IndexPageStyleSheet", and where I have ExampleValue, you will need to update each release with the new stylesheet path. This will only need to be updated when the filename changes.

I then created a ViewConfiguration class which stores all of the values from the appsettings.json file.

You will need to create one property per configuration line, and ensure that the name of the property matches the name of the key in your appsettings.json.

For example where my appsettings.json has ExampleKey, my ViewConfiguration class also has an ExampleKey.

public class ViewConfiguration {
    public string ExampleKey { get; set; }
}

In your Startup.cs you will need to tell your IOC container to load your configuration values into your configuration object.

In my Startup.cs, my ConfigureServices method loads my "ExampleValue" into ViewConfiguration.ExampleKey automatically.

    public void ConfigureServices(IServiceCollection services) {
        // This line is the magic that loads the values from appsettings.json into a ViewConfiguration object.
        services.Configure<ViewConfiguration>(Configuration.GetSection("ViewConfiguration"));

        services.AddMvc();
    }

Now, in my _ViewImports.cshtml I inject my ViewConfiguration object so that I don't need to inject it into every single page. This can be anywhere in the _ViewImports.cshtml file. If you only want to inject specific configuration per folder, you can create a new _ViewImports.cshtml file per folder and inject different configuration objects into each one. It's flexible.

@using Microsoft.Extensions.Options;

@* Please rename this variable to something more appropriate to your application: *@
@inject IOptions<ViewConfiguration> InjectedViewConfig

Now, in any page, you can simply reference the property in your ViewConfiguration object.

For example in my Index.cshtml, I reference the ViewConfiguration.ExampleKey property by referencing the strongly typed property on InjectedViewConfig.Value, and it outputs "ExampleValue" on the page.

This value could just as easily be injected into a script or css link tag as the name of a file. It's very flexible.

<h1>Value: @InjectedViewConfig.Value.ExampleKey</h1>

Example output

With further research, you will be able to inject these values from any configuration source, such as Azure application settings or Azure Key Vault. Please see this article for more details.

Jim Yarbro
  • 2,063
  • 15
  • 21
  • I appreciate the effort but i do not want to use magic property names for each view, i want values associated with path and so i do not want to type Path in each view but just access those properties. And beyond all i want to have them statically compiled into views, not fetched from a class or dictionary each time a view accessed but only once per view throughout the life cycle of application. But it seems almost impossible besides some template engine or compilation override. – lockedscope Jan 26 '18 at 14:24
  • 2
    @lockedscope Unfortunately razor pages are not intended to be implemented like that. MVC is a convention over configuration framework, and what you're attempting is not conventional. You are correct, it would definitely be better to look into another view engine if you cannot use a conventional approach. – Jim Yarbro Jan 26 '18 at 14:55
  • But configuring views might be good. With the advance of compilation nowadays, we should be easily tamper with the compilation of views. – lockedscope Jan 26 '18 at 15:22
  • 2
    @lockedscope Well in this case I think the conventional approach is to use bundleconfig.json and use the built in bundling engine rather than webpack. Please see [this article](https://learn.microsoft.com/en-us/aspnet/core/client-side/bundling-and-minification) for more information on bundleconfig.json – Jim Yarbro Jan 26 '18 at 15:47
  • That's good but I don't think that it supports wide range of options/plugins like webpack. – lockedscope Jan 26 '18 at 19:51
0

If you are using mvc, you can create models and add it into the views. Since you don't want to recreate for each view, you can create readonly variables.

static readonly MyModel ModelData = new MyModel { PropName = "Hello" };
public IActionResult Index () => View(ModelData);

In your view you can now strongly type the value. If you are looking to use MVVM, you can refer to ViewModel concept still exists in ASP.NET MVC Core?

Neville Nazerane
  • 6,622
  • 3
  • 46
  • 79
0

Implementing IFileProvider and IFileInfo provides changing the contents of view at compile-time. So, we could replace and provide static data in views with a template engine(i.e. http://dotliquidmarkup.org/).

Check this; https://www.mikesdotnetting.com/article/301/loading-asp-net-core-mvc-views-from-a-database-or-other-location

lockedscope
  • 965
  • 17
  • 45