Astrol.JSInterop.Base: almacenamiento del navegador, portapapeles, archivos y datos del navegador desde C#.
Astrol.JSInterop.Base se instala con Astrol.Component.Basic y reúne las llamadas al navegador que casi toda aplicación necesita, para no escribir JavaScript. Su módulo JS se descarga la primera vez que se usa. AddAstrolBasic() ya registra AstrolJSInterop; el almacenamiento son métodos de extensión de IJSRuntime.
@* Program.cs: builder.Services.AddAstrolBasic(); (registers AstrolJSInterop) *@@using Astrol.JSInterop.Base@inject AstrolJSInterop jsI @* clipboard, files, browser, idle timer *@@inject IJSRuntime js @* storage: extension methods of IJSRuntime *@Guarde preferencias, filtros, el último paso de un asistente o un borrador con su tipo de C#: el valor se convierte a JSON al guardarlo y vuelve a su tipo al leerlo; si no existe se obtiene default. localStorage se conserva al cerrar el navegador y sessionStorage solo mientras dure la pestaña.
Por defecto (useEncrypt = true) el valor se guarda ofuscado: no se lee a simple vista en las herramientas del navegador, lo que añade una capa de discreción. No es un cifrado de seguridad: no guarde contraseñas, tokens ni datos sensibles en el navegador. Con useEncrypt: false se guarda el JSON legible (p. ej. para compartirlo con código JavaScript). Lea siempre con el mismo valor de useEncrypt con el que guardó.
Pruébelo: guarde con y sin useEncrypt y compare el valor guardado.
—public record Preferences(string Theme, int PageSize); // Save any serializable value (stored as JSON; obfuscated by default)await js.SetInLocalStorage("prefs", new Preferences("dark", 20)); // Read it back with its type (default if it does not exist)var prefs = await js.GetFromLocalStorage<Preferences>("prefs"); bool exists = await js.ExistsInLocalStorage("prefs");await js.RemoveFromLocalStorage("prefs");await js.ClearLocalStorage(); // Same API for sessionStorage (cleared when the tab is closed)await js.SetInSessionStorage("wizard-step", 3);int step = await js.GetFromSessionStorage<int>("wizard-step"); // Plain, readable JSON (e.g. to share it with JavaScript code)await js.SetInLocalStorage("theme", "dark", useEncrypt: false);CopyToClipboard copia un texto (devuelve false si el navegador no lo permite). SaveAs descarga un archivo generado en la aplicación a partir de sus bytes (un CSV, un PDF, un Excel...) y DownloadFile uno que ya está en una URL, con el nombre que indique.
bool copied = await jsI.CopyToClipboard("dotnet add package Astrol.Component.Basic"); // A file generated in the app (CSV, PDF, Excel... as byte[])await jsI.SaveAs("clients.csv", Encoding.UTF8.GetBytes(csv)); // A file that is already at a URLawait jsI.DownloadFile("files/report.pdf", "report-2026.pdf");Zona horaria e idioma del usuario (para fechas y textos), MatchesMedia para cualquier media query de CSS (móvil, modo oscuro, impresión...), abrir una pestaña nueva de forma segura y desplazarse a un elemento o al principio de la página (también dentro del cuerpo de AstrolLayoutMenu).
string timeZone = await jsI.GetTimeZone(); // "America/Tijuana"string language = await jsI.GetBrowserLanguage(); // "es-MX"bool isMobile = await jsI.MatchesMedia("(max-width: 768px)");bool prefersDark = await jsI.MatchesMedia("(prefers-color-scheme: dark)"); await jsI.OpenInNewTab("https://astrolui.com");await jsI.ScrollToElement("#results");await jsI.ScrollToTop();IdleTimer llama a su método [JSInvokable] Logout() cuando el usuario lleva un tiempo sin mover el ratón, escribir, hacer scroll ni tocar la pantalla. La última actividad se comparte entre pestañas: trabajar en una mantiene viva la sesión en las demás.
// MainLayout.razor.cs: log out after 30 minutes without activityprivate DotNetObjectReference<MainLayout>? self; protected override async Task OnAfterRenderAsync(bool firstRender){ if (firstRender) { self = DotNetObjectReference.Create(this); await jsI.IdleTimer(self, storageKey: "myapp", time: 30 * 60 * 1000); }} [JSInvokable]public async Task Logout(){ await AuthService.LogoutAsync(); Navigation.NavigateTo("/login");}Almacenamiento (extensiones de IJSRuntime, useEncrypt por defecto true)
AstrolJSInterop