This talk cover the principles and the best practices in creation of flexible Microsoft .NET Core-based applications in connection with Microsoft Azure services, as well as tools and libraries that greatly simplify the development, configuration and deployment of applications. Also, attention paid to some pitfalls that may be encountered while using .NET Core.
This presentation by Andrii Antilikatorov, Consultant at GlobalLogic Kharkiv, was delivered at GlobalLogic Kharkiv MS TechTalk #2 on November 4, 2017.
4. 4
.Net Core, Java, NodeJSâŚ
.NET Core will be as popular as Ruby and NodeJS.
.NET Core and NodeJS will be the most popular
platforms for back-end solution compete on the market.
In few years .NET Core (not Java) will be number one
choice for enterprise-level applications.
Analytics saysâŚ
6. 6
.NET Core :: Few Things
⢠Many mechanisms such as authentication,
security, component interactions now
changed comparing to .Net Framework.
⢠Many components and platforms (for example
for Desktop applications) missing.
⢠.NET Core provides corporate-level software
benefits for small projects
Photo is
example for
placement and
max. size
7. 7
.Net Core vs .Net Framework
⢠There are cross-platform needs.
⢠Application architecture is based on
microservices.
⢠Scalability and high performance are the
must. Need to get as much as possible out
of the box.
⢠Need to use both Linux and Windows
containers.
⢠You are running multiple .NET versions side-
by-side.
⢠Opensource framework is required.
.NET Core
⢠Application currently uses .NET Framework
and has strong dependencies on Windows.
⢠Need to use Windows APIs that are not
supported by .NET Core.
⢠Need to use third-party libraries or NuGet
packages that are not available for .NET
Core.
⢠Need tools, technologies or platforms not
supported by .NET Core.
.Net Framework
8. 8
.Net Core vs .Net Framework :: Docker Containers
Architecture / App Type Linux containers Windows Containers
Microservices on containers .NET Core .NET Core
Monolithic app .NET Core .NET Framework, .NET Core
Best-in-class performance and scalability .NET Core .NET Core
Windows Server legacy app (âbrown-fieldâ) migration to
containers
-- .NET Framework
New container-based development (âgreen-fieldâ) .NET Core .NET Core
ASP.NET Core .NET Core .NET Core (recommended)
.NET Framework
ASP.NET 4 (MVC 5, Web API 2, and Web Forms) -- .NET Framework
SignalR services .NET Core .NET Framework
.NET Core
WCF, WF, and other legacy frameworks Limited WCF support
in .NET Core
.NET Framework
Limited WCF support in
.NET Core
Consumption of Azure services .NET Core .NET Framework, .NET Core
10. 10
Microservices :: Pros and Cons
⢠Each microservice is relatively smallâeasy to
manage and evolve.
⢠It is possible to scale out individual areas of
the application.
⢠You can divide the development work
between multiple teams.
⢠Issues are more isolated.
⢠You can use the latest technologies.
Benefits
⢠Distributed application adds complexity for
developers.
⢠Deployment complexity.
⢠Atomic transactions usually are not possible.
⢠Usually increase hardware resource needs
⢠Communication complexity.
⢠Partitioning the microservices.
Disadvantages
11. 11
.Net Core Apps :: Hosting
Feature App
Service
Service
Fabric
Virtual
Machine
Near-Instant Deployment X X
Scale up to larger machines without redeploy X X
Instances share content and configuration; no need to redeploy or
reconfigure when scaling
X X
Multiple deployment environments (production, staging) X X
Automatic OS update management X
Seamless switching between 32/64 bit platforms X
Deploy code with Git, FTP X X
Deploy code with WebDeploy X X
Deploy code with TFS X X X
Host web or web service tier of multi-tier architecture X X X
Access Azure services like Service Bus, Storage, SQL Database X X X
Install any custom MSI X X
16. 16
API :: Direct Communication
Back-EndBack-End
Microservice 1
Microservice 2
Microservice N
Client AppsClient Apps
17. 17
API :: API Gateway
Back-EndBack-End
Microservice 1
Microservice 2
Microservice N
Client AppsClient Apps
API Gateway
18. 18
API :: API Gateway with Azure API Management
Back-EndBack-End
Microservice 1
Microservice 2
Microservice N
Client AppsClient Apps
Azure API
Management
19. 19
API :: Swagger
⢠Automatically generates API documentation
⢠Supports Client API generation and discoverability
⢠Provides ability to automatically consume and integrate APIs
20. 20
API :: Swagger :: Configuration
public void ConfigureServices(IServiceCollection services)
{
// API documentation configuration
var swaggerConfigurationInfo = new SwaggerConfigurationInfo() {
Title = âMy Application User API ",
Description = "Service provides all user specific information and management api.",
TermsOfService = âNoneâ,
SecuritySchemas = new List<SecurityScheme> {
// Define the OAuth2.0 scheme (i.e. Implicit Flow), for access_token the user of
// Swagger will be redirected to Auth0 Login hosted page to input credentials
new OAuth2Scheme { Type = "oauth2", Flow = "implicit", AuthorizationUrl =
m_identityProviderSettings.Auth0Authorize.AbsoluteUri,
Scopes = new Dictionary<string, string> { { "openid profile email", "Security API" }}
}}};
// Add Framework API services(API versioning, swagger, etc.)
services.AddApiServices(swaggerConfigurationInfo);
}
21. 21
API :: AutoRest
{autorest-location}autorest -Input http://{webapiname}.azurewebsites.net/swagger/
public async void InvokeTest()
{
UserApiClient client = new UserApiClient(...);
await client.IdentityUserActivatePostAsync(
new ActivateUserModel
{
ExternalReferenceId = "1354687252",
Password = "Qwerty123"
});
}
23. 23
API Versioning :: Business Rules
⢠API versioning shall be applicable for any API endpoint.
⢠Old versions has to be supported as long as you agreed with our clients.
⢠Old API versions should work the same way they worked before new
version was introduced.
⢠Old APIs shall be marked as deprecated.
⢠All versions has to be testable via unit/integration tests.
⢠Best practice is to apply versioning to external API only.
24. 24
API Versioning :: Versioning in the URI
⢠URI Path
https://mywebportal.com/api/v2/getUsers
⢠Query String
https://mywebportal.com/api/getUsers?v=2.0
25. 25
API Versioning :: Versioning with Header/Accept Header
GET /api/camps HTTP/1.1
Host: localhost:43333
Content-Type: application/json
X-version: 2.0
GET /api/camps HTTP/1.1
Host: localhost:43333
Content-Type: application/json
Accept: application/json;version=2.0
26. 26
API Versioning :: Versioning with Content Type
GET /api/camps HTTP/1.1
Host: localhost:43333
Content-Type: application/vnd.myapplication.v1+json
Accept: application/vnd.myapplication.v1+json
27. 27
API Versioning :: Versioning in Action
⢠Use Microsoft ASP.NET Api Versioning NuGet package
- Each controller should be marked with API version:
- Each old version API controller should be marked as deprecated
- Each API version should be stored in Version folder
- Each controller should be placed in specific namespace
- Unit and integration tests should be also stored separately
30. 30
EF Core :: Resilient Connections and Transactions
System.InvalidOperationException: The configured execution strategy
'SqlServerRetryingExecutionStrategy' does not support user initiated transactions. Use the
execution strategy returned by 'DbContext.Database.CreateExecutionStrategy()' to execute
all the operations in the transaction as a retriable unit.
// Use of resiliency strategy within an explicit transaction
var strategy = dbContext.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () => {
using (var transaction = dbContext.Database.BeginTransaction()) {
dbContext.Users.Update(user);
await dbContext.SaveChangesAsync();
await eventLogService.SaveEventAsync(userChangedEvent);
transaction.Commit();
}
});
SOLUTION
31. 31
EF Core :: Seeding
public class Startup
{
// Other Startup code...
public void Configure(IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
// Other Configure code...
// Seed data through our custom class
CatalogContextSeed.SeedAsync(app).Wait();
// Other Configure code...
}
}
32. 32
EF Core :: Seeding
public class CatalogContextSeed {
public static async Task SeedAsync(IApplicationBuilder applicationBuilder) {
var context = (AppDbContext)applicationBuilder.
ApplicationServices.GetService(typeof(AppDbContext));
using (context) {
context.Database.Migrate();
if (!context.Users.Any()) {
context.Users.AddRange(...);
await context.SaveChangesAsync();
}
if (!context.Departments.Any()) {
context.Departments.AddRange(...);
await context.SaveChangesAsync();
}
}
}
}
}
33. 33
EF Core :: Seeding Improvement
⢠Use standard migration mechanism.
⢠Create base class(es) for seed migrations.
⢠Specify data context via attribute.
34. 34
EF Core :: Seeding Improvement
/// <summary>
/// Seed Roles, RolesClaims and UserRoles
/// </summary>
[DbContext(typeof(MyContext))]
[Migration("SEED_201709121256_AddRolesClaimsUserRoles")]
public class AddRolesClaimsUserRoles : EmptyDbSeedMigration
{
/// <summary>
/// <see cref="SeedMigrationBase.PopulateData"/>
/// </summary>
protected override void PopulateData()
{
...
}
}
35. 35
EF Core :: In-Memory Database
public class Startup
{
// Other Startup code ...
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(Configuration);
// DbContext using an InMemory database provider
services.AddDbContext<AppDbContext>(opt =>
opt.UseInMemoryDatabase());
}
// Other Startup code ...
}
38. 38
Health Checks :: Middleware Registration
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseHealthChecks("/hc)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
39. 39
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Add health checks here.
services.AddHealthChecks(checks => {
checks.AddUrlCheck(âURL Check" )
.AddHealthCheckGroup("servers",
group => group
.AddUrlCheck("https://myserviceurl::8010")
.AddUrlCheck("https://tmysecondserviceurl:7777"))
}
services.AddMvc();
}
}
Health Checks :: Web Resources