Create Global Variable in .Net Core 2.0 to Use in Razor Views

How can I set a global variable in Razor Pages of ASP.NET Core?

HTTP requests work by clients sending a request (with header and body) to your server. Your server can then access this info and send a response. This doesn't create any persistent (ongoing) connection between the server and client. This means there is no permanent link between your server and each client. Any global variable you declare will be global for your server's web application and will be common for every client.

What you are trying to do here is create variables isolated from each client's connection. Normally this is done with the help of Session or Cookie variable. But in this case, I don't see how this will improve any performance over the code you have written. In your code, you are trying to access the Http Headers from the request. Cookies and session variables are also accessed in a very similar way. If anything fetching directly from headers must have a slightly better performance. If you are trying to clean up your code so you don't have to write this on every page, services could be quite helpful.

You can create a class for service something like this:

public class AgentChecker
{

public bool IsIE { get; set; }

// makes sure check is done only when object is created
public AgentChecker(IHttpContextAccessor accessor)
{
string UA = accessor.HttpContext.Request.Headers["User-Agent"].ToString();
if (UA.Contains("Trident") || UA.Contains("MSIE"))
{
IsIE = true;
}
else
{
IsIE = false;
}
}

// optional to simplify usage further.
public static implicit operator bool(AgentChecker checker) => checker.IsIE;

}

In your startup class add the following:

// to access http context in a service
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// makes sure object is created once per request
services.AddScoped<AgentChecker>();

Once this is set up, in your view you can use:

@inject AgentChecker checker

@* if you didn't create the implicit operator, you can use if (checker.IsIE) *@
@if (checker)
{
<div>Is ie</div>
}
else
{
<div>not ie</div>
}

The inject goes at the top of any view page you would like to use this in. While this still creates a new object each request, it is cleaner to use and only creates one object no matter how many partial views you are using.

Define global variable in _ViewStart.cshtml

In the _ViewImports.cshtml you can inject the variable like this:

@using MyApp.AspNetCore
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

@{
string UserEmail = "test@test.com";
}
@inject string UserEmail;

In the Index.cshtml you can reference it by its name:

<span>Hello @UserEmail </span>

Sharing variable across Razor views in ASP .NET Core 3.1

"Instead of creating variables, you're better off injecting a service that will generate the values you need as required."

as written by DavidG @ https://stackoverflow.com/a/47858367/2768479

Global Variables in ASP.Net Core 2

I often do this kind of thing with connection strings and other global constants. First create a class for those variables that you need. In my project it is MDUOptions but whatever you want.

public class MDUOptions
{
public string mduConnectionString { get; set; }
public string secondaryConnectionString { get; set; }
}

Now in your Startup.cs ConfigureServices method:

Action<MDU.MDUOptions> mduOptions = (opt =>
{
opt.mduConnectionString = Configuration["ConnectionStrings:mduConnection"];
});
services.Configure(mduOptions);
services.AddSingleton(resolver => resolver.GetRequiredService<IOptions<MDUOptions>>().Value);

Now you use DI to access it in code:

public class PropertySalesRepository : IPropertySalesRepository
{
private static string _mduDb;

public PropertySalesRepository(MDUOptions options)
{
_mduDb = options.mduConnectionString;
}
....
}

In my case the only property I wanted was the string but I could have used the entire options class.

Global Variables in Razor View Engine

You could use ViewBag.Title inside the layout:

<html>
<head>
<title>@ViewBag.Title - Site Name</title>
</head>
<body>
<div>
@RenderBody()
</div>
</body>
</html>

and then define this variable inside the view:

@model AppName.Models.Product
@{
ViewBag.Title = Model.Name;
}

UPDATE:

Following on the comments question about default values you could use sections.

<html>
<head>
<title>
@if (IsSectionDefined("Title"))
{
RenderSection("Title")
}
else
{
<text>Some default title</text>
}
</title>
</head>
<body>
<div>
@RenderBody()
</div>
</body>
</html>

and then inside your view you could redefine the section if you will:

@section Title {
<text>some redefined title here</text>
}

Application Variables in ASP.NET Core 2.0

A lot has progressed in the last 100 years. Some time ago, I believe in ASP.NET 1.0, the Application object in ASP classic was superseded with caching (although the Application object was left in for backward compatibility with ASP classic).

AspNetCore has replaced the caching mechanism of ASP.NET and made it DI-friendly, but it is still very similar to how the state of things was in ASP.NET. The main difference is that you now need to inject it instead of using the static HttpContext.Current.Cache property.

Register the cache at startup...

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
services.AddMvc();
}

public void Configure(IApplicationBuilder app)
{
app.UseMvcWithDefaultRoute();
}
}

And you can inject it like...

public class HomeController : Controller
{
private IMemoryCache _cache;

public HomeController(IMemoryCache memoryCache)
{
_cache = memoryCache;
}

public IActionResult Index()
{
string companyName = _cache[CacheKeys.CompanyName] as string;

return View();
}

Then to make it work application wide, you can use a filter or middleware combined with some sort of cache refresh pattern:

  1. Attempt to get the value from the cache
  2. If the attempt fails

    • Lookup the data from the database
    • Repopulate the cache
  3. Return the value

public string GetCompanyName()
{
string result;

// Look for cache key.
if (!_cache.TryGetValue(CacheKeys.CompanyName, out result))
{
// Key not in cache, so get data.
result = // Lookup data from db

// Set cache options.
var cacheEntryOptions = new MemoryCacheEntryOptions()
// Keep in cache for this time, reset time if accessed.
.SetSlidingExpiration(TimeSpan.FromMinutes(60));

// Save data in cache.
_cache.Set(CacheKeys.CompanyName, result, cacheEntryOptions);
}

return result;
}

Of course, you could clean that up and make a service with strongly typed properties as a wrapper around your cache that is injected into controllers, but that is the general idea.

Note also there is a distributed cache in case you want to share data between web servers.

You could alternatively use a static method or a statically registered class instance, but do note if hosting on IIS that the static will go out of scope every time the application pool recycles. So, to make that work, you would need to ensure your data is re-populated using a similar refresh pattern.

The primary difference is that with caching there are timeout settings which can be used to optimize how long the data should be stored in the cache (either a hard time limit or a sliding expiration).

Populating global variable in razor view using JQuery (MVC)

Remember that @{} code runs server-side, so before it gets to the browser. Once it has "rendered" in the browser, it's as if it was plain text and can't be changed.

You can pass your parameters by building them in the script, eg:

Remove the param from the Url.Action arguments

<input type="text" data-id="@item.Item1" class="form-control prop"/>
<a class="btn btn-default" id="run-report" href="@Url.Action("RunReport", "Reports", new {reportId = Model.ReportId})"> Run Report</a>

Add them via script

$("#run-report").click(function () {

var url = $(this).attr("href");

$(".prop").each(function () {
var currentProp = $(this).data("id");
var currentPropVal = (this).value;

url += "?" + currentProp + "=" + currentPropVal;
});

location.href = url;
});

Depending on the format expected by your action, you may need to change how your url is built, but this shows the principle.



Related Topics



Leave a reply



Submit