Gökhan Gökalp
Software Architect, Blog writer. If you free your mind, you free your code.
Gökhan GÖKALP
11.11.2017
Devnot
Logging, Caching and Localization in Asp.NET Core 2.0
How to create log?
public class TodoController : Controller
{
private readonly ILogger<TodoController> _logger;
public TodoController(ILogger<TodoController> logger)
{
_logger = logger;
}
}
public IActionResult Index()
{
_logger.LogInformation(1000, "Index method invoked.");
return View();
}
How to add providers?
"Console" and "Debug" logging provider default template.
ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
})
How to add providers?
Use several built-in logging providers with the "ConfigureLogging()" method on WebHost builder.
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, logging) =>
{ logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
})
.Build();
Log Category, Log Levels and Log Event Id
info: DotNETCoreDay.Controllers.TodoController[1000]
Index method invoked.
DotNETCoreDay.Controllers.TodoController:Information: Index method invoked
Two ways to create log category:
Two ways to create log level:
Log Category, Log Levels and Log Event Id
Use "log event id" to groupe related messages.
info: DotNETCoreDay.Controllers.TodoController[1002] //Get operations
Getting item invalidid
warn: DotNETCoreDay.Controllers.TodoController[4000]
GetById(invalidid) NOT FOUND
Log Exceptions
Use "LogError()" method.
catch(Exception ex)
{
_logger.LogError(1001, ex, "Oops!");
}
Log Filtering Rules
Specify minimum log levels in "appsettings" easily.
{
"Logging": {
"Console": {
"LogLevel":{
"DotNETCoreDay.Controllers.HomeController" : "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}
or in "Program.cs":
WebHost.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddFilter<ConsoleLoggerProvider>("DotNETCoreDay.Controllers.TodoController",
LogLevel.Information);
logging.SetMinimumLevel(LogLevel.Debug); //Default value is "Information"
})
.Build();
Log Scopes
Useful for grouping some logical operations. E.g:
private void DoSomething()
{
using(_logger.BeginScope("DoSomething scope!"))
{
_logger.LogInformation(1000, "DoSomething method invoked.");
//..
_logger.LogWarning(1002, "Something happened!");
}
}
To activating scopes:
WebHost.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConsole(options => options.IncludeScopes = true);
})
.Build();
{
"Logging": {
"IncludeScopes": true
}
}
or
Third-party Logging Providers
Asp.NET Core 2.0 supports popular logging providers. E.g:
Response Caching Middleware
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCaching(options => {
options.UseCaseSensitivePaths = false;
});
}
Configure in "Startup.cs"
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseResponseCaching();
}
Response Caching Middleware
[ResponseCache(Duration = 20)] //second
public IActionResult Index()
{
return View();
}
ResponseCache attribute
Some HTTP directives (Cache-Control)
HTTP 1.1 Caching specification
Response Caching Middleware
ResponseCache attribute - VaryByQueryKeys
Request | Result |
---|---|
http://example.com?key1=value1 | Returned from server |
http://example.com?key1=value1 | Returned from middleware |
http://example.com?key1=value2 | Returned from server |
Response Caching Middleware
ResponseCache attribute - Vary
[ResponseCache(VaryByHeader = "Accept-Language")]
public IActionResult Index()
{
return View();
}
Response Caching Middleware
ResponseCache attribute - Cache Profiles
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.CacheProfiles.Add("Default",
new CacheProfile()
{
Duration = 60 //Second
})
});
}
[ResponseCache(CacheProfileName = "Default"]
public IActionResult Index()
{
return View();
}
Memory Cache
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
}
readonly IMemoryCache _memoryCache;
TodoController(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}
CustomerModel GetCustomer(int id)
{
CustomerModel customerModel;
if(!_memoryCache.TryGetValue(id, out customerModel))
{
customerModel = //...
var memoryCacheEntryOptions = new MemoryCacheEntryOptions()
{
SlidingExpiration = TimeSpan.FromMinutes(5)
};
_memoryCache.Set(id, customerModel, memoryCacheEntryOptions);
}
return customerModel;
}
Distributed Caching
How to use?
services.AddDistributedRedisCache(options =>
{
options.Configuration = "localhost:6379";
options.InstanceName = "master";
});
readonly IDistributedCache _distributedCache;
public TodoController(IDistributedCache distributedCache)
{
_distributedCache = distributedCache;
}
For localization:
Make the App's Content Localizable
public class TodoController : Controller
{
private readonly IStringLocalizer<TodoController> _localizer;
public TodoController(IStringLocalizer<TodoController> localizer)
{
_localizer = localizer;
}
public IActionResult Index()
{
CultureModel cultureModel = new CultureModel();
cultureModel.Title = _localizer["Merhaba Dünya!"];
return View(cultureModel);
}
}
Make the App's Content Localizable
public class TodoController : Controller
{
private readonly IStringLocalizer _localizerForShared;
public CulturesController(IStringLocalizerFactory localizerFactory)
{
_localizerForShared = localizerFactory.Create(typeof(SharedResource));
}
}
IStringLocalizerFactory (e.g shared resources)
Resource path: controller file path
Make the App's Content Localizable
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@{
ViewData["Title"] = Localizer["Merhaba Dünya!"];
}
View Localization - IViewLocalizer
Resource path: view file path
Make the App's Content Localizable
public class CreateCultureModel
{
[Required(ErrorMessage = "This field is required.")]
public string Name { get; set; }
}
DataAnnotations Localization
Configuring Localization
public void ConfigureServices(IServiceCollection services)
{
services.AddLocalization(options => {
options.ResourcesPath = "Resources";
});
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization(options =>
{
options.DataAnnotationLocalizerProvider = (type, factory) => {
return factory.Create(typeof(SharedResource));
}
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var lockOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(lockOptions.Value);
}
How to add localization to service collection?
Configuring Localization
public void ConfigureServices(IServiceCollection services)
{
services.Configure<RequestLocalizationOptions>(options => {
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("tr-TR"),
new CultureInfo("en-US")
};
options.DefaultRequestCulture = new RequestCulture("tr-TR");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
}
SupportedCultures(date, currency etc.) and SupportedUICultures(translate)
Implement a Strategy to Select the Language
3 options with RequestLocalization
By Gökhan Gökalp
Logging, Caching and Localization in Asp.NET Core 2.0
Software Architect, Blog writer. If you free your mind, you free your code.