September 08 2025
dotnet tool install -g uno.check
uno.check
app.MapGet("/weather", (string city) =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
)).ToArray();
// deterministic pick for a couple of city names
var selected = city switch
{
string s when s.Equals("Belgrade", StringComparison.OrdinalIgnoreCase) => forecast[0],
string s when s.Equals("Paris", StringComparison.OrdinalIgnoreCase) => forecast[1],
_ => forecast[2]
};
var humidity = Random.Shared.Next(30, 90);
var icon = iconBySummary.TryGetValue(selected.Summary ?? "", out var ic) ? ic : "01d";
var response = new WeatherResponse(
Name: city,
Main: new MainInfo(Temp: selected.TemperatureC, Humidity: humidity),
Weather: new List<WeatherInfo>
{
new WeatherInfo(
Description: (selected.Summary ?? "unknown").ToLowerInvariant(),
Icon: icon)
}
);
});
<Page
x:Class="TheWeather.Presentation.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="TheWeather"
FontSize="28"
FontWeight="SemiBold"
Margin="16,24,16,12"
HorizontalAlignment="Center" />
<StackPanel Grid.Row="1"
Spacing="12"
Margin="16"
HorizontalAlignment="Center"
Width="460">
<TextBox PlaceholderText="City"
Text="{Binding City, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button Content="Get Weather"
Command="{Binding LoadCommand}" />
<ProgressBar IsIndeterminate="True"
Visibility="{Binding IsBusy, Converter={StaticResource BoolToVisibilityConverter}}" />
<TextBlock Text="{Binding StatusMessage}" Opacity="0.75" Foreground="White" />
<Border Padding="16" CornerRadius="12" BorderBrush="#33000000" BorderThickness="1">
<StackPanel Spacing="8" HorizontalAlignment="Center">
<TextBlock Text="{Binding Temperature}" FontSize="36" FontWeight="SemiBold" Foreground="White" />
<TextBlock Text="Feel: Warm" Foreground="White" />
</StackPanel>
</Border>
</StackPanel>
</Grid>
</Page>
public sealed class WeatherResponse
{
[JsonPropertyName("name")] public string? City { get; set; }
[JsonPropertyName("main")] public MainInfo? Main { get; set; }
[JsonPropertyName("weather")] public List<WeatherInfo>? Weather { get; set; }
}
public sealed class MainInfo
{
[JsonPropertyName("temp")] public double Temp { get; set; }
}
public sealed class WeatherInfo
{
[JsonPropertyName("description")] public string? Description { get; set; }
[JsonPropertyName("icon")] public string? Icon { get; set; }
}
public sealed class WeatherService(HttpClient http) : IWeatherService
{
private static readonly JsonSerializerOptions JsonOpts = new(JsonSerializerDefaults.Web);
public async Task<WeatherResponse?> GetByCityAsync(string city, CancellationToken ct = default)
{
// Expecting a proxy endpoint /weather?city=...
var response = await http.GetAsync($"/weather?city={Uri.EscapeDataString(city)}", ct);
if (!response.IsSuccessStatusCode) return null;
await using var s = await response.Content.ReadAsStreamAsync(ct);
return await JsonSerializer.DeserializeAsync<WeatherResponse>(s, JsonOpts, ct);
}
}
public partial class MainModel : ObservableObject
{
private readonly IWeatherService _service;
[ObservableProperty] private string _city = "Paris";
[ObservableProperty] private bool _isBusy;
[ObservableProperty] private string? _statusMessage = "Ready";
[ObservableProperty] private string? _temperature;
[ObservableProperty] private string? _details;
[ObservableProperty] private string? _iconUrl;
public IAsyncRelayCommand LoadCommand { get; }
public MainModel(IWeatherService service)
{
_service = service;
LoadCommand = new AsyncRelayCommand(LoadAsync);
}
private async Task LoadAsync()
{
try
{
IsBusy = true;
StatusMessage = $"Loading weather for {City}...";
var data = await _service.GetByCityAsync(City);
if (data is null)
{
StatusMessage = "No data found.";
Temperature = Details = IconUrl = null;
return;
}
var tempC = data.Main?.Temp ?? 0;
var desc = data.Weather?.FirstOrDefault()?.Description ?? "n/a";
var hum = data.Main?.Humidity ?? 0;
var icon = data.Weather?.FirstOrDefault()?.Icon;
Temperature = $"{tempC:0.#}°C";
Details = $"{desc} · Humidity {hum}%";
IconUrl = string.IsNullOrWhiteSpace(icon) ? null : $"https://openweathermap.org/img/wn/{icon}@2x.png";
StatusMessage = $"Weather for {data.City ?? City}";
}
catch (Exception ex)
{
StatusMessage = $"Error: {ex.Message}";
}
finally
{
IsBusy = false;
}
}
}
.ConfigureServices((context, services) =>
{
var baseUri = new Uri("https://localhost:7121");
services.AddHttpClient<IWeatherService, WeatherService>(c => c.BaseAddress = baseUri);
services.AddTransient<MainModel>();
})
.UseNavigation(ReactiveViewModelMappings.ViewModelMappings, RegisterRoutes)
1. Design Patterns that Deliver
This isn’t just another design patterns book. Dive into real-world examples and practical solutions to real problems in real applications.Check out it here.
Go-to resource for understanding the core concepts of design patterns without the overwhelming complexity. In this concise and affordable ebook, I've distilled the essence of design patterns into an easy-to-digest format. It is a Beginner level. Check out it here.
Every Monday morning, I share 1 actionable tip on C#, .NET & Arcitecture topic, that you can use right away.
Join 17,150+ subscribers to improve your .NET Knowledge.
Subscribe to the TheCodeMan.net and be among the 17,150+ subscribers gaining practical tips and resources to enhance your .NET expertise.