.NET MAUI
``
xamarin · net · csharp - blazor · android · Backend - csharp - Desarrollo multiplataforma
Introducción a .NET MAUI
.NET MAUI (Multi-platform App UI) es el framework moderno de .NET para desarrollar aplicaciones nativas multiplataforma (Android, iOS, macOS y Windows) usando una base de código unificada en CSharp.
Surgió como evolución de Xamarin.Forms, con un enfoque más moderno, mayor rendimiento, soporte completo para MVVM y XAML, y una arquitectura más modular y extensible.
MAUI permite que los desarrolladores compartan la lógica del negocio, servicios y modelos de datos entre plataformas, manteniendo la capacidad de crear interfaces nativas mediante XAML o C#.
Características clave
- Un solo proyecto: gestión unificada de recursos, dependencias y configuración multiplataforma.
- Compatibilidad total con XAML para la definición de interfaces declarativas.
- MVVM integrado para separar lógica de presentación y vista.
- Hot Reload (XAML y C#): mejora drásticamente la productividad.
- Integración con Backends y APIs REST mediante CSharp.
- Desarrollo multiplataforma real: compila nativamente para Android, iOS, macOS y Windows.
- Interoperabilidad nativa: acceso directo a API de sistema y librerías específicas de cada plataforma.
Arquitectura general
- UI Layer (View): Interfaces en XAML o C#, dependientes de plataforma o compartidas.
- ViewModel Layer (MVVM): Gestión del estado, comandos, validaciones y enlace de datos.
- Model Layer: Lógica de negocio, entidades y acceso a datos.
- Services Layer: Integración con Backend, APIs o almacenamiento local (SQLite, Preferences, etc.).
Este diseño modular favorece la escalabilidad, testabilidad y mantenimiento del código.
Interfaces y XAML
XAML (eXtensible Application Markup Language) define la estructura visual y comportamientos de UI en MAUI.
Permite la vinculación directa con propiedades y comandos del ViewModel (Data Binding).
Ejemplo básico de una interfaz en MAUI:
Ejemplo: XAML básico
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.MainPage">
<VerticalStackLayout Padding="30">
<Label Text="Hola .NET MAUI"
FontSize="24"
HorizontalOptions="Center" />
<Button Text="Pulsa aquí"
Command="{Binding OnClickCommand}" />
</VerticalStackLayout>
</ContentPage>
`
Patrón MVVM en .NET MAUI
El patrón MVVM (Model-View-ViewModel) es la base para separar la lógica de UI de la lógica de negocio. Facilita el enlace de datos, el testing unitario y la reactividad en la aplicación.
Ejemplo: ViewModel en C#
public class MainViewModel : INotifyPropertyChanged
{
public ICommand OnClickCommand { get; }
private string _message;
public string Message
{
get => _message;
set { _message = value; OnPropertyChanged(); }
}
public MainViewModel()
{
OnClickCommand = new Command(() => Message = "¡Botón pulsado!");
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
El enlace con la vista se realiza automáticamente mediante data binding y el sistema de notificación de cambios (INotifyPropertyChanged).
Migración desde Xamarin.Forms
MAUI es el reemplazo natural de Xamarin.Forms:
- Se mantienen los principios de XAML y MVVM.
- Cambios mínimos en lógica, pero mejora en el sistema de proyecto unificado.
- Nuevas APIs para manejar dependencias, recursos y estilos compartidos.
- Migraciones asistidas disponibles desde Visual Studio y herramientas CLI.
Integración con Backend y lógica compartida
La lógica de negocio puede integrarse con:
- APIs REST o gRPC.
- Entity Framework Core o Prisma (si se usa con servicios externos).
- Autenticación JWT, OAuth o Auth0.
- Almacenamiento local mediante
Preferences,SecureStorageo SQLite.
Esto convierte a MAUI en un cliente nativo potente dentro de un ecosistema de arquitectura moderna (p. ej. con Clean Architecture o CQRS).
Ecosistema de UI relacionadas
WPF
Framework de UI basado en XAML para aplicaciones de escritorio Windows. MAUI hereda parte de sus conceptos, especialmente en data binding y estilos.
WinUI
Evolución moderna de la UI de Windows, base de Windows App SDK. MAUI usa WinUI como capa nativa cuando se ejecuta en Windows.
Recursos y documentación
- GitHub - dotnet/maui
- Documentación oficial de .NET MAUI
- ¿Qué es .NET MAUI?
- Patrón MVVM: fundamentos
-
[MVVM en .NET MAUI Microsoft Learn](https://learn.microsoft.com/es-es/dotnet/architecture/maui/mvvm) - Patrón MVVM reactivo (video)
- WPF Overview
- WinUI - Windows apps
Próximos temas sugeridos
- Integración con Blazor Hybrid
- Optimización de rendimiento en UI
- Despliegue multiplataforma (App Store / Play Store / Windows Store)
- Testing UI con MAUI Test Tools
- Estilos y temas globales con ResourceDictionary
- Integración CI/CD con GitHub Actions y Azure DevOps
.NET MAUI – Avanzado y ciclo de vida
net · csharp · xamarin · android · Backend
Ciclo de vida de una app .NET MAUI
MAUI abstrae los distintos ciclos de vida (Android, iOS, Windows, macOS) mediante la clase Application y los métodos globales de eventos:
- `OnStart()`: al iniciar la app.
- `OnSleep()`: cuando entra en segundo plano.
- `OnResume()`: al volver a primer plano.
También se pueden usar los eventos del MauiAppBuilder para configurar servicios o suscripciones globales antes del arranque.
Ejemplo: ciclo de vida en App.xaml.cs
public partial class App : Application
{
protected override void OnStart()
{
Console.WriteLine("App iniciada");
}
protected override void OnSleep()
{
Console.WriteLine("App suspendida");
}
protected override void OnResume()
{
Console.WriteLine("App reanudada");
}
}
`
Inyección de dependencias (DI)
.NET MAUI usa el sistema de DI nativo de .NET, facilitando la modularidad y testabilidad.
Los servicios se registran en MauiProgram.cs.
Ejemplo: configuración de DI
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder.Services.AddSingleton<ApiService>();
builder.Services.AddTransient<MainViewModel>();
builder.Services.AddTransient<MainPage>();
return builder.Build();
}
}
Esto permite inyectar dependencias automáticamente en constructores de vistas o viewmodels.
Integración con APIs nativas y permisos
MAUI proporciona acceso unificado a funcionalidades del dispositivo mediante Microsoft.Maui.Essentials:
- Sensores: GPS, acelerómetro, brújula.
- Sistema: batería, conectividad, almacenamiento.
- Multimedia: cámara, micrófono, galería.
- Seguridad: autenticación biométrica y permisos.
Ejemplo: uso de GPS
var location = await Geolocation.GetLastKnownLocationAsync();
if (location != null)
Console.WriteLine($"Lat: {location.Latitude}, Lon: {location.Longitude}");
Los permisos deben gestionarse en AndroidManifest.xml o Info.plist, según plataforma.
Persistencia local
Opciones comunes para almacenar datos en MAUI:
- Preferences: pares clave-valor simples.
- SecureStorage: datos cifrados (tokens, credenciales).
- SQLite: base de datos local estructurada.
Ejemplo: SQLite básico
public class Note
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Text { get; set; }
}
public class NoteDatabase
{
private readonly SQLiteAsyncConnection _database;
public NoteDatabase(string dbPath)
{
_database = new SQLiteAsyncConnection(dbPath);
_database.CreateTableAsync<Note>().Wait();
}
public Task<List<Note>> GetNotesAsync() => _database.Table<Note>().ToListAsync();
public Task<int> SaveNoteAsync(Note note) => _database.InsertOrReplaceAsync(note);
}
Optimización de rendimiento
- Usar imágenes escaladas por plataforma para evitar sobrecarga de GPU.
- Evitar layouts anidados: preferir
GridsobreStackLayout. - Compilar XAML (XAML Compilation) para reducir tiempo de carga.
- Lazy loading de recursos y vistas pesadas.
- Profiling con herramientas de Visual Studio o
dotnet-trace.
Testing y CI/CD
MAUI soporta tests unitarios y UI tests:
- Unit tests: lógica MVVM (usando xUnit o NUnit).
- UI tests: con Appium o MAUI Test Tools.
- CI/CD: integraciones con GitHub Actions, Azure DevOps o App Center.
Ejemplo: test de ViewModel
[Fact]
public void ClickCommand_ShouldChangeMessage()
{
var vm = new MainViewModel();
vm.OnClickCommand.Execute(null);
Assert.Equal("¡Botón pulsado!", vm.Message);
}
Despliegue y publicación
- Android: firma y exportación
.aabo.apk. - iOS: requiere cuenta de Apple Developer.
- Windows/macOS: empaquetado MSIX o
.pkg. - Distribución: AppCenter, Play Store, TestFlight, sideloading.
Recomendable usar pipelines automatizados para versionado y despliegue continuo.
Ejemplo completo: App de Notas con API REST + SQLite + MVVM
Estructura del proyecto
- Models/ →
Note.cs - ViewModels/ →
NotesViewModel.cs - Views/ →
NotesPage.xaml - Services/ →
ApiService.cs,NoteDatabase.cs
Flujo
- Al abrir la app, se cargan notas locales desde SQLite.
- El usuario puede sincronizar con una API REST remota.
- La UI reacciona mediante bindings MVVM.
- Los servicios se inyectan mediante DI.
Ejemplo: ApiService.cs
public class ApiService
{
private readonly HttpClient _client = new();
public async Task<List<Note>> GetNotesAsync()
{
var response = await _client.GetAsync("https://api.example.com/notes");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<List<Note>>(json);
}
}
Ejemplo: integración en ViewModel
public class NotesViewModel : INotifyPropertyChanged
{
private readonly ApiService _api;
private readonly NoteDatabase _db;
public ObservableCollection<Note> Notes { get; set; } = new();
public ICommand SyncCommand { get; }
public NotesViewModel(ApiService api, NoteDatabase db)
{
_api = api;
_db = db;
SyncCommand = new Command(async () => await SyncNotes());
}
private async Task SyncNotes()
{
var apiNotes = await _api.GetNotesAsync();
foreach (var note in apiNotes)
await _db.SaveNoteAsync(note);
Notes.Clear();
var local = await _db.GetNotesAsync();
foreach (var note in local)
Notes.Add(note);
}
}
Conclusión
Con estos módulos, .NET MAUI permite desarrollar aplicaciones multiplataforma robustas y modernas, integrando:
- Arquitectura MVVM.
- Persistencia local.
- Integración con Backend y APIs nativas.
- Flujo CI/CD completo.
Es una herramienta madura y central en el ecosistema .NET moderno para desarrollo móvil y de escritorio.
Recursos adicionales
.NET MAUI + Blazor Hybrid
net · csharp · blazor · maui · xamarin · frontend · Backend
Introducción a Blazor Hybrid en .NET MAUI
Blazor Hybrid permite combinar componentes web interactivos (Blazor) dentro de una aplicación nativa .NET MAUI, compartiendo la misma base de código en CSharp y .NET.
Esta integración une:
- La interfaz web basada en Razor Components.
- El renderizado nativo multiplataforma de MAUI.
- Un único modelo de programación full-stack C# (sin JavaScript).
El resultado: una aplicación que puede usar UI nativa o web embebida, con acceso a APIs del dispositivo y servicios locales, sin depender de un navegador externo.
Arquitectura híbrida
- BlazorWebView: el puente entre MAUI y Blazor.
- Razor Components: UI basada en HTML + C#.
- Services & ViewModels: compartidos entre Blazor y MAUI.
- Backend APIs (opcional): comunicación mediante HttpClient o SignalR.
[ MAUI Host ]
└── BlazorWebView
├── Razor Components
├── Shared C# Logic
└── Interop con servicios nativos (GPS, Storage, etc.)
`
Esta estructura permite usar Blazor para la UI principal, o solo para partes específicas de la app (por ejemplo, dashboards o vistas reactivas).
Configuración de un proyecto Blazor Hybrid
Se puede crear un proyecto desde Visual Studio o CLI:
dotnet new maui-blazor -n MyHybridApp
`
Esto genera un proyecto MAUI con:
MainPage.xaml: contenedor conBlazorWebView.wwwroot/: recursos estáticos (CSS, JS, imágenes).Pages/yShared/: componentes Razor.
Ejemplo: MainPage.xaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyHybridApp"
x:Class="MyHybridApp.MainPage">
<BlazorWebView HostPage="wwwroot/index.html">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
</ContentPage>
Ejemplo básico de componente Razor
@page "/"
@inject HttpClient Http
<h1>Notas desde API</h1>
@if (notes == null)
{
<p>Cargando...</p>
}
else
{
<ul>
@foreach (var note in notes)
{
<li>@note.Text</li>
}
</ul>
}
@code {
private List<Note>? notes;
protected override async Task OnInitializedAsync()
{
notes = await Http.GetFromJsonAsync<List<Note>>("https://api.example.com/notes");
}
}
Este componente puede ejecutarse dentro del BlazorWebView, accediendo a los mismos servicios registrados por MAUI.
Comunicación entre Blazor y MAUI (Interop)
Puedes exponer servicios nativos de MAUI (p. ej. GPS, almacenamiento, cámara) a Blazor mediante inyección de dependencias compartida:
Ejemplo: inyectar un servicio MAUI en Blazor
1. Registrar el servicio en MauiProgram.cs
builder.Services.AddSingleton<LocationService>();
2. Servicio nativo (C#)
public class LocationService
{
public async Task<string> GetLocationAsync()
{
var loc = await Geolocation.GetLastKnownLocationAsync();
return loc == null ? "Sin datos" : $"{loc.Latitude}, {loc.Longitude}";
}
}
3. Usar el servicio desde Blazor
@inject LocationService LocationService
<p>Ubicación actual: @location</p>
@code {
private string location = "Obteniendo...";
protected override async Task OnInitializedAsync()
{
location = await LocationService.GetLocationAsync();
}
}
Esto permite que un componente Razor acceda a hardware nativo sin usar JavaScript.
Compartir código entre UI nativa y Blazor
Un mismo ViewModel, Service o modelo de datos puede usarse tanto en:
- Una vista XAML nativa de MAUI.
- Un componente Razor Blazor.
Ejemplo
public class NotesService
{
private readonly HttpClient _http;
public NotesService(HttpClient http) => _http = http;
public async Task<List<Note>> GetNotesAsync() =>
await _http.GetFromJsonAsync<List<Note>>("https://api.example.com/notes");
}
Tanto una página XAML (NotesPage.xaml) como un componente Razor (Notes.razor) pueden inyectar y usar NotesService sin duplicar lógica.
Integración con Backend y APIs
Blazor Hybrid puede consumir:
- APIs REST del backend.
- Servicios locales del dispositivo.
- WebSockets o SignalR para actualizaciones en tiempo real.
- gRPC-Web si se desea rendimiento binario en entorno híbrido.
Los componentes Razor pueden trabajar en modo offline, almacenando datos con SQLite o SecureStorage y sincronizando al reconectarse.
Ejemplo completo: App híbrida de tareas
Arquitectura
- `MainPage.xaml` → contenedor con `BlazorWebView`.
- `Tasks.razor` → listado y formulario de tareas.
- `TaskService.cs` → servicio compartido (REST + SQLite).
Flujo
- El usuario crea o edita tareas desde el componente Blazor.
- Los datos se guardan localmente con SQLite.
- Se sincronizan con el backend mediante API REST.
- La UI Blazor refleja los cambios al instante.
Ejemplo de componente
@page "/tasks"
@inject TaskService TaskService
<h2>Tareas</h2>
<input @bind="newTask" placeholder="Nueva tarea" />
<button @onclick="AddTask">Agregar</button>
<ul>
@foreach (var task in tasks)
{
<li>@task.Text</li>
}
</ul>
@code {
private List<TaskItem> tasks = new();
private string newTask = "";
protected override async Task OnInitializedAsync()
{
tasks = await TaskService.GetTasksAsync();
}
private async Task AddTask()
{
await TaskService.AddTaskAsync(new TaskItem { Text = newTask });
tasks = await TaskService.GetTasksAsync();
newTask = "";
}
}
Ventajas de Blazor Hybrid
- Reutilización de código C# entre backend, lógica y UI.
- Renderizado web sin navegador externo.
- Acceso directo a APIs nativas.
- Actualización rápida mediante Hot Reload.
- Ideal para apps empresariales o multiplataforma con UI web existente.
Limitaciones y consideraciones
- Mayor consumo de memoria que una UI nativa pura.
- No apto para apps con animaciones o gráficos intensivos.
- Requiere mantener
wwwrooty componentes Razor. - Interfaz dependiente de WebView: rendimiento variable por plataforma.
Integración con Blazor Server y Blazor WebAssembly
Blazor Hybrid puede convivir con otros modelos de Blazor:
| Tipo | Ejecución | Casos de uso |
|---|---|---|
| Hybrid | Código C# dentro de MAUI (nativo) | Apps multiplataforma |
| Server | Renderizado en servidor via SignalR | Web apps empresariales |
| WebAssembly | Cliente puro en navegador | SPA sin backend nativo |
Todos comparten el mismo modelo de componentes Razor, lo que permite migrar o reutilizar UI entre entornos.
Despliegue
Las apps Blazor Hybrid se publican como apps MAUI normales, empaquetadas en formato nativo:
- Android: `.aab` / `.apk`
- iOS: `.ipa`
- Windows: `.msix`
- macOS: `.pkg`
No dependen de un servidor web, ya que BlazorWebView ejecuta los componentes localmente.
Recursos adicionales
- Documentación oficial – Blazor Hybrid
- dotnet/maui-samples (Blazor Hybrid demos)
- BlazorWebView Overview – Microsoft Docs
- Ejemplo: Blazor + MAUI Todo App (GitHub)
Próximos temas sugeridos
- Blazor Hybrid + MAUI + Electron.NET (para escritorio extendido)
- pwa y empaquetado híbrido
- SignalR en tiempo real con Blazor Hybrid
- Patrón MVU (Model-View-Update) aplicado a MAUI-Blazor
- Testing de componentes híbridos con bUnit
.NET MAUI + Blazor Hybrid – Integración avanzada con servicios nativos
net · csharp · blazor · maui · frontend · Backend · xamarin · mobile
Introducción
En un entorno Blazor Hybrid + .NET MAUI, los componentes Blazor se ejecutan dentro de un contenedor nativo (BlazorWebView).
Esto permite acceder directamente a APIs y hardware del dispositivo sin usar JavaScript ni dependencias externas.
Esta integración se realiza mediante:
- Servicios nativos registrados en el MauiProgram.cs.
- Inyección de dependencias compartida entre MAUI y Blazor.
- Microsoft.Maui.Essentials, que unifica acceso a cámara, sensores, notificaciones, almacenamiento, etc.
Arquitectura de integración nativa
[ .NET MAUI Host ]
└── BlazorWebView
├── Razor Components
├── Servicios C# inyectados (nativos)
└── API Essentials (GPS, cámara, batería, almacenamiento)
`
Cada servicio puede exponerse como clase C# registrada en DI y consumida desde Blazor vía @inject.
📱 Notificaciones locales
Las notificaciones locales permiten enviar alertas o recordatorios desde la app sin conexión a internet.
Servicio: NotificationService.cs
using Plugin.LocalNotification;
public class NotificationService
{
public void Show(string title, string message)
{
var request = new NotificationRequest
{
NotificationId = 1,
Title = title,
Description = message,
Schedule = new NotificationRequestSchedule
{
NotifyTime = DateTime.Now.AddSeconds(2)
}
};
LocalNotificationCenter.Current.Show(request);
}
}
`
Registro en MauiProgram.cs
builder.Services.AddSingleton<NotificationService>();
Uso desde Blazor
@inject NotificationService NotificationService
<button @onclick="Notify">Enviar notificación</button>
@code {
private void Notify()
{
NotificationService.Show("Recordatorio", "Has pulsado el botón de prueba");
}
}
📸 Cámara y galería
Puedes capturar fotos o seleccionar imágenes con la API nativa de MAUI (MediaPicker).
Servicio: CameraService.cs
public class CameraService
{
public async Task<FileResult?> TakePhotoAsync()
{
if (MediaPicker.Default.IsCaptureSupported)
{
return await MediaPicker.Default.CapturePhotoAsync();
}
return null;
}
public async Task<FileResult?> PickPhotoAsync()
{
return await MediaPicker.Default.PickPhotoAsync();
}
}
Uso desde Blazor
@inject CameraService CameraService
<button @onclick="TakePhoto">📷 Tomar foto</button>
@if (photoPath != null)
{
<img src="@photoPath" width="200" />
}
@code {
private string? photoPath;
private async Task TakePhoto()
{
var result = await CameraService.TakePhotoAsync();
if (result != null)
photoPath = result.FullPath;
}
}
💡 Blazor Hybrid puede mostrar imágenes locales usando
file://odata:URIs.
📂 Almacenamiento local y archivos
Puedes guardar o leer archivos usando FileSystem y Preferences.
Servicio: StorageService.cs
public class StorageService
{
public string GetAppDataPath() => FileSystem.AppDataDirectory;
public async Task SaveTextAsync(string filename, string text)
{
var path = Path.Combine(FileSystem.AppDataDirectory, filename);
await File.WriteAllTextAsync(path, text);
}
public async Task<string?> ReadTextAsync(string filename)
{
var path = Path.Combine(FileSystem.AppDataDirectory, filename);
return File.Exists(path) ? await File.ReadAllTextAsync(path) : null;
}
}
Uso desde Blazor
@inject StorageService StorageService
<input @bind="text" placeholder="Escribe algo..." />
<button @onclick="Save">Guardar</button>
<button @onclick="Load">Cargar</button>
<p>@loadedText</p>
@code {
private string text = "";
private string loadedText = "";
private async Task Save()
{
await StorageService.SaveTextAsync("demo.txt", text);
}
private async Task Load()
{
loadedText = await StorageService.ReadTextAsync("demo.txt") ?? "Archivo vacío";
}
}
🧭 Sensores del dispositivo
MAUI expone múltiples sensores: GPS, acelerómetro, brújula, batería, conectividad, etc. Estos se pueden consultar o suscribir desde Blazor sin intermediarios JS.
Servicio: SensorService.cs
public class SensorService
{
public async Task<string> GetLocationAsync()
{
var location = await Geolocation.GetLastKnownLocationAsync();
return location == null ? "Sin ubicación" : $"{location.Latitude}, {location.Longitude}";
}
public double GetBatteryLevel() => Battery.ChargeLevel * 100;
}
Uso desde Blazor
@inject SensorService SensorService
<h3>📍 Información del dispositivo</h3>
<p>Ubicación: @location</p>
<p>Batería: @battery%</p>
<button @onclick="Refresh">Actualizar</button>
@code {
private string location = "";
private double battery;
private async Task Refresh()
{
location = await SensorService.GetLocationAsync();
battery = SensorService.GetBatteryLevel();
}
}
🛠️ Manejo de permisos
Al acceder a cámara, almacenamiento o GPS, MAUI gestiona los permisos según la plataforma. Antes de usar una API, se recomienda solicitar permisos explícitamente:
var status = await Permissions.RequestAsync<Permissions.Camera>();
if (status != PermissionStatus.Granted)
{
// Mostrar aviso al usuario
}
En Android, declara permisos en AndroidManifest.xml.
En iOS, agrega descripciones en Info.plist (p. ej. NSCameraUsageDescription).
🧩 Integración combinada – ejemplo práctico
Escenario
App híbrida de reportes de campo que:
- Usa la cámara para capturar una imagen.
- Guarda metadatos en almacenamiento local.
- Envía notificación local confirmando guardado.
- Adjunta coordenadas GPS.
Flujo
- El usuario abre el componente Blazor.
- Pulsa “Tomar foto”.
- La imagen y datos se guardan con
StorageService. SensorServiceañade ubicación.NotificationServiceenvía confirmación.
@page "/report"
@inject CameraService Camera
@inject StorageService Storage
@inject SensorService Sensor
@inject NotificationService Notify
<button @onclick="CreateReport">📸 Crear reporte</button>
<p>@status</p>
@code {
private string status = "Esperando acción...";
private async Task CreateReport()
{
var photo = await Camera.TakePhotoAsync();
if (photo == null) return;
var loc = await Sensor.GetLocationAsync();
var metadata = $"Foto tomada en {DateTime.Now} - {loc}";
await Storage.SaveTextAsync("report.txt", metadata);
Notify.Show("Reporte creado", metadata);
status = "Reporte guardado correctamente ✅";
}
}
🔐 Buenas prácticas de integración
- Centralizar el acceso a APIs nativas en servicios.
- Evitar llamadas directas desde componentes Razor.
- Controlar errores por plataforma (try/catch con fallback).
- Implementar permisos condicionales.
- Usar
IConnectivitypara validar conexión antes de llamadas REST. - Aprovechar
PreferencesoSecureStoragepara datos sensibles.
🚀 Pruebas y despliegue
- Usa Emuladores y simuladores (Android/iOS) para validar hardware.
- Las APIs de
Essentialsse adaptan automáticamente según plataforma. - En CI/CD, deshabilita funciones que requieran sensores físicos o usa mocks.
- Firma y distribuye como cualquier app MAUI (
.aab,.msix,.pkg).
📚 Recursos
- Microsoft.Maui.Essentials overview
- Plugin.LocalNotification (GitHub)
- Camera & MediaPicker en MAUI
- Geolocation y sensores
- FileSystem y almacenamiento
Próximos temas sugeridos
- Blazor Hybrid + MAUI + SignalR (sincronización en tiempo real)
- Arquitectura Clean Architecture híbrida (backend + MAUI + Blazor)
- Testing avanzado de servicios nativos (mocks y simulaciones)
- PWA + MAUI: empaquetado híbrido para escritorio y móvil
.NET MAUI + Blazor Hybrid – Extensiones avanzadas y escenarios empresariales
net · maui · blazor · hybrid · xamarin · mobile · cloud · uiux · arquitectura
🌐 Integración con servicios web y APIs REST
Blazor Hybrid permite consumir servicios REST directamente desde el cliente, pero aprovechando HttpClient configurado a nivel MAUI para autenticación, logs o compresión.
Configuración centralizada
builder.Services.AddHttpClient("ApiClient", client =>
{
client.BaseAddress = new Uri("https://api.miempresa.com/");
client.DefaultRequestHeaders.Add("Accept", "application/json");
});
`
Uso desde Blazor
@inject IHttpClientFactory HttpFactory
@code {
private async Task<List<Product>> LoadProductsAsync()
{
var client = HttpFactory.CreateClient("ApiClient");
return await client.GetFromJsonAsync<List<Product>>("products");
}
}
💡 Se recomienda un servicio intermedio que encapsule las llamadas API, agregue caching o maneje reintentos automáticos con
Polly.
🔁 Comunicación bidireccional Blazor ↔ Nativo
La comunicación entre Blazor y código nativo (C# MAUI) es fundamental cuando se requiere interacción directa entre UI web y lógica de dispositivo.
Desde Blazor a MAUI
Se realiza inyectando servicios nativos (@inject) o usando un bridge en el contenedor BlazorWebView.
blazorWebView.HostPage = "wwwroot/index.html";
blazorWebView.RootComponents.Add(new RootComponent
{
Selector = "#app",
ComponentType = typeof(MainPage)
});
blazorWebView.RegisterCustomJavaScriptBridge("AppInterop", new AppInterop());
Desde MAUI a Blazor
Puedes invocar métodos de componentes Blazor desde C# usando Dispatcher o IJSRuntime.
await blazorWebView.Dispatcher.DispatchAsync(async () =>
{
await blazorWebView.WebView.CoreWebView2.ExecuteScriptAsync("window.refreshUI()");
});
Esto permite, por ejemplo:
- Actualizar vistas Blazor al recibir datos nativos (sensores, Bluetooth).
- Sincronizar estado de la app entre capas.
- Integrar UI web con eventos nativos (por ejemplo, cierre de sesión automático).
⚡ Sincronización en tiempo real con SignalR
Blazor Hybrid puede usar SignalR como cualquier aplicación web para actualizaciones instantáneas. El cliente puede ejecutarse dentro del proceso MAUI, compartiendo conexión y almacenamiento local.
Ejemplo básico
builder.Services.AddSingleton<HubConnection>(sp =>
new HubConnectionBuilder()
.WithUrl("https://api.miempresa.com/hub/notificaciones")
.WithAutomaticReconnect()
.Build());
@inject HubConnection Hub
@code {
protected override async Task OnInitializedAsync()
{
Hub.On<string>("Mensaje", msg => mensajes.Add(msg));
await Hub.StartAsync();
}
}
🚀 Ideal para sincronizar estados en apps de inventario, chat, pedidos o telemetría en tiempo real.
🔐 Autenticación y autorización híbrida
En escenarios empresariales se requiere integrar autenticación nativa (AppCenter, MSAL, biometría) con Blazor y API backend.
Tipos comunes de autenticación
-
OAuth2 / OpenID Connect (MSAL / Azure AD) Integración directa con
Microsoft.Identity.Clientpara obtener tokens. -
Biometría nativa (FaceID / Fingerprint) Uso de
Platform.CurrentActivityo librerías comoPlugin.Fingerprint. -
JWT Token Sharing El token JWT se guarda con
SecureStoragey se pasa a Blazor a través deHttpClient.
var token = await SecureStorage.GetAsync("auth_token");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
⚙️ Para entornos empresariales, la sincronización entre capas debe hacerse mediante un servicio de sesión compartido.
🧩 Integración con hardware externo (Bluetooth, NFC, GPS extendido)
El modelo híbrido permite integrar librerías MAUI para hardware extendido sin depender de JS.
Bluetooth
Usa Plugin.BLE o Shiny.BluetoothLE para escanear y conectar dispositivos.
var adapter = CrossBluetoothLE.Current.Adapter;
adapter.DeviceDiscovered += (s, a) =>
{
Console.WriteLine($"Dispositivo: {a.Device.Name}");
};
await adapter.StartScanningForDevicesAsync();
NFC
Shiny.Nfc permite leer/escribir etiquetas NFC desde MAUI, pasando datos a Blazor mediante servicios inyectados.
GPS avanzado
Para tracking continuo o rutas, combina Geolocation con Geocoding y BackgroundService (MAUI Worker) para enviar posiciones incluso con la app en segundo plano.
📤 Sincronización offline y almacenamiento híbrido
Blazor Hybrid puede trabajar offline, sincronizando datos locales con el servidor al reconectarse.
Opciones de almacenamiento
SQLitelocal (nativo en MAUI).LiteDBoRealmpara modelos offline con sincronización.Preferencespara configuraciones rápidas.
Ejemplo con SQLite
builder.Services.AddSingleton<LocalDatabase>();
public class LocalDatabase
{
private readonly SQLiteAsyncConnection _db;
public LocalDatabase()
{
var path = Path.Combine(FileSystem.AppDataDirectory, "app.db");
_db = new SQLiteAsyncConnection(path);
_db.CreateTableAsync<Report>();
}
public Task<int> SaveAsync(Report report) => _db.InsertAsync(report);
}
💾 La capa de datos puede compartirse entre MAUI (nativo) y Blazor (interfaz).
🧠 Patrones de arquitectura híbrida recomendados
Para mantener escalabilidad y limpieza del código:
- MVU (Model–View–Update) o MVVM con
CommunityToolkit.Mvvm. - Clean Architecture: separación entre UI, lógica y persistencia.
- Service Locator Pattern para inyectar servicios nativos en Blazor.
- Reactive UI / EventBus para comunicación entre componentes.
Ejemplo con MVVM + Blazor
public partial class ReportViewModel : ObservableObject
{
[ObservableProperty]
private string reportStatus = "Iniciando...";
private readonly NotificationService _notification;
public ReportViewModel(NotificationService notification)
{
_notification = notification;
}
public void SaveReport()
{
_notification.Show("Reporte", "Guardado con éxito");
ReportStatus = "Completado ✅";
}
}
Blazor consume el ViewModel directamente vía @inject o mediante un CascadingParameter.
🧱 Personalización UI/UX híbrida
Combina controles nativos MAUI con componentes Razor para ofrecer una experiencia fluida:
- Páginas nativas (`ContentPage`, `Shell`) con fragmentos Blazor (`BlazorWebView`).
- Controles MAUI para navegación, menús, tabs y modales.
- CSS y temas compartidos (`wwwroot/css`) con estilos adaptativos.
- Animaciones con `CommunityToolkit.Maui.Animations`.
Ejemplo de Shell + BlazorWebView
<ShellContent Title="Inicio">
<BlazorWebView HostPage="wwwroot/index.html">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
</ShellContent>
🎨 Los temas pueden adaptarse con variables CSS ligadas a
AppThemeBindingpara modo oscuro y claro.
☁️ Despliegue y CI/CD
- Publica como APK / AAB, MSIX, o PKG según la plataforma.
- Usa .NET MAUI Workload en GitHub Actions o Azure Pipelines.
- Automatiza versiones y firmas con
dotnet workload install maui+msbuild. - Empaqueta recursos Blazor (
wwwroot) junto con el proyecto MAUI.
💡 En entornos enterprise, se recomienda usar App Center o Intune para distribución controlada.
📊 Monitorización y telemetría
Integración directa con:
- App Center Analytics
- Azure Application Insights
- Sentry o Raygun para capturar errores y métricas.
AppCenter.Start("android=APP_KEY;ios=APP_KEY;", typeof(Analytics), typeof(Crashes));
Los eventos y métricas pueden combinarse con logs de Blazor (
ILogger) para obtener trazabilidad completa.
🔮 Próximos módulos sugeridos
- Blazor Hybrid + MAUI + SignalR + Offline Sync
- Clean Architecture aplicada a proyectos híbridos
- Testing de UI y servicios nativos con
xUnit+bUnit+MauiTest - Integración con AI Services (Cognitive Services, OpenAI, Azure AI)
- Blazor MAUI Desktop: crear apps de escritorio multiplataforma con lógica compartida
- Micro Frontends híbridos con Blazor WebAssembly + MAUI Host
¿Te gusta este contenido? Suscríbete vía RSS