Real basic stuff for cross module sharing of code. We'll keep it simple in here. Key features are extensions to EPiServer's ILogger interface for logging objects (not only strings). and a base class for making web api calls.
This namespace contains extension method to EPiServer.Logging.ILogger
interface. Enables you to send in entire object instances for logging of coplex typs. The types will be serialized as JSON structures in the log message. This can be useful to avoid lots of string concatenation code in logger calls.
Use this:
var model = new { Foo = "foo", Bar = "bar" };
_log.Information(new { message = "some message", model });
Instead of this:
var model = new { Foo = "foo", Bar = "bar" };
_log.Information($"some message. Foo: {mdel.Foo}, Bar: {model.Bar}");
Select EPiServer properties will be excluded from being serialized in the log message. These include:
- XhtmlString
- XForm
Reference loops are ignored using built in loop handling form Newtonsoft.Json
If you have special needs for controlling how objects are serialized for logging purposes, you can decorate your model class being logged with the ICustomLogMessage
contract. The implementation of ICustomLogMessage.ToLoggableString()
will decide the log message.
public class Person : ICustomLogMessage
{
public string Name { get; set; }
public string SocialSecurityNumber { get; set; }
public string ToLoggableString()
{
return $"Name: {Name}, SocialSecurityNumber: masked in logs";
}
}
Implement a service with a static read-only instance of System.Net.Http.HttpClient. Let it live – don't dispose it after each call. Inherit Epinova.Infrastructure.RestServiceBase, and use the CallAsync method to safely make API calls
public class AwesomeService : RestServiceBase
{
private static readonly HttpClient Client = new HttpClient { BaseAddress = new Uri("https://some.api/address/") };
private readonly ILogger _log;
public AwesomeService(ILogger log) : base(log)
{
_log = log;
}
public async Task<Bar> CreateStuff(Foo payload)
{
var responseMessage = await CallAsync(() => Client.PostAsync("api/method", new StringContent("serialized version og Foo")));
//Even simpler, if using in combination with Microsoft.AspNet.WebApi.Client:
var responseMessage = await CallAsync(() => Client.PostAsync<Foo>("api/method", payload, new JsonMediaTypeFormatter()));
if (responseMessage == null || !responseMessage.IsSuccessStatusCode)
{
_log.Information(new { message = "Unable to post payload", payload });
return null;
}
Bar responseDto = await ParseJsonAsync<Bar>(responseMessage);
if (responseDto.HasError)
{
_log.Information(new { message = "Unable to parse response data.", responseDto.ErrorMessage, payload });
return null;
}
return responseDto;
}
}
Helper class to run async methods within a sync process. Use only when you really cannot use the await keyword or use a proper synchronous method.
AsyncHelper.RunSync(() => DoSomethingAwesoneAsync());
The RunSync
method also has an overload for returning stuff from async methods.
Credits to https://cpratt.co/async-tips-tricks/
This module depends on EPiServer.Framework >= v11.1 for logging purposes. No setup or init code required.
The module is published on nuget.org.
nuget install Epinova.Infrastructure
- .NET Standard 2.0
- Tests target .NET Core 2.1
- Tarjei Olsen - Initial work - apeneve
See also the list of contributors who participated in this project.
This project is licensed under the MIT License - see the LICENSE file for details