This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var implementationTypes = AppDomain.CurrentDomain | |
| .GetAssemblies() | |
| .SelectMany(x => x.GetTypes()) | |
| .Where(t => t.GetInterface(typeof(IValidator<>).FullName) != null) | |
| .Where(t => !t.Name.Contains("InlineValidator") && !t.Name.Contains("AbstractValidator")) | |
| .ToList(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Before (FluentValidation ≤ 11.4) | |
| public interface IValidator<T> | |
| // After (FluentValidation > 11.4) | |
| public interface IValidator<in T> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public static IServiceCollection AddValidators(this IServiceCollection services, | |
| ServiceLifetime lifetime = ServiceLifetime.Scoped) | |
| { | |
| var fluentValidationAssembly = typeof(IValidator).Assembly; | |
| var implementationTypes = AppDomain.CurrentDomain | |
| .GetAssemblies() | |
| .SelectMany(x => | |
| { | |
| try { return x.GetTypes(); } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class CountryService | |
| { | |
| private readonly IDbContextFactory<CountryDbContext> _contextFactory; | |
| public CountryService(IDbContextFactory<CountryDbContext> contextFactory) | |
| => _contextFactory = contextFactory; | |
| public async IAsyncEnumerable<Country> StreamCountries( | |
| [EnumeratorCancellation] CancellationToken ct = default) | |
| { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| builder.Services.AddAuthentication() | |
| .AddJwtBearer(options => { | |
| options.Events = new JwtBearerEvents { | |
| OnMessageReceived = context => { | |
| var accessToken = context.Request.Query["access_token"]; | |
| // If the request is for the SSE endpoint, grab the token from the query string | |
| var path = context.HttpContext.Request.Path; | |
| if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/your-sse-endpoint")) { | |
| context.Token = accessToken; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Net.ServerSentEvents; | |
| app.MapGet("/countries/stream", (CountryService service, HttpRequest request, CancellationToken ct) => | |
| { | |
| // On reconnect, the browser sends this header automatically | |
| int.TryParse(request.Headers["Last-Event-ID"], out var lastEventId); | |
| async IAsyncEnumerable<SseItem<Country>> Stream( | |
| [EnumeratorCancellation] CancellationToken token) | |
| { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Component, inject, DestroyRef } from '@angular/core'; | |
| import { CountryStreamService } from './country-stream.service'; | |
| @Component({ | |
| template: ` | |
| @for (country of countryStream.countries(); track country.id) { | |
| <div>{{ country.name }} — {{ country.population | number }}</div> | |
| } | |
| @if (countryStream.error(); as err) { | |
| <p class="error">{{ err }}</p> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class CountryService | |
| { | |
| private readonly IDbContextFactory<CountryDbContext> _contextFactory; | |
| public CountryService(IDbContextFactory<CountryDbContext> contextFactory) | |
| => _contextFactory = contextFactory; | |
| public async IAsyncEnumerable<Country> StreamCountries( | |
| int startAfterId = 0, | |
| [EnumeratorCancellation] CancellationToken ct = default) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class Country | |
| { | |
| public int Id { get; set; } | |
| public required string Name { get; set; } | |
| public required string Code { get; set; } | |
| public long Population { get; set; } | |
| } | |
| public class CountryDbContext : DbContext | |
| { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var builder = WebApplication.CreateBuilder(args); | |
| var app = builder.Build(); | |
| // This endpoint only responds to api.localhost | |
| app.MapGet("/", () => "Welcome to the API") | |
| .RequireHost("api.localhost:7001"); | |
| // This endpoint only responds to admin.localhost | |
| app.MapGet("/", () => "Welcome to the Admin Dashboard") | |
| .RequireHost("admin.localhost:7002"); |
NewerOlder