Uno Platform Extensions Services
Patterns for the Uno.Extensions service layer: hosting, DI, authentication, HTTP, configuration, logging, and storage.
Critical Rules
Hosting and Dependency Injection
- •Always start with
.UseConfiguration()before other extensions - Configuration is a dependency of most other extensions - •Use
TryAddSingleton/TryAddTransient- Allows downstream code to override registrations - •Constructor injection is the primary resolution pattern - Inject
IServiceProvideronly as a last resort - •Named services use
AddNamedSingleton<TService, TImpl>("name")and resolve withGetRequiredNamedService<TService>("name")
csharp
// App.xaml.cs - host builder setup
var builder = this.CreateBuilder(args)
.Configure(host => host
.UseConfiguration()
.UseLogging()
.UseSerilog()
.UseAuthentication()
.UseHttp()
.ConfigureServices((ctx, services) =>
{
services.TryAddSingleton<IMyService, MyService>();
})
);
UnoFeatures Required
xml
<UnoFeatures>
Hosting;
Configuration;
Logging;
LoggingSerilog;
Http;
HttpKiota; <!-- or HttpRefit -->
Authentication;
AuthenticationMsal; <!-- or AuthenticationOidc -->
Storage;
</UnoFeatures>
Authentication
- •MSAL for Microsoft identity (Azure AD, Azure AD B2C)
- •OIDC for any OpenID Connect provider (IdentityServer, Auth0, Okta)
- •Add
AuthenticationMsalorAuthenticationOidcto UnoFeatures - •MSAL 5.2+:
AddMsal()requires aWindowparameter
csharp
.UseAuthentication(auth =>
auth.AddMsal(msal =>
msal
.Builder(b => b.WithAuthority("https://login.microsoftonline.com/{tenantId}"))
.Scopes(new[] { "User.Read" })
)
)
csharp
// OIDC
.UseAuthentication(auth =>
auth.AddOidc(oidc =>
oidc
.Authority("https://your-identity-server.com")
.ClientId("your-client-id")
.Scopes(new[] { "openid", "profile" })
)
)
Common Mistakes:
- •Forgetting the Window parameter for MSAL on 5.2+
- •Not registering redirect URIs per platform (Android needs intent filter, iOS needs URL scheme)
- •Using
AuthenticationUnoFeature alone withoutAuthenticationMsalorAuthenticationOidc
HTTP Clients
- •Kiota (preferred): Generate strongly-typed clients from OpenAPI specs
- •Refit: Interface-based HTTP clients with attribute routing
- •Configure endpoints in
appsettings.json, not hardcoded URLs
csharp
// Kiota setup
.UseHttp(http =>
http.AddClient<MyApiClient>(ctx =>
new MyApiClient(
new HttpClientRequestAdapter(
new AnonymousAuthenticationProvider(),
httpClient: ctx.HttpClient)))
)
csharp
// Refit setup
.UseHttp(http =>
http.AddRefitClient<IMyApi>(ctx =>
new RefitSettings())
)
json
// appsettings.json
{
"MyApi": {
"Url": "https://api.example.com",
"UseNativeHandler": true
}
}
Common Mistakes:
- •Hardcoding base URLs instead of using configuration
- •Not using
UseNativeHandler: truefor platform-optimized networking - •Creating
HttpClientinstances manually instead of through DI
Configuration
- •Embed
appsettings.jsonasEmbeddedResourcein the project - •Use
IOptions<T>for read-only,IWriteableOptions<T>for runtime changes - •Environment-specific overrides:
appsettings.development.json
csharp
.UseConfiguration(config =>
config
.EmbeddedSource<App>()
.Section<MySettings>()
)
csharp
// Consuming in a ViewModel
public class MyViewModel
{
public MyViewModel(IOptions<MySettings> settings)
{
var baseUrl = settings.Value.BaseUrl;
}
}
Logging
- •
UseLogging()registersILogger<T>in DI - •
UseSerilog()adds Serilog with structured logging and configurable sinks - •Add
LoggingSerilogto UnoFeatures for Serilog support
csharp
.UseLogging(configure: logBuilder =>
logBuilder
.SetMinimumLevel(LogLevel.Information)
.AddFilter("Uno", LogLevel.Warning)
)
.UseSerilog()
Detailed References
- •references/01-hosting-di.md - Read when setting up host builder, registering services, or using named services
- •references/02-authentication.md - Read when adding MSAL, OIDC, or custom auth providers
- •references/03-http-clients.md - Read when configuring Kiota, Refit, or custom HTTP handlers
- •references/04-configuration-logging.md - Read when setting up appsettings, IOptions, ILogger, or Serilog