Two days ago I read some news about Lamar 3.0, new version of Lamar dependency injection library meant to replace the well established but closing down StructureMap. Because yesterday I tested decorators with Scrutor, I wanted to try something similar with Lamar, a chance to use it for the first time.
Docs are very minimal, and took me a while to understand that I must add Shouldly, which I didn't use before either. Of course I didn't read the entire documentation before trying Lamar, so their example didn't work for me. Eventually I get back to StructureMap decorators and use it similarly like this:
This way it seems to work fine, but still some work on the documentation should be done, I think. But I promise I'll try a bit more their GitHub test samples, which hopefully will clarify many aspects.
One thing I read about it and liked, was that it plays nicely with default .NET Core dependency injection implementing IServiceCollection.
Sunday, March 31, 2019
.NET Core decorator pattern with DI and Scrutor
I few days ago I tested .NET Fiddle with some .NET code, but since then I found out its biggest limitation: doesn't work with .NET Core. Only later I noticed the .NET Framework version is 4.5, but most importantly it can't be changed.
So, my next test for decorator pattern failed, as I wanted to use Scrutor library with default .NET Core Dependency Injection.
Consequently, here's the Gist from GitHub
As you can see, using this small library, is very easy to add new functionality to existing objects (using Decorate() extension DI method), expanding them, especially when we don't have access to source code to change those objects directly. Besides Decorator it also can scan assemblies (which in fact is the main functionality of the library), working with default .NET Core dependency injection.
In this case I simulated some sort of logging (on console) after interface methods call, but can be used for many other objectives, like adding caching, authorization (before calls), notifications, and so on.
Saturday, March 30, 2019
ASP.NET Core Identity with MediatR
A good way to play with ASP.NET Core 3.0 Identity (using VS 2019 preview) and MediatR is this sample project on GitHub.
MediatR is a small but very useful utility library which main goal is to implement Mediator pattern, but is more than that. For instance comes with ASP.NET Core Dependency Injection extensions, pipelines (or behaviors) that implement decorator pattern, and few other goodies. Simply speaking, it may be a very first step toward CQRS, to split up queries and commands. In many cases is used more like a command pattern, I think.
In my case I wanted to use MediatR to extract from identity Razor pages all references to Microsoft.AspNetCore.Identity and move the code in some handlers. This should help unit testing because page's OnGetAsync() or OnPostAsync() are only calling mediator Send() method which does the job, without any reference to Identity's SigInManager class.
To start with, just create a new ASP.NET Core web application with local identity accounts, so the entire back-end to identities are already created. Then I run the database migration:
dotnet ef database update
If you ran the application at this stage it should work, so you should be able to register a new account and login. By default, ASP.NET uses default identity UI which hides from us all details. If we want to customize the login, for instance, as we do, we need to scaffold the pages and manually change them in the project, see this docs link:
dotnet tool install -g dotnet-aspnet-codegenerator
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet restore
To actually generate the pages use this:
dotnet aspnet-codegenerator identity -dc SampleMediatR.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.Logout"
Newly generated login, logout and registration pages are available under /Areas/Identity/Pages/Account:
At this stage, if you want to run the application is important to comment out in Startup.cs in ConfigureServices() the call of AddDefaultUI() because we don't need it anymore (once scaffolded in the app):
services.AddDefaultIdentity<IdentityUser>()
//.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
Actually, scaffolding operation created a new file in the root of the project called ScaffoldingReadme.txt with instruction on how to set it up.
Also, I created a new folder called 'MediatR' under /Areas/Identity for classes needed by MediatR library, but first let's add those references:
dotnet add package MediatR
dotnet add package MediatR.Extensions.Microsoft.DependencyInjection
Then add it for dependency injection in Startup.cs ConfigureServices():
services.AddMediatR();
Now we are ready to implement query & handler classes needed by MediatR. For instance MediatR/LoginGet.cs has 2 classes: query (request) called "LoginGet" and handler called "LoginGetHandler". First one wraps the data passed to the handler, while the second is the handler doing the job in method called Handler(), called automatically by the MediatR library.
public class LoginGet: IRequest<IEnumerable<AuthenticationScheme>> { }
public class LoginGetHandler : IRequestHandler<LoginGet, IEnumerable<AuthenticationScheme>>
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly IHttpContextAccessor _httpContextAccessor;
public LoginGetHandler(SignInManager<IdentityUser> signInManager, IHttpContextAccessor httpContextAccessor)
{
_signInManager = signInManager;
_httpContextAccessor = httpContextAccessor;
}
public async Task<IEnumerable<AuthenticationScheme>> Handle(LoginGet request, CancellationToken cancellationToken)
{
await _httpContextAccessor.HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
return await _signInManager.GetExternalAuthenticationSchemesAsync();
}
}
Notice couple things:
ExternalLogins = (await _mediator.Send(new LoginGet())).ToList();
All the previous logic that didn't belong to the OnGetAsync() controller was moved to the MediatR handler, and similarly for OnPostAsync(), as well as Logout.cshtml.cs OnPostAsync().
See the code for other details.
MediatR is a small but very useful utility library which main goal is to implement Mediator pattern, but is more than that. For instance comes with ASP.NET Core Dependency Injection extensions, pipelines (or behaviors) that implement decorator pattern, and few other goodies. Simply speaking, it may be a very first step toward CQRS, to split up queries and commands. In many cases is used more like a command pattern, I think.
In my case I wanted to use MediatR to extract from identity Razor pages all references to Microsoft.AspNetCore.Identity and move the code in some handlers. This should help unit testing because page's OnGetAsync() or OnPostAsync() are only calling mediator Send() method which does the job, without any reference to Identity's SigInManager class.
To start with, just create a new ASP.NET Core web application with local identity accounts, so the entire back-end to identities are already created. Then I run the database migration:
dotnet ef database update
If you ran the application at this stage it should work, so you should be able to register a new account and login. By default, ASP.NET uses default identity UI which hides from us all details. If we want to customize the login, for instance, as we do, we need to scaffold the pages and manually change them in the project, see this docs link:
dotnet tool install -g dotnet-aspnet-codegenerator
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
dotnet restore
To actually generate the pages use this:
dotnet aspnet-codegenerator identity -dc SampleMediatR.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.Logout"
Newly generated login, logout and registration pages are available under /Areas/Identity/Pages/Account:
At this stage, if you want to run the application is important to comment out in Startup.cs in ConfigureServices() the call of AddDefaultUI() because we don't need it anymore (once scaffolded in the app):
services.AddDefaultIdentity<IdentityUser>()
//.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
Actually, scaffolding operation created a new file in the root of the project called ScaffoldingReadme.txt with instruction on how to set it up.
Also, I created a new folder called 'MediatR' under /Areas/Identity for classes needed by MediatR library, but first let's add those references:
dotnet add package MediatR
dotnet add package MediatR.Extensions.Microsoft.DependencyInjection
Then add it for dependency injection in Startup.cs ConfigureServices():
services.AddMediatR();
Now we are ready to implement query & handler classes needed by MediatR. For instance MediatR/LoginGet.cs has 2 classes: query (request) called "LoginGet" and handler called "LoginGetHandler". First one wraps the data passed to the handler, while the second is the handler doing the job in method called Handler(), called automatically by the MediatR library.
public class LoginGet: IRequest<IEnumerable<AuthenticationScheme>> { }
public class LoginGetHandler : IRequestHandler<LoginGet, IEnumerable<AuthenticationScheme>>
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly IHttpContextAccessor _httpContextAccessor;
public LoginGetHandler(SignInManager<IdentityUser> signInManager, IHttpContextAccessor httpContextAccessor)
{
_signInManager = signInManager;
_httpContextAccessor = httpContextAccessor;
}
public async Task<IEnumerable<AuthenticationScheme>> Handle(LoginGet request, CancellationToken cancellationToken)
{
await _httpContextAccessor.HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
return await _signInManager.GetExternalAuthenticationSchemesAsync();
}
}
Notice couple things:
- LoginGet class implements MediatR's IRequest interface with type IEnumerable<AuthenticationScheme>, which is exactly the type returned by Handle() method. In this case the class doesn't need any properties (but see some in LoginPost.cs).
- In LoginGetHandler() constructor is injected from DI both SignInManager and HttpContextAccessor (which was added in Startup.cs with services.AddHttpContextAccessor(), just to get access to HttpContext in a safe way).
- Handle() function uses SignInManager and HttpContextAccessor to call necessary functions.
ExternalLogins = (await _mediator.Send(new LoginGet())).ToList();
All the previous logic that didn't belong to the OnGetAsync() controller was moved to the MediatR handler, and similarly for OnPostAsync(), as well as Logout.cshtml.cs OnPostAsync().
See the code for other details.
Monday, March 25, 2019
Visitor pattern on .NET Fiddle
A few days ago I discovered .Net Fiddle which I wanted to try with something, so I tested with 2 samples for visitor pattern: dotnetfiddle.net/KLQ3i4 and dotnetfiddle.net/yLYvY9 . Cool.
A very convenient way to play with C# code, run it in the browser and share it online. See my profile.
A very convenient way to play with C# code, run it in the browser and share it online. See my profile.
Saturday, March 23, 2019
Class diagrams refresher for design patterns in C#
We all know the concept of design patterns, as a well known, reusable solution for various software design problems. We may have read the books, including the famous Design Patterns: Elements of Reusable Object-Oriented Software, but also others, or checked sites like OODesign.com or DOFactory.com, especially for C#.
One mistake a think is happening many times is to treat all those patterns equally, when some of them are used way more often than others. My recommendation is to learnt them that way: start with something you may actually use, and add more when needed, in time. Other mistake is to consider only those listed in that book or websites mentioned, forgetting others described in other sources (see the list on Wikipedia is much longer).
However, when comes to learn those patterns my suggestion is to focus on UML class diagrams provided.
Let's take an example of a behavioural pattern that's very likely to be used in complex architectures: Mediator. Here's the UML diagram from Wikipedia:
(Actually the other image is much better because has more information and uses the correct relationship arrows instead of these non-standard, but also include sequence diagram which a tried to avoid for now, for simplicity)
You also have the C# code, as an example, but may question to you is: what's easier to read, diagram or C# code? I'm pretty sure many will answer the latter, but why? UML has many objectives in scope, some of them are obsolete these days like using CASE tools to generate code, but don't forget the main objective - to draw a picture that replace 1000 words. Just seeing that diagram should be clear for many developers, because that's the meaning of it, to simplify communications between developers.
I was looking for a good UML class diagram refresher with significant code example in C# and because I couldn't find one, here's my attempt to do one. Some inspiration comes from Agile Principles, Patterns, and Practices in C# by Robert C. Martin and Micah Martin (see chapters 13 and 19).
Class diagrams (made on draw.io) have a name, attributes (fields or properties) and messages (methods):
Which in C# it may be:
public class ThingA {
public int attribute1 {get; set;}
private string attribute2;
public int Message1() { /* ... */ }
protected bool Message2(string s) { /* ... */ }
private void Message3(IEnumerable<int>) { /* ... */ }
}
public abstract class AbstractThingA {
public virtual int attribute1 {get; set;}
public abstract int Message1();
}
public interface IThingA {
public int attribute1 {get; set;}
public int Message1();
}
Notice here:
Note these implementations are not mandatory this way, you may choose similar solutions with the same results.
Other important details:
That's all information we can extract from this diagram, for some other details we'd need some other diagrams, like a sequence diagram. Also, we considered some best practices for C#, like creating only public setters. In ConcreteMediator we have access to collegue1 & collegue2 private properties which can be used from whatever functionality we implement in that mediator class.
On the website you can see a full C# implementation.
Getting used to "read" class diagrams may help understanding and implementing design patterns, because I think it's easier to remember differences and details of various patterns graphically instead of the implementation code. Also, in many cases is more important to understand the classes, interfaces and relationships between them instead of some kind of implementation, which can slightly vary from project to project. For instance, you can use public properties or fields, or constructor injection on how the objects are created and passed around. Even for mediator example above there may be other solutions that does similar functionality, but the pattern itself is described by the class diagram, not by implementation details.
One mistake a think is happening many times is to treat all those patterns equally, when some of them are used way more often than others. My recommendation is to learnt them that way: start with something you may actually use, and add more when needed, in time. Other mistake is to consider only those listed in that book or websites mentioned, forgetting others described in other sources (see the list on Wikipedia is much longer).
However, when comes to learn those patterns my suggestion is to focus on UML class diagrams provided.
Let's take an example of a behavioural pattern that's very likely to be used in complex architectures: Mediator. Here's the UML diagram from Wikipedia:
(Actually the other image is much better because has more information and uses the correct relationship arrows instead of these non-standard, but also include sequence diagram which a tried to avoid for now, for simplicity)
You also have the C# code, as an example, but may question to you is: what's easier to read, diagram or C# code? I'm pretty sure many will answer the latter, but why? UML has many objectives in scope, some of them are obsolete these days like using CASE tools to generate code, but don't forget the main objective - to draw a picture that replace 1000 words. Just seeing that diagram should be clear for many developers, because that's the meaning of it, to simplify communications between developers.
I was looking for a good UML class diagram refresher with significant code example in C# and because I couldn't find one, here's my attempt to do one. Some inspiration comes from Agile Principles, Patterns, and Practices in C# by Robert C. Martin and Micah Martin (see chapters 13 and 19).
Class diagrams (made on draw.io) have a name, attributes (fields or properties) and messages (methods):
Which in C# it may be:
public class ThingA {
public int attribute1 {get; set;}
private string attribute2;
public int Message1() { /* ... */ }
protected bool Message2(string s) { /* ... */ }
private void Message3(IEnumerable<int>) { /* ... */ }
}
public abstract class AbstractThingA {
public virtual int attribute1 {get; set;}
public abstract int Message1();
}
public interface IThingA {
public int attribute1 {get; set;}
public int Message1();
}
Notice here:
- Access modifiers (visibility in UML): '+' means 'public', '-' means 'private' and '#' means protected
- Abstract classes are denoted by italics font (used on DOFactory.com, for instance), or may use '<<abstract>>' stereotype;
- For interfaces you can use '<<interface>>' stereotype (above interface name) or just prefix it it 'I' (my preferred method);
- Constants may be uppercase and static elements underlined (not used here);
There may be different preferences when implementing class diagrams, but in C# in think best option is to implement private attributes as class fields and public attributes as properties. Also, up to you if in abstract classes you implement a method (or property / field) as abstract or virtual (be aware of the difference), which is just an implementation detail.
This is easy, right? Now let's continue with relationships between classes and interfaces which needs to be clearly understood in order to 'read' effectively UML class diagrams. Here we have a few options:
- Inheritance (----|>) - ThingA class inherits from AbstractThingA:
public abstract class AbstractThingA { /* .. */ }
public class ThingA: AbstractThingA { /* .. */ }
- Implementation or realization (- - - -|>) - ThingA class implements interface IThingA:
public interface IThingA { /* .. */ }
public class ThingA: IThingA { /* .. */ }
- Association (---->) - class ThingA uses class ThingB. There are various ways to 'use' a class like :
- A local variable in a method in an object of type ThingA:
public class ThingA {
public int Message1() {
ThingB b = new ThingB();
return b.MessageB1();
}
}
- An object of type ThingB being parameter in a method in ThingB object:
public class ThingA {
public int Message1(ThingB b) {
return b.MessageB1();
}
}
- Other option may be returning an object of type ThingB from a method in ThingA. These differences may be specified with stereotypes above the arrow, like respectively "<<local>>", "<<parameter>>", or "<<create>>".
- Aggregation ( <>----->) is a special kind of association when class ThingA "has an" object of ThingB, but ThingB object may exists on its own:
public class ThingA {
private ThingB b;
public ThingA(ThingB b) {
this.b = b;
}
// then use b.MessageB1()
}
- Composition ( <|>----->) is yet another kind of association when class ThingA "has an" object of ThingB, but ThingB object may not exists on its own (like the part may only make sense in the context of a whole object):
public class ThingA {
private ThingB b = new ThingB();
// then use b.MessageB1()
}
- Dependency ( - - - - >) - usually means "everything else", when an object of type ThingB is used somehow by an object of type ThingA, other than the relationships described above. It's a weaker relationship, but still included in the class diagram.
Note these implementations are not mandatory this way, you may choose similar solutions with the same results.
Other important details:
- Multiplicity - like 0 (when no instance of the dependent object may exists), 1 (exactly 1 instance of dependent object exists), 0..1 (no or 1 instance exists), * or 0..* (any number of instances may exists, usually means some sort of collection):
class ThingA {
private ThingB objB;
} - Attribute Name - on the arrow we can specify the name of the property holding the dependent class ("collB" here):
class ThingA {
private List<ThingB> collB;
} - Association Qualifier - on the source class we have some key or collection to keep track of dependent object ("keyB" here):
class ThingA {
private string keyB;
public ThingB {
get { return new ThingB(keyB);}
}
}
After all these details let's see the Mediator pattern as described on DOFactory.com website:
Is it now a bit clearer that Mediator is an abstract class having ConcreteMediator as derived class, and Colleague abstract class has a property called 'mediator' (of type Mediator) having 2 derived classes, ConcreteCollegue1 and ConcreteCollegue2, both used by ConcreteMediator? So, we can translate this into C# code as:
abstract class Mediator;
class ConcreteMediator: Mediator {
private ConcreteCollegue1 collegue1;
public ConcreteCollegue1 Collegue1 {
set {collegue1 = value;}
}
private ConcreteCollegue2 collegue2;
public ConcreteCollegue2 Collegue2 {
set {collegue2 = value;}
}
}
abstract class Collegue {
protected Mediator mediator;
public Collegue(Mediator mediator) {
this.mediator = mediator;
}
}
class ConcreteCollegue1: Collegue {
public ConcreteCollegue1(Mediator mediator): base(mediator){}
}
class ConcreteCollegue2: Collegue {
public ConcreteCollegue2(Mediator m): base(mediator){}
}
main() {
ConcreteMediator m = new ConcreteMediator();
ConcreteCollegue1 c1 = new ConcreteCollegue1(m);
ConcreteCollegue1 c2 = new ConcreteCollegue2(m);
m.Collegue1 = c1;
m.Collegue2 = c2;
}
That's all information we can extract from this diagram, for some other details we'd need some other diagrams, like a sequence diagram. Also, we considered some best practices for C#, like creating only public setters. In ConcreteMediator we have access to collegue1 & collegue2 private properties which can be used from whatever functionality we implement in that mediator class.
On the website you can see a full C# implementation.
Getting used to "read" class diagrams may help understanding and implementing design patterns, because I think it's easier to remember differences and details of various patterns graphically instead of the implementation code. Also, in many cases is more important to understand the classes, interfaces and relationships between them instead of some kind of implementation, which can slightly vary from project to project. For instance, you can use public properties or fields, or constructor injection on how the objects are created and passed around. Even for mediator example above there may be other solutions that does similar functionality, but the pattern itself is described by the class diagram, not by implementation details.
Friday, March 22, 2019
Uninstalling .NET Core 3.0 preview3
A few days ago I installed VS 2019 (preview, on Mac OS) with .NET Core 3.0 preview 3 (latest, at this time) and all instances of Visual Studio (including 2017) stopped working when application run in the IDE. It worked from CLI, but not the IDE, which was a nuisance. What was strange is that it didn't work for .NET Core 2.2 projects on VS 2017, even though .NET 3.0 was only for VS 2019.
The error was like:
I waited some time, but then the just decided to uninstall .NET Core 3.0 preview 3 following this:
$ dotnet --list-sdks
[...]
3.0.100-preview3-010431 /usr/local/share/dotnet/sdk
$ sudo rm -rf /usr/local/share/dotnet/sdk/3.0.100-preview3-010431
$ dotnet --list-runtimes
[...]
Microsoft.AspNetCore.App 3.0.0-preview3-19153-02 /usr/local/share/dotnet/shared/Microsoft.AspNetCore.App
Microsoft.NETCore.App 3.0.0-preview3-27503-5 /usr/local/share/dotnet/shared/Microsoft.NETCore.App
$ sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App 3.0.0-preview3-19153-02
$ sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.AspNetCore.App/Microsoft.NETCore.App 3.0.0-preview3-27503-5
(I also tried to install just the run-time, but didn't help)
Uninstalling a version of .NET Core is pretty easy, just delete the folder under /usr/local/share/dotnet/sdk and restart VS. Then check the IDE -> Tools -> SDK Manager under .NET Core:
Done. Now all my previous .NET Core 2.2 run again from IDE.
I'll definitely try later with another version of .NET Core 3.0.
The error was like:
/usr/local/share/dotnet/sdk/3.0.100-preview3-010431/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(5,5): Error MSB4018: The "ResolvePackageAssets" task failed unexpectedly.I searched online and found 2 open issues on GitHub related to this, #2460 & #2461 (see my comments there).
System.TypeLoadException: Could not resolve type with token 0100003f from typeref (expected class 'NuGet.Packaging.Core.PackageDependency' in assembly 'NuGet.Packaging, Version=5.0.0.4, Culture=neutral, PublicKeyToken=31bf3856ad364e35') [...]
I waited some time, but then the just decided to uninstall .NET Core 3.0 preview 3 following this:
$ dotnet --list-sdks
[...]
3.0.100-preview3-010431 /usr/local/share/dotnet/sdk
$ sudo rm -rf /usr/local/share/dotnet/sdk/3.0.100-preview3-010431
$ dotnet --list-runtimes
[...]
Microsoft.AspNetCore.App 3.0.0-preview3-19153-02 /usr/local/share/dotnet/shared/Microsoft.AspNetCore.App
Microsoft.NETCore.App 3.0.0-preview3-27503-5 /usr/local/share/dotnet/shared/Microsoft.NETCore.App
$ sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App 3.0.0-preview3-19153-02
$ sudo rm -rf /usr/local/share/dotnet/shared/Microsoft.AspNetCore.App/Microsoft.NETCore.App 3.0.0-preview3-27503-5
(I also tried to install just the run-time, but didn't help)
Uninstalling a version of .NET Core is pretty easy, just delete the folder under /usr/local/share/dotnet/sdk and restart VS. Then check the IDE -> Tools -> SDK Manager under .NET Core:
Done. Now all my previous .NET Core 2.2 run again from IDE.
I'll definitely try later with another version of .NET Core 3.0.
Wednesday, March 13, 2019
Traefik getting started
After previous post I've really wanted to get started and do some testing with Traefik.io. I started a bit on a wrong foot, but eventually all worked out fine. Many times, having some issues with a new tool or technology is best way to get you digging into the details and learn a lot.
For beginning I wanted to use it as a simple reverse proxy, similarly to NGINX. I installed Traefik locally (very simple, just an executable) and used my SiteGo test project, both as a simple local application and using Docker version:
docker run -t -i -p 8000:8000 ovicrisan/sitego
Then I created sitego.toml file needed for Traefik configuration, like this:
[entryPoints]
[entryPoints.http]
address = ":8081"
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.routes.test_1]
rule = "Host:localhost"
[backends]
[backends.backend1]
[backends.backend1.servers.server1]
url = "http://localhost:8000"
[file]
#[api]
And start it locally with
traefik -c sitego.toml --accessLog
-c is for config file ('sitego.toml'), and --accessLog to show in terminal / console all requests.
Opening in the browser with http://localhost:8081 worked fine
Very important note here: don't forget [file] config setting, otherwise you'll get an 404 error ("page not found") with the message "backend not found". That setting will define a 'provider' which is necessary for all thing to work. There is another option to pass all config settings as parameters in command line (or Docker command), but for simple projects I prefer TOML file.
You can enable / disable [api] to access Web UI (dashboard) for metrics and stuff, then just load it at http://localhost:8080.
Intentionally I didn't want to use it from Docker container, no TLS (https) and other details, just to keep it to a bare minimum. I'll definitely use it for much more, including some ASP.NET Core microservices.
For beginning I wanted to use it as a simple reverse proxy, similarly to NGINX. I installed Traefik locally (very simple, just an executable) and used my SiteGo test project, both as a simple local application and using Docker version:
docker run -t -i -p 8000:8000 ovicrisan/sitego
Then I created sitego.toml file needed for Traefik configuration, like this:
[entryPoints]
[entryPoints.http]
address = ":8081"
[frontends]
[frontends.frontend1]
backend = "backend1"
[frontends.frontend1.routes.test_1]
rule = "Host:localhost"
[backends]
[backends.backend1]
[backends.backend1.servers.server1]
url = "http://localhost:8000"
[file]
#[api]
And start it locally with
traefik -c sitego.toml --accessLog
-c is for config file ('sitego.toml'), and --accessLog to show in terminal / console all requests.
Opening in the browser with http://localhost:8081 worked fine
Very important note here: don't forget [file] config setting, otherwise you'll get an 404 error ("page not found") with the message "backend not found". That setting will define a 'provider' which is necessary for all thing to work. There is another option to pass all config settings as parameters in command line (or Docker command), but for simple projects I prefer TOML file.
You can enable / disable [api] to access Web UI (dashboard) for metrics and stuff, then just load it at http://localhost:8080.
Intentionally I didn't want to use it from Docker container, no TLS (https) and other details, just to keep it to a bare minimum. I'll definitely use it for much more, including some ASP.NET Core microservices.
Monday, March 11, 2019
NGINX (to Join F5) vs Traefik
I've read today's news, NGINX to Join F5: Proud to Finish One Chapter and Excited to Start the Next, which made me think again about what may come next. Probably Traefik.io.
I'm using NGIX for some years, mostly for some small websites (PHP), but also as reverse proxy for ASP.NET Core apps. I like that has a small footprint and open source version was enough for what I needed. It's not difficult to setup and upstream servers are pretty good for load balancing.
Of course I've read "And make no mistake about it: F5 is committed to keeping the NGINX brand and open source technology alive", and probably will continue for years to come this way, but still, this may be a good chance to look with different eyes to Traefik.
I didn't use it for anything, yet, but I'll try it very soon, because from what I've read and seen, it seems better fit for microservices / Docker / K8s clusters and the like. Looks like better integrated with lots of backends and excellent features (like Let's Encrypt automatic support + metrics).
I'm not saying bye to NGIX, but welcome Traefik. See this picture, isn't it cool?
I'm using NGIX for some years, mostly for some small websites (PHP), but also as reverse proxy for ASP.NET Core apps. I like that has a small footprint and open source version was enough for what I needed. It's not difficult to setup and upstream servers are pretty good for load balancing.
Of course I've read "And make no mistake about it: F5 is committed to keeping the NGINX brand and open source technology alive", and probably will continue for years to come this way, but still, this may be a good chance to look with different eyes to Traefik.
I didn't use it for anything, yet, but I'll try it very soon, because from what I've read and seen, it seems better fit for microservices / Docker / K8s clusters and the like. Looks like better integrated with lots of backends and excellent features (like Let's Encrypt automatic support + metrics).
I'm not saying bye to NGIX, but welcome Traefik. See this picture, isn't it cool?
Unit testing protected async method with Moq, XUnit and ASP.NET Core
There are a few good examples online about using protected methods in XUnit tests using Moq, but this example will combine it with async/await, for a more realistic sample.
We'll work with the default Visual Studio template, just adding few minimal lines of code, with an additional project for unit testing.
First of, we add a new HomeService.cs class with an interface having 2 methods to increment and decrement a given value:
public interface IHomeService
{
Task<int> IncrAsync(int i);
Task<int> DecrAsync(int i);
}
public class HomeService : IHomeService
{
public Task<int> DecrAsync(int i)
{
return OpAsync(i, -1);
}
public Task<int> IncrAsync(int i)
{
return OpAsync(i, 1);
}
protected async Task<int> OpAsync(int i, int step)
{
return await Task.Run(async () =>
{
await Task.Delay(3000);
//Thread.Sleep(3000);
return i + step;
});
}
}
Here, we wanted to use a protected (non-public) method used by both public interface methods, for simplicity. There are many times when a protected method make sense, for various reasons.
Instead of using the blocking Thread.Sleep() I used awaitable Task.Delay(), waiting for 3 seconds. Note that without await keyword the task is not blocking, it just continue immediately. When both IncrAsync() and DecrAsync() are called the code waits for 3 + 3 seconds, which is very noticeable in unit testing.
We also add IHomeService to ASP.NET Core dependency injection, so in Startup.cs in ConfigureServices() we have this (let's say we need a scoped lifetime):
services.AddScoped<IHomeService, HomeService>();
Then, let's use it in default About action of HomeController:
public async Task<IActionResult>
About([FromServices] IHomeService homeService)
{
int n = await homeService.IncrAsync(4);
ViewData["Message"] = "Your application description page.4"
+ await homeService.DecrAsync(n);
return View();
}
As you can see, we call once the service to increment default 4 value, then call it again to decrement it to original value.
Now, let's switch to the unit testing project and after adding a reference to the MVC project let's write some tests for the service itself. In HomeServiceTests.cs we may have
public class HomeServiceTests
{
[Fact]
public async void IHomeService_Incr_Success_With_Delay()
{
IHomeService homeService = new HomeService();
int n = await homeService.IncrAsync(2);
Assert.Equal(3, n);
}
[Fact]
public async Task IHomeService_Incr_Success_No_Delay()
{
var mock = new Mock<HomeService>();
mock.Protected().Setup<Task<int>>("OpAsync", ItExpr.IsAny<int>(),
ItExpr.IsAny<int>()).Returns(Task.FromResult<int>(3));
int n = await mock.Object.IncrAsync(2);
Assert.Equal(3, n);
}
}
First test, IHomeService_Incr_Success_With_Delay(), is just calling the service methods which will wait for those 3 seconds.
For second test we want to skip that waiting by mocking OpAsync() method. Don't forget that OpAsync() is protected, so we can't just call it. For this, we use Moq.Protected, but still some changes to the code are necessary. Most importantly, we have to declare OpAsync() as virtual, so its signature in HomeService.ca will be:
If we want to test the controller itself (HomeController) we can have in a HomeControllerTests.cs something like this:
public class HomeControllerTests
{
[Fact]
public async void HomeController_About_Success_With_Delay()
{
var homeController = new HomeController();
IHomeService homeService = new HomeService();
var x = await homeController.About(homeService) as ViewResult;
Assert.NotNull(x);
Assert.True(x.ViewData["Message"].ToString() ==
"Your application description page.4");
}
[Fact]
public async Task HomeController_About_Success_No_Delay()
{
var mock = new Mock<HomeService>();
mock.Protected().Setup<Task<int>>("OpAsync", ItExpr.IsAny<int>(),
ItExpr.IsAny<int>()).Returns(Task.FromResult<int>(4));
var homeController = new HomeController();
var x = await homeController.About(mock.Object) as ViewResult;
Assert.NotNull(x);
Assert.True(x.ViewData["Message"].ToString() ==
"Your application description page.4");
}
}
Again, first test is just calling the action waiting for 3 + 3 seconds, while the second test mock OpAsync() similarly to HomeServiceTests. For asserts we can use directly the ViewData[] value.
The alternative would be that you manually create a class inheriting from HomeService with a public method that just call the base protected OpAsync(), but using the Moq built-in functionality may be quicker to develop.
It's true this code doesn't follow strictly SOLID principles, especially the D part ("One should depend upon abstractions, not concretions") because we tested mostly here the concrete HomeService class instead of IHomeService interface, but this is an example about testing protected methods which only make sense in classes, not interfaces (which are supposed to be public).
We'll work with the default Visual Studio template, just adding few minimal lines of code, with an additional project for unit testing.
First of, we add a new HomeService.cs class with an interface having 2 methods to increment and decrement a given value:
public interface IHomeService
{
Task<int> IncrAsync(int i);
Task<int> DecrAsync(int i);
}
public class HomeService : IHomeService
{
public Task<int> DecrAsync(int i)
{
return OpAsync(i, -1);
}
public Task<int> IncrAsync(int i)
{
return OpAsync(i, 1);
}
protected async Task<int> OpAsync(int i, int step)
{
return await Task.Run(async () =>
{
await Task.Delay(3000);
//Thread.Sleep(3000);
return i + step;
});
}
}
Here, we wanted to use a protected (non-public) method used by both public interface methods, for simplicity. There are many times when a protected method make sense, for various reasons.
Instead of using the blocking Thread.Sleep() I used awaitable Task.Delay(), waiting for 3 seconds. Note that without await keyword the task is not blocking, it just continue immediately. When both IncrAsync() and DecrAsync() are called the code waits for 3 + 3 seconds, which is very noticeable in unit testing.
We also add IHomeService to ASP.NET Core dependency injection, so in Startup.cs in ConfigureServices() we have this (let's say we need a scoped lifetime):
services.AddScoped<IHomeService, HomeService>();
Then, let's use it in default About action of HomeController:
public async Task<IActionResult>
About([FromServices] IHomeService homeService)
{
int n = await homeService.IncrAsync(4);
ViewData["Message"] = "Your application description page.4"
+ await homeService.DecrAsync(n);
return View();
}
As you can see, we call once the service to increment default 4 value, then call it again to decrement it to original value.
Now, let's switch to the unit testing project and after adding a reference to the MVC project let's write some tests for the service itself. In HomeServiceTests.cs we may have
public class HomeServiceTests
{
[Fact]
public async void IHomeService_Incr_Success_With_Delay()
{
IHomeService homeService = new HomeService();
int n = await homeService.IncrAsync(2);
Assert.Equal(3, n);
}
[Fact]
public async Task IHomeService_Incr_Success_No_Delay()
{
var mock = new Mock<HomeService>();
mock.Protected().Setup<Task<int>>("OpAsync", ItExpr.IsAny<int>(),
ItExpr.IsAny<int>()).Returns(Task.FromResult<int>(3));
int n = await mock.Object.IncrAsync(2);
Assert.Equal(3, n);
}
}
First test, IHomeService_Incr_Success_With_Delay(), is just calling the service methods which will wait for those 3 seconds.
For second test we want to skip that waiting by mocking OpAsync() method. Don't forget that OpAsync() is protected, so we can't just call it. For this, we use Moq.Protected, but still some changes to the code are necessary. Most importantly, we have to declare OpAsync() as virtual, so its signature in HomeService.ca will be:
protected virtual async Task<int> OpAsync(int i, int step)Also notice the way how we mock that async method (returning Task<int>) and declaring parameters with ItExpr.IsAny< >(), instead of just It.IsAny< >.
If we want to test the controller itself (HomeController) we can have in a HomeControllerTests.cs something like this:
public class HomeControllerTests
{
[Fact]
public async void HomeController_About_Success_With_Delay()
{
var homeController = new HomeController();
IHomeService homeService = new HomeService();
var x = await homeController.About(homeService) as ViewResult;
Assert.NotNull(x);
Assert.True(x.ViewData["Message"].ToString() ==
"Your application description page.4");
}
[Fact]
public async Task HomeController_About_Success_No_Delay()
{
var mock = new Mock<HomeService>();
mock.Protected().Setup<Task<int>>("OpAsync", ItExpr.IsAny<int>(),
ItExpr.IsAny<int>()).Returns(Task.FromResult<int>(4));
var homeController = new HomeController();
var x = await homeController.About(mock.Object) as ViewResult;
Assert.NotNull(x);
Assert.True(x.ViewData["Message"].ToString() ==
"Your application description page.4");
}
}
Again, first test is just calling the action waiting for 3 + 3 seconds, while the second test mock OpAsync() similarly to HomeServiceTests. For asserts we can use directly the ViewData[] value.
The alternative would be that you manually create a class inheriting from HomeService with a public method that just call the base protected OpAsync(), but using the Moq built-in functionality may be quicker to develop.
It's true this code doesn't follow strictly SOLID principles, especially the D part ("One should depend upon abstractions, not concretions") because we tested mostly here the concrete HomeService class instead of IHomeService interface, but this is an example about testing protected methods which only make sense in classes, not interfaces (which are supposed to be public).
Tuesday, March 5, 2019
Subscribe to:
Posts (Atom)