In-Memory Cache with .NET EF Core throws error - asp.net-core

I have a .Net Core application with EF which returns a page called Customer as home page. But I need show an app not available page (AppNotAvialable.cshmtl) when the user tries to access the application on a holiday(holiday list is stored in a table)instead of the Customer page. Instead of querying the holiday list table every time the home page is accessed I am trying to use the In-Memory Cache so I can store the query response in cache and use them in the controller. I am implementing the cache for the 1st time and below is what I tried
public class CustomersController : Controller
{
private readonly SurplusMouseContext _context;
private readonly IMemoryCache memoryCache;
.......................
public async Task<IActionResult> Index(string sortOrder, string searchString,
int? pageNumber, string currentFilter)
{
int holidaycheck;
var timeUtc = DateTime.UtcNow;
var easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var todayDt = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, easternZone);
bool isExist = memoryCache.TryGetValue("HolidayWk", out holidaycheck);
if (!isExist)
{
holidaycheck = (from hc in _context.HolidayWeeks
where hc.HolidateDate.Date == todayDt.Date
select hc).Count();
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromHours(2));
memoryCache.Set("HolidayWk", holidaycheck, cacheEntryOptions);
}
if (holidaycheck != 0)
{
return View("/Views/Customers/AppNotAvailable.cshtml");
}
else
{
when I try to debug the application it throws error like below
Can anyone please suggest if I am implementing the in Memory Cache here correct/missing anything and where should I be doing the cacheMemory.Remove() Any help is greatly appreciated

The first step to check:
In your question, it is possible you didn't initialize MemoryCache object in the constructor.
There is an example of MemoryCache.
1 - You should register MemoryCache in services like this:
services.AddMemoryCache();
2 - Inject IMemoryCache interface in your controller and initialize it.
public class YourController : Controller
{
private readonly IMemoryCache _memoryCache;
public YourController(IMemoryCache memoryCache)
{
_memoryCache = memoryCache
}
}
3 - Using memory cache:
public async Task<IActionResult> Index(string sortOrder, string searchString,
int? pageNumber, string currentFilter)
{
bool isExist = _memoryCache.TryGetValue("HolidayWk", out holidaycheck);
}

Related

Using GetGridHtml in a controller in Umbraco 10

I have made a simple Api controller on my umbraco website, that simply searches some nodes for some properties and returns the content from those properties in json.
One of the properties is an umbraco grid. Technically that is also json, and I could successfully get the content with some elaborate JObject querying. But from the view side there is access to a "GetGridHtml" helper function that does that for you.
So my question is, how do I achieve that in a controller? I got the node as IPublishedContent which incidentally has that helper function, but it wants an IHtmlHelper which isn't available in this context. So what do I do?
[HttpGet]
[Route("api/myapp/version/")]
public IActionResult GetLatestMyAppVersion()
{
var releaseNote = _umbracoHelper.ContentAtXPath("//releaseNoteList").First().Children().OrderByDescending(x => x.Value<DateTime>("releaseDate")).First();
var ver = releaseNote.Value<string>("myAppReleaseVersion");
var date = releaseNote.Value<DateTime>("releaseDate");
var desc = releaseNote.GetGridHtml(?????, "mainContent", "Clean"); // this is where IHtmlHelper is needed
return Ok(new { Application = "MyApp", Version = ver, ReleaseDate = date.ToString("yyyy-MM-dd"), Description = desc });
}
If you want to get the Ihtmlhelper inside the controller method, I suggest you could inject it by inside the controller construct method and then you could use it inside your codes.
More details, you could refer to below codes:
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly IHtmlGenerator _htmlGenerator;
private readonly IHtmlHelper _helper;
public HomeController(IHtmlHelper helper, IHtmlGenerator htmlGenerator, ILogger<HomeController> logger)
{
_logger = logger;
_helper = helper;
_htmlGenerator = htmlGenerator;
}

Hangfire per-job correlationId/state

I run Hangfire on ASP.NET Core.
For our other projects we have CorrelationIds that we pass when making API calls to be able to link the caller and callee.
We use the IHttpContextAccessor's TraceIdentifier for this in ASP.NET Core.
Unfortunately it looks like the trick used by ASP.NET Core to get a scoped CorrelationId in the Transient IHttpContextAccessor doesn't work for Hangfire job execution.
Using a Scoped state correlation object doesn't work because it must be Transient to be able to work with the rest of the system (logging etc.)
I used to be able to get away using the ServiceLocator anti-pattern and resolve a scoped state object in a transient service.
In the latest ASP.NET Core that is no longer supported and an exception is thrown making the system too slow because of the huge number of exceptions thrown.
Is there something that Hangfire provides already that would give me a unique ID per job execution?
Cheers.
Thanks to jbl's comment I looked at what I was doing again and managed to get it working through a kludge.
I've got the transient state holder
(basically it's the HttpContextAccessor class renamed):
public class StateHolder
{
private static AsyncLocal<ContextHolder> _contextCurrent = new AsyncLocal<ContextHolder>();
public string State {
get {
return _contextCurrent.Value?.Context;
}
set {
var holder = _contextCurrent.Value;
if (holder != null)
{
holder.Context = null;
}
if (value != null)
{
_contextCurrent.Value = new ContextHolder { Context = value };
}
}
}
private class ContextHolder
{
public string Context;
}
}
and then in Hangfire I hook it up to the activation with
public class LoggingActivator : JobActivator
{
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ContextAccessor _contextAccessor;
public LoggingActivator([NotNull] IServiceScopeFactory serviceScopeFactory, ContextAccessor contextAccessor)
{
_serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory));
_contextAccessor = contextAccessor;
}
public override JobActivatorScope BeginScope(JobActivatorContext context)
{
return new LoggingActivatorScope(_serviceScopeFactory.CreateScope(), _contextAccessor);
}
}
and
public class LoggingActivatorScope : JobActivatorScope
{
private readonly IServiceScope _serviceScope;
private readonly ContextAccessor _contextAccessor;
public LoggingActivatorScope(
[NotNull] IServiceScope serviceScope,
ContextAccessor contextAccessor)
{
_serviceScope = serviceScope ?? throw new ArgumentNullException(nameof(serviceScope));
_contextAccessor = contextAccessor;
}
public override object Resolve(Type type)
{
_contextAccessor.Context = Guid.NewGuid().ToString();
return ActivatorUtilities.GetServiceOrCreateInstance(_serviceScope.ServiceProvider, type);
}
public override void DisposeScope()
{
_serviceScope.Dispose();
}
}
That seems to work fine.

How can I make an ASP Core Claims Principal available in a non-controller object?

I am working on an ASP Core 2 project using JWT authentication and the Dapper ORM.
Like all ASP projects, I have a lot of controllers, each instantiating its associated data objects. Each data object inherits from an abstract DbObject class that provides database access services. I also have an AuthenticatedUser object that abstracts the JWT to make it's properties easier to use.
What I want is to do is create the AuthenticatedUser object in the constructor of DbObject. Of course, one method is to create it in the controller and pass it to every concrete data object but this is messy as it would have to be passed hundreds of times (and it just feels wrong).
Is there a way to use the ASP Core middleware to get the token after authentication and make it available through dependency injection in the DbObject?
Edit
Hopefully, this clarifies my intentions. I would like the controller to create data objects and use their properties and methods without regard to implementation (i.e. DbObject). But queries executed by DbObject will be filtered by information in the token of the logged in user.
public class ManufacturerController : Controller {
[HttpGet]
public async Task<IActionResult> Get() {
var manufacturers = await new Manufacturer().SelectMany();
return Ok(manufacturers);
}
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id) {
var manufacturer = await new Manufacturer().SelectOne(id);
return Ok(manufacturer);
}...
public class Manufacturer : DbObject<Manufacturer> {
protected override string QrySelectOne => #"
Select *
From org.fn_Manufacturers ({0})
Where Id = {1}";
protected override string QrySelectMany => #"
Select *
From org.fn_Manufacturers ({0})";
public int Id { get; set; }
public string Name { get; set; }
public string Phone { get; set; }...
public abstract class DbObject<T> {
protected readonly AuthenticatedUser authenticatedUser;
public DbObject(IHttpContextAccessor contextAccessor) {
authenticatedUser = new
AuthenticatedUser(contextAccessor.HttpContext.User);
}
protected abstract string QrySelectOne { get; }
protected abstract string QrySelectMany { get; }
public async Task<T> SelectOne (int id) {...}
public async Task<T> SelectOne(params object[] ids) {...}
public async Task<IEnumerable<T>> SelectMany () {...}
public async Task<IEnumerable<T>> SelectMany (params object[] ids) {...}
I suppose one solution may be to create a static data object factory which has the IHttpContextAccessor injected??
ASP.NET Core provides IHttpContextAccessor interface for accessing HttpContext from non-controller objects.
The usage is fair simple. Inject IHttpContextAccessor into DbObject and access HttpContext by calling IHttpContextAccessor.HttpContext:
public abstract class DbObject
{
protected DbObject(IHttpContextAccessor contextAccessor)
{
var context = contextAccessor.HttpContext;
// Create instance of AuthenticatedUser based on context.User or other request data
}
}
EDIT
Your controllers instantiate data objects directly (with new operator), that's why you can't have IHttpContextAccessor injected out of the box. Here are possible solutions. I list them in order of my preference (from best to worst).
If each controller uses only one (or just several) types of data objects, the best options will be to avoid direct instantiation and move toward normal Dependency Injection.
So if ManufacturerController requires only Manufacturer like in your sample then, it's better to inject Manufacturer instance to controller, not to create it inside:
public class Manufacturer1Controller : Controller
{
private readonly Manufacturer manufacturer;
public Manufacturer1Controller(Manufacturer manufacturer)
{
this.manufacturer = manufacturer ?? throw new ArgumentNullException(nameof(manufacturer));
}
[HttpGet]
public async Task<IActionResult> Get()
{
var manufacturers = await manufacturer.SelectMany();
return Ok(manufacturers);
}
// ...
}
IHttpContextAccessor will be injected into Manufacturer and passed to base DbObject:
public class Manufacturer : DbObject<Manufacturer>
{
public Manufacturer(IHttpContextAccessor contextAccessor) : base(contextAccessor)
{
}
}
It's the cleanest solution in the list. You use DI in classic way and utilize all benefits DI provides.
If one controller could use dozens of different data objects, you could inject the factory object that creates instances of data objects. It could be simple implementation based on IServiceProvider:
public interface IDbObjectFactory
{
TDbObject Create<TDbObject>() where TDbObject : DbObject<TDbObject>;
}
public class DbObjectFactory : IDbObjectFactory
{
private readonly IServiceProvider serviceProvider;
public DbObjectFactory(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}
public TDbObject Create<TDbObject>() where TDbObject : DbObject<TDbObject>
{
return serviceProvider.GetRequiredService<TDbObject>();
}
}
public class Manufacturer2Controller : Controller
{
private readonly IDbObjectFactory dbObjectFactory;
public Manufacturer2Controller(IDbObjectFactory dbObjectFactory)
{
this.dbObjectFactory = dbObjectFactory ?? throw new ArgumentNullException(nameof(dbObjectFactory));
}
[HttpGet]
public async Task<IActionResult> Get()
{
var manufacturer = dbObjectFactory.Create<Manufacturer>();
var manufacturers = await manufacturer.SelectMany();
return Ok(manufacturers);
}
}
The code for Manufacturer and DbObject does not change comparing to the first option.
I don't see any reason not to use option #1 or #2. However just to complete the picture, I'll describe another two options.
Inject IHttpContextAccessor into conroller and pass this instance (or IHttpContextAccessor.HttpContext.User) to Data Object constructor invoked with operator new:
public class Manufacturer3Controller : Controller
{
private readonly IHttpContextAccessor contextAccessor;
public Manufacturer3Controller(IHttpContextAccessor contextAccessor)
{
this.contextAccessor = contextAccessor ?? throw new ArgumentNullException(nameof(contextAccessor));
}
[HttpGet]
public async Task<IActionResult> Get()
{
var manufacturer = await new Manufacturer(contextAccessor).SelectMany();
// or
// var manufacturer = await new Manufacturer(contextAccessor.HttpContext.User).SelectMany();
return Ok(manufacturer);
}
}
It's a bad solution, because you don't use Dependency Injection for Manufacturer here and loose many advantages that DI provides.
And the worst option would be using of static object factory with injected IHttpContextAccessor. With this approach you also loose benefits of DI. In addition you get ugly code somewhere in Startup that initializes static instance of IHttpContextAccessor. When you come to this approach, you'll discover that theere is no quite elegant way to do this.
My advice: use option #1 untill you have good reasons against it. Then use option #2.
Here is Sample Project on GitHub with samples for approaches ##1-3.

Create a Helper class from a Controller's method thats getting fat

This method receive a CSV file (Sale, Date) POSTed from front-end, cleans a table and inserts csv file record into the table, then gets latest Date and returns it to the front-end. I know the code looks a bit ugly and I have a lot to learn but what I am trying to figure out here is how to create a Helper class from this code since the method is getting too fat I gess?
So I tried to migrate some of the code to a Helper class then I created a static Class but the problem is that I couldn't inject dependencies into its constructor since it was an static Class... then no database service from the Helper class and this is not too "helper".
So in your opinion, is this method too long/ fat?
Is there a need for a Helper Class?
How can I build it?
Cheers
Here my Controller
private IDataService<Sale> _SaleDataService;
private readonly MyOptions _myOptions;
public DateTime LastWindowDay;
public ForecastApiController(IDataService<Sale> service, IOptions<MyOptions> optionsAccessor)
{
_SaleDataService = service;
_myOptions = optionsAccessor.Value;
}
[HttpPost("api/Sales/uploadFile")]
public async Task<IActionResult> UploadFiles()
{
try
{
//clean table
var all = _SaleDataService.GetAll();
if (all.Count() > 0)
{
foreach (var item in all)
{
_SaleDataService.Delete(item);
}
}
var files = Request.Form.Files;
//Read Request for the unique uploaded file (method can process multiple but frontend will post just one)
foreach (var file in files)
{
using (System.IO.StreamReader sr = new StreamReader(file.OpenReadStream()))
{
//Reads the file one line at a time until its end
String line = await sr.ReadLineAsync();
while (sr.Peek() >= 0)
{
//Split the values on the line and convert them into a propper format
var fileLine = sr.ReadLine();
var lineToArray = fileLine.Split(',').ToArray();
var timeElement = DateTime.Parse(lineToArray[0]);
var saleAmauntElement = float.Parse(lineToArray[1], System.Globalization.CultureInfo.InvariantCulture);
//Discard negative values and store data into database
if (saleAmauntElement >= 0)
{
//Store line into database
Sale sl = new Sale
{
SaleDate = timeElement,
SaleAmount = saleAmauntElement
};
_SaleDataService.Create(sl);
LastWindowDay = sl.SaleDate;
}
}
// Simple Moving Average method will be used and the restriction is that it will calculate only within a week after -
// - last day of historical data.
// Create an array and stores the next 7 days from the last day that there is data
string[] predictionDays = new string[7];
for (int i = 0; i < 7; i++)
{
predictionDays[i] = LastWindowDay.AddDays(i + 1).ToString("dd/MM/yyyy");
}
//returns the array to frontend to let the user select a prediction day
return Json(predictionDays);
}
}
return Json(new { message = "Error trying to process information" });
}
catch (Exception ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { message = ex.Message });
}
}
Following the Repository pattern helps to maintain the controllers and the project in general, it is like having a helper class with all your operations (business logic and DB).
In your Startup.cs
services.AddScoped<IRepository, Repository>();
Create an Interface
public interface IRepository
{
IEnumerable<MyData> GetData();
}
Create your helper class
public partial class Repository : IRepository
{
private DBContext _context;
private ILogger<Repository> _logger;
private IHttpContextAccessor _httpContextAccessor;
public Repository(DBContext context, ILogger<Repository> logger, IHttpContextAccessor httpContextAccessor)
{
_context = context;
_logger = logger;
_httpContextAccessor = httpContextAccessor;
}
public async Task<bool> SaveChangesAsync()
{
return (await _context.SaveChangesAsync()) > 0;
}
public IEnumerable<MyData> GetData()
{
_logger.LogInformation("Getting All Data from the Database");
return _context.Data.ToList();
}
}
Finally inject it in your Controller
public class RequestsController : Controller
{
private IRepository _repository;
private ILogger<RequestsController> _logger;
private IConfiguration _config;
public RequestsController(IRepository repository,ILogger<RequestsController> logger,IConfiguration config)
{
_repository = repository;
_logger = logger;
_config = config;
}
// GET: Requests
public IActionResult Index()
{
var data = _repository.GetData()
return View(data);
}
}
The best practice approach is to follow the repository pattern as advised by Steve Tolba's answer. The repository pattern alleviates the bulk of query logic, transformation of view Models and the calling of business models from the controller.
However, if for whatever reason you do not want to follow the repository pattern and just want to split up your controller, you may pass the reference to the controller as a parameter to another action method:
[HttpGet("myActionMethodThatUsedToBeFat")]
public int MyActionMethodThatUsedToBeFat()
{
await HelperAction(this);
//Do stuff...
}
private async Task<byte[]> HelperAction(Controller controller)
{
//Do stuff in here that would have made the calling action method too bulky
}

Query the authenticated user object too often within a http request

I am using asp.net core mvc with asp.net identity.
My ApplicationUser has a property: Country => 'GB' or 'FR' etc...
I want to set the System.Threading.Thread.CurrentThread.CurrentCulture to the value read from the applicationUser.Country. to display all datetime/number values correctly in my views as set by the user.
Thus I created this action filter:
public class LanguageActionFilter : ActionFilterAttribute
{
private readonly ILogger _logger;
private UserManager<ApplicationUser> _userManager;
public LanguageActionFilter(ILoggerFactory loggerFactory, UserManager<ApplicationUser> userManager)
{
_logger = loggerFactory.CreateLogger("LanguageActionFilter");
_userManager = userManager;
}
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var user = await _userManager.GetUserAsync(context.HttpContext.User);
Thread.CurrentThread.CurrentCulture = new CultureInfo(user.Country);
await base.OnActionExecutionAsync(context, next);
}
}
On the action/controller where this actionfilter is set I also run this code:
public async Task<IActionResult> Index()
{
var user = await this.userManager.GetUserAsync(User);
var todos = await service.GetTodosAsync(user.Id);
return View(todos);
}
At the moment I call the this.userManager.GetUserAsync(User);
TWO TIMES !
Then I thought about passing the user object to the
context.HttpContext.Items.Add("applicationUser", user);
and grab this user object again within the Index() action method:
var user = (ApplicationUser)base.HttpContext.Items["applicationUser"];
That worked, but is that a good idea? Do you see any problems with that approach?
What you did is fine...
I'm quoting from the definition of the HttpContext class :
/// <summary>
/// **Gets or sets a key/value collection that can be used to share data within the scope of this request.**
/// </summary>
public abstract IDictionary<object, object> Items { get; set; }
Edit : It seems ef core doesn't support first level cache. So my idea went for nothing
Your code works, but i think you won't gain considerable performance.
You probably use aspnet identity with entity framework. Since ef supports first level cache. , if you call this.userManager.GetUserAsync(User); more than one, ef retrieves user entity from database only once. As a result two ways approximately have same effect for performance. I wouldn't use HttpContext.Items for your case.