Sunday, October 28, 2018

ASP.NET Core In-Memory Caching

In this post let’s go through how server-side caching can be used in an ASP.NET Core Application, specially in-memory caching.

Caching can be used to improve the performance of an application. For an example, say that you have an API endpoint and there, you are returning some data after querying a database, and you are sure the related data is not going to get refreshed for a certain period of time, maybe daily. In that case, there is no point of querying the database each time your endpoint is being called within that day. So in the initial call, you can query the database, cache them and for the next subsequent calls, you can return the data from the cache. Then after that certain period of time expires, elicit the data in the cache and start from the beginning.

The in-memory caching uses web servers memory to store the cache. So now an interesting question comes, what if the application is running on multiple servers then how can the cache is shared. In such scenario, either we will need to enforce sticky sessions (specific session and all its subsequent sessions being directed to the same server) or distributed caching (doesn't use local memory and uses some other providers to maintain the cache Microsoft SQL Server, Redis etc.). In this post, we are assuming sticky sessions are in place.

ASP.NET Core provides 2 options.
public class MemoryCache : IDisposable, Microsoft.Extensions.Caching.Memory.IMemoryCache
This one is the preferred in the world of ASP.NET Core, as you can see it implements IMemoryCache and nicely integrated to ASP.NET Core DI.
public class MemoryCache : System.Runtime.Caching.ObjectCache, IDisposable
This one comes for .NET Framework, but still as long you target .NET Standard 2.0 or above, you can use this.

Now let’s see how we can use in-memory caching using Microsoft.Extensions.Caching.Memory.MemoryCache.

I have created an ASP.NET Core Web API application using the default template.

First, you need to register IMemoryCache. We don’t explicitly need to register, there is an extension method already available.
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
 
    services.AddMemoryCache();
}
Next, in the controllers’ constructor, I can inject IMemoryCache.
public IMemoryCache _memoryCache { get; }
 
public ValuesController(IMemoryCache memoryCache)
{
    _memoryCache = memoryCache;
}
And use as follows.
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
    string key = "Somekey";
 
    if (!_memoryCache.TryGetValue(key, out DateTime cacheValue))
    {
        cacheValue = DateTime.Now;
 
        var cacheEntryOptions = new MemoryCacheEntryOptions()
            .SetSlidingExpiration(TimeSpan.FromSeconds(30));
 
        _memoryCache.Set(key, cacheValue, cacheEntryOptions);
    }
 
    return new string[] { $"Cached: { cacheValue.ToString()}", $"Actual: { DateTime.Now.ToString()}" };
}
The cache contains EntriesCollection which is maintained using keys. The logic is simple, we are adding items to EntriesCollection identified by a key, and when we add we can set a variety of options (MemoryCacheEntryOptions).

  • AbsoluteExpiration
Gets or sets an absolute expiration date for the cache entry.
  • AbsoluteExpirationRelativeToNow
Gets or sets an absolute expiration time, relative to now.
  • ExpirationTokens
Gets the IChangeToken instances which cause the cache entry to expire.
  • PostEvictionCallbacks
Gets or sets the callbacks will be fired after the cache entry is evicted from the cache.
  • Priority
Gets or sets the priority for keeping the cache entry in the cache during a memory pressure triggered cleanup. The default is Normal.
  • Size
Gets or sets the size of the cache entry value.
  • SlidingExpiration    
Gets or sets how long a cache entry can be inactive (e.g. not accessed) before it will be removed. This will not extend the entry lifetime beyond the absolute expiration (if set).

More reading,
Cache in-memory in ASP.NET Core

Hope this helps.

Happy Coding.

Regards,
Jaliya

Thursday, October 11, 2018

.NET Core on MacOS: Code Coverage with Coverlet

I wanted to check the code coverage on a .NET Core project I am working on. But I am on MacOS, and unfortunately, Visual Studio for Mac nor JetBrains Rider (on MacOS) does not support code coverage as of today. JetBrains is going to port dotCover to be cross-platform so we will have Rider + dotCover in near future which is something to look forward to.

I found this brilliant tool coverlet developed by Toni Solarin-Sodara. Coverlet is a cross-platform code coverage library for .NET Core, with support for line, branch and method coverage. I just gave it a try now, it looks amazing and with very little steps, I can get the code coverage.

First I need to add the coverlet.msbuild nuget package to the unit test project.
# From the folder which contains UnitTests.csproj file
dotnet add package coverlet.msbuild

# If the folder contains multiple .csproj files, specify the targetted .csproj file
dotnet add <MyProject.UnitTests.csproj> package coverlet.msbuild
Then I can just run,
dotnet test <MyProject.UnitTests.csproj> /p:CollectCoverage=true
But for some reason, I was getting this error "...coverlet.msbuild.targets: error: Failed to resolve assembly:...". After a little bit of googling, found this issue where it says to run dotnet test command with /p:CopyLocalLockFileAssemblies=true flag.
dotnet test <MyProject.UnitTests.csproj> /p:CollectCoverage=true /p:CopyLocalLockFileAssemblies=true
And yes, that did it and I am presented with most awaited code coverage.

Code Coverage
There are a lot of options that you can configure with coverlet and you should definitely try it.

Hope this helps.

Happy Coding.

Regards,
Jaliya

Tuesday, October 2, 2018

ASP.NET Core: Setting Up HTTPS Local Development Certificate in MacOS

In this post let’s see how we can configure local HTTPS certificate in MacOS for an ASP.NET Core web application.

You can use dotnet-dev-cert which is a command line tool to generate certificates used in ASP.NET Core during local development. To install the tool, you can simply run the following command (note: the version can be different, it's the version as of today).
dotnet tool install --global dotnet-dev-certs --version 2.1.1 
Once installed, you can generate a certificate just by running the below command.
dotnet dev-certs https -ep localhost.pfx -p dev
image
dotnet dev-certs
You can run the command with --help flag to see more options about the tool.
dotnet dev-certs https --help

image
dotnet dev-certs https --help
Once the certificate is generated, you should be able to see the certificate in Keychain Access. You can easily open Keychain Access by using Spotlight or, navigating to Applications -> Utilities -> Keychain Access.

image
Keychain Access
Now you need to trust the certificate for SSL by double-clicking on the certificate, expanding Trust and selecting Always Trust in Secure Socket Layter (SSL) dropdown.
image
Keychain Access
Hope this helps.

Happy Coding.

Regards,
Jaliya