What you will learn

  • Combine skills from the previous lessons into a full example
  • Retrieve current conditions via Open-Meteo without a paid API key
  • Remember the selected city using Preferences
How to use this example: Start from a new .NET MAUI App project called MauiWeather with .NET 10. Use the complete file listings below, and leave other template-generated files unchanged unless the lesson explicitly says otherwise. Run the Android target on Windows.
iOS testing: The shared code is designed for MAUI targets, but no iOS build is claimed. iOS compilation, device testing and App Store release require a Mac/Xcode toolchain.

1. Plan the weather dashboard

Create a .NET MAUI App named MauiWeather. The dashboard lets a user choose Kuala Lumpur, Singapore, Tokyo or London; then it retrieves current temperature, relative humidity and wind speed from the Open-Meteo forecast API over HTTPS. Fixed city coordinates avoid location permissions and make the example reproducible.

2. Design the XAML

The interface contains a Picker for the city, a Refresh button, a status label, and three result cards. A ScrollView keeps the page usable on smaller devices. This is a stand-alone example—no assets or paid subscriptions are required.

3. Implement the data retrieval

The code builds the URL using InvariantCulture to guarantee that decimal coordinates use periods. The Open-Meteo JSON response contains a current object. Read its temperature_2m, relative_humidity_2m and wind_speed_10m properties, then show the values in the UI.

The example catches networking, JSON parsing and timeout errors, prevents overlapping requests by disabling the Refresh button, and stores the selected city index with Preferences.Default.

4. Test the finished app

  1. Run the app on an Android emulator or connected Android phone.
  2. Choose Kuala Lumpur and tap Load weather.
  3. Change to another city and refresh.
  4. Restart the app to confirm the city selection is remembered.
  5. Disconnect the network and verify that the status label shows a useful error instead of crashing.

5. Next improvements

Add weather codes and icons, local caching, a timestamp of the last successful response and a list of favorite cities. An advanced version could use device location, but it would need platform permissions, explicit user consent and on-device validation.

API usage: Open-Meteo provides access under its published terms; check the current free/non-commercial conditions before using the API in a commercial application.

Complete sample code

Use the exact file names and folder locations shown below. Copy each listing into your MAUI project. The separate source files can also be downloaded individually.

MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiWeather.MainPage"
             Title="City Weather">
    <ScrollView>
        <VerticalStackLayout Padding="24" Spacing="14">
            <Label Text="City Weather Dashboard"
                   FontSize="26" FontAttributes="Bold" />
            <Label Text="Choose a city" />
            <Picker x:Name="CityPicker" Title="Select a city" />
            <Button x:Name="RefreshButton" Text="Load weather"
                    Clicked="OnRefreshClicked" />
            <Label x:Name="StatusLabel" Text="Tap Load weather."
                   FontSize="14" />
            <Border Padding="18" BackgroundColor="#E6F4FF"
                    StrokeShape="RoundRectangle 16">
                <VerticalStackLayout Spacing="6">
                    <Label Text="Temperature" TextColor="#34566E" />
                    <Label x:Name="TemperatureLabel" Text="—"
                           FontSize="32" FontAttributes="Bold" />
                </VerticalStackLayout>
            </Border>
            <Border Padding="18" BackgroundColor="#ECFDF5"
                    StrokeShape="RoundRectangle 16">
                <VerticalStackLayout Spacing="6">
                    <Label Text="Relative humidity" TextColor="#34566E" />
                    <Label x:Name="HumidityLabel" Text="—"
                           FontSize="24" />
                </VerticalStackLayout>
            </Border>
            <Border Padding="18" BackgroundColor="#F2F2FF"
                    StrokeShape="RoundRectangle 16">
                <VerticalStackLayout Spacing="6">
                    <Label Text="Wind speed" TextColor="#34566E" />
                    <Label x:Name="WindLabel" Text="—"
                           FontSize="24" />
                </VerticalStackLayout>
            </Border>
        </VerticalStackLayout>
    </ScrollView>
</ContentPage>
MainPage.xaml.cs
using Microsoft.Maui.Storage;
using System.Globalization;
using System.Text.Json;

namespace MauiWeather;

public partial class MainPage : ContentPage
{
    private static readonly HttpClient Client = new()
    {
        Timeout = TimeSpan.FromSeconds(15)
    };

    private readonly (string Name, double Lat, double Lon)[] cities =
    [
        ("Kuala Lumpur", 3.1390, 101.6869),
        ("Singapore", 1.3521, 103.8198),
        ("Tokyo", 35.6762, 139.6503),
        ("London", 51.5072, -0.1276)
    ];

    public MainPage()
    {
        InitializeComponent();
        CityPicker.ItemsSource = cities.Select(c => c.Name).ToList();
        int saved = Preferences.Default.Get("cityIndex", 0);
        CityPicker.SelectedIndex = Math.Clamp(saved, 0, cities.Length - 1);
    }

    private async void OnRefreshClicked(object sender, EventArgs e)
    {
        int index = CityPicker.SelectedIndex;
        if (index < 0) return;
        Preferences.Default.Set("cityIndex", index);
        var city = cities[index];

        string lat = city.Lat.ToString(CultureInfo.InvariantCulture);
        string lon = city.Lon.ToString(CultureInfo.InvariantCulture);
        string url = "https://api.open-meteo.com/v1/forecast" +
            $"?latitude={lat}&longitude={lon}" +
            "&current=temperature_2m,relative_humidity_2m,wind_speed_10m";

        RefreshButton.IsEnabled = false;
        StatusLabel.Text = $"Loading {city.Name}...";
        try
        {
            using var response = await Client.GetAsync(url);
            response.EnsureSuccessStatusCode();
            string jsonText = await response.Content.ReadAsStringAsync();
            using var doc = JsonDocument.Parse(jsonText);
            var current = doc.RootElement.GetProperty("current");

            double temp = current.GetProperty("temperature_2m").GetDouble();
            double humidity = current.GetProperty("relative_humidity_2m").GetDouble();
            double wind = current.GetProperty("wind_speed_10m").GetDouble();

            TemperatureLabel.Text = $"{temp:0.#} °C";
            HumidityLabel.Text = $"{humidity:0}%";
            WindLabel.Text = $"{wind:0.#} km/h";
            StatusLabel.Text = $"Current conditions for {city.Name}.";
        }
        catch (Exception ex) when (ex is HttpRequestException
                                  or TaskCanceledException
                                  or JsonException
                                  or KeyNotFoundException)
        {
            StatusLabel.Text = "Weather unavailable. Check the connection and try again.";
        }
        finally
        {
            RefreshButton.IsEnabled = true;
        }
    }
}
Platforms/Android/AndroidManifest.xml (permission excerpt)
<!-- Add inside the existing <manifest> element only if absent. -->
<uses-permission android:name="android.permission.INTERNET" />

Common problems and solutions

  • No data loads: Check Internet permission, connectivity and whether the Open-Meteo API is reachable.
  • Temperature stays blank: The app only fetches after you tap Load weather.
  • The weather values look different from another app: Weather providers use different models, refresh times and locations.

Practice exercise

Add a fifth city and a last-updated timestamp based on the response. Clearly label the timezone of the timestamp.

Expected result: A multi-city weather app retrieves current conditions over HTTPS and remembers the selected city.

Official references