Recent Discussions
- 83KViews1like7Comments
Convert the standard Blazor navigation menu to a collapsible icon menu
While I admittedly love Blazor I’ve always changed the out-of-the-box navigation menu that comes with it. It’s the first manoeuvre I pull when spinning up a new Blazor app, stripping out the purple gradient and getting it in, what I consider, a “blank slate state”. The other change I’ve wanted to make to the out-the-box look is one of those deluxe collapsible menus that leave just the icons showing. Anyone that’s used Azure DevOps will know what I’m talking about. I’ve included a picture to show DevOps example of what I’d like to see in my Blazor app. It gives a load of extra screen real estate which is always a priority for me in business applications particularly with complex or intensive workflows. Plus it gives the user the option to remove the text prompts once they are familiar with the system which is supported with carefully selected icon choices. As with most tasks that I assume will be an obvious solution I hit my search engine of choice and looked to avoid reinventing the wheel. However I found no source of pre-written changes to achieve this and was directed to fairly expensive third party controls to solve this one for me, which, being tight fisted, pushed me to do it for myself. Here I hope you save you the trouble of paying a pretty penny or having to wrestle the CSS into submission and provide a guide for producing a nice collapsible icon navigation menu by altering the existing out of the box menu in Blazor. In the following example I have left all the standard styling as is with the menu and just done the changes required to make the collapsible menu. The three files that require changes are MainLayout.razor, NavMenu.razor and NavMenu.razor.css. The code changes are shown below: Firstly the NavMenu.razor requires a bool value (IconMenuActive) to indicate whether the icon menu is showing or not, then wrap the text of the each NavItem in an if statement dependent on this bool. Then a method for toggling this bool and EventCalBack to send a bool to the MainLayout.razor for shrinking the width of the sidebar. Lastly there needs to be the control for switching menu views (I used the standard io icon arrows). NavMenu.razor <div class="top-row ps-3 navbar navbar-dark"> <div class="container-fluid"> <span class="oi oi-monitor" style="color:white;" aria-hidden="true"></span> @if (!@IconMenuActive) { <a class="navbar-brand" href="">The Menu Title Here</a> } <button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu"> <span class="navbar-toggler-icon"></span> </button> </div> </div> <div class="@NavMenuCssClass" @onclick="ToggleNavMenu"> <nav class="flex-column"> <div class="nav-item px-3"> <NavLink class="nav-link" href="" Match="NavLinkMatch.All"> <span class="oi oi-home" aria-hidden="true"></span> @if (!@IconMenuActive) { <label>Home</label> } </NavLink> </div> <div class="nav-item px-3"> <NavLink class="nav-link" href="counter"> <span class="oi oi-plus" aria-hidden="true"></span> @if (!@IconMenuActive) { <label>Counter</label> } </NavLink> </div> <div class="nav-item px-3"> <NavLink class="nav-link" href="fetchdata"> <span class="oi oi-list-rich" aria-hidden="true"></span> @if (!@IconMenuActive) { <label>Fetch data</label> } </NavLink> </div> </nav> </div> <div class="bottom-row"> <div class="icon-menu-arrow"> @if (!@IconMenuActive) { <span class="oi oi-arrow-left" style="color: white;" @onclick="ToggleIconMenu"></span> } else { <span class="oi oi-arrow-right" style="color: white;" @onclick="ToggleIconMenu"></span> } </div> </div> @code { //bool to send to MainLayout for shrinking sidebar and showing/hide menu text private bool IconMenuActive { get; set; } = false; //EventCallback for sending bool to MainLayout [Parameter] public EventCallback<bool> ShowIconMenu { get; set; } private bool collapseNavMenu = true; private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; private void ToggleNavMenu() { collapseNavMenu = !collapseNavMenu; } //Method to toggle IconMenuActive bool and send bool via EventCallback private async Task ToggleIconMenu() { IconMenuActive = !IconMenuActive; await ShowIconMenu.InvokeAsync(IconMenuActive); } } Next I add in a bit of CSS in to NavMenu.razor.css to put the arrow for toggling the menu at the bottom of the sidebar and a media query to make sure it doesn't show up in mobile view. The CSS classes added are .bottom-row and .icon-menu-arrow. NavMenu.razor.css .navbar-toggler { background-color: rgba(255, 255, 255, 0.1); } .top-row { height: 3.5rem; background-color: rgba(0,0,0,0.4); } .bottom-row { position: absolute; bottom: 0; padding-bottom: 10px; text-align: right; width: 100%; padding-right: 28px; } .icon-menu-arrow { text-align: right; } .navbar-brand { font-size: 1.1rem; } .oi { width: 2rem; font-size: 1.1rem; vertical-align: text-top; top: -2px; } .nav-item { font-size: 0.9rem; padding-bottom: 0.5rem; } .nav-item:first-of-type { padding-top: 1rem; } .nav-item:last-of-type { padding-bottom: 1rem; } .nav-item ::deep a { color: #d7d7d7; border-radius: 4px; height: 3rem; display: flex; align-items: center; line-height: 3rem; } .nav-item ::deep a.active { background-color: rgba(255,255,255,0.25); color: white; } .nav-item ::deep a:hover { background-color: rgba(255,255,255,0.1); color: white; } @media (min-width: 641px) { .navbar-toggler { display: none; } .collapse { /* Never collapse the sidebar for wide screens */ display: block; } } @media (max-width: 640px) { .bottom-row { display: block; } } Finally I add in the handler for the EventCallback to MainLayout.razor and a method to alter the width of the sidebar. MainLayout.razor @inherits LayoutComponentBase <div class="page"> <div class="sidebar" style="@IconMenuCssClass"> <NavMenu ShowIconMenu="ToggleIconMenu"/> </div> <main> <div class="top-row px-4"> <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a> </div> <article class="content px-4"> @Body </article> </main> </div> @code{ private bool _iconMenuActive { get; set; } private string? IconMenuCssClass => _iconMenuActive ? "width: 80px;" : null; protected void ToggleIconMenu(bool iconMenuActive) { _iconMenuActive = iconMenuActive; } } The final product of these little changes are shown in the pictures below: I'd love to hear if anyone has tackled this in a different way to me and if they've got any ideas on making it cleaner. Have yourselves a wonderful day, Gav72KViews10likes16CommentsCould not load file or assembly System.Data.SqlClient
Hello, I'm currently learning the ASP.NET Core-Web-API (.NET 6) system. I added a class-library (.NET Framework) (v4.8) as a DataAccessLayer to my project. There is a DAO class with a sql-query that uses Dapper and System.Data.SqlClient. just for example: var parameters = new { id }; using (SqlConnection connection = new SqlConnection("...")) { connection.Open(); return connection.ExecuteScalar<bool>(query, parameters); } ASP.NET Core-Web-API - Controller Lib - DAO-Class Now my Problem: When I try to invoke the method which contains this query: [HttpGet("foo")] public ActionResult<bool> Foo(DTO request) { var isOk = Lib.Dao.FetchSomething(request); return Ok(isOk); } , I'll get the following error on line 3: System.IO.FileNotFoundException: "Could not load file or assembly 'System.Data.SqlClient, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified." My lib has the reference to System.Data (4.0.0.0) and System.Data.SqlClient (4.6.1.3). Why do .net tries to search the version 0.0.0.0? Why does this doesn't work? This should work (worked for me on .NET WebForms) Regards.68KViews0likes5CommentsDotnet tool install 401 Unauthorized
I'm trying to install the "dotnet-reportgenerator-globaltool" tool via .Net Core custom task. Custom Command: tool Arguments: install --global dotnet-reportgenerator-globaltool --version 4.0,15 Problem: When executing from a directory that contains a nuget.config pointing to a private azure artifacts, I get an error like the following. I don't want to use my feed or need to, but because the nuget.config exists I have no choice. Is there a way I can pass credentials to this command? There is no directory that doesn't inherit the nuget.config [command]"C:\Program Files\dotnet\dotnet.exe" tool install --global dotnet-reportgenerator-globaltool --version 4.0.15 C:\Program Files\dotnet\sdk\2.2.104\NuGet.targets(114,5): error : Unable to load the service index for source https://pkgs.dev.azure.com/bstglobal/_packaging/BSTWEB/nuget/v3/index.json. [C:\Users\VssAdministrator\AppData\Local\Temp\rkrgqk3i.dkp\restore.csproj] C:\Program Files\dotnet\sdk\2.2.104\NuGet.targets(114,5): error : Response status code does not indicate success: 401 (Unauthorized). [C:\Users\VssAdministrator\AppData\Local\Temp\rkrgqk3i.dkp\restore.csproj] The tool package could not be restored.37KViews0likes9Comments.NET 8.0.2 Update Causes ASP.NET Core MVC 'Index View Not Found' Error
Hello everyone, I recently updated to .NET 8.0.2 and encountered an issue with my ASP.NET Core MVC application. After the update, the application began throwing an error related to the 'Index' view not being found. This issue was not present prior to the update. An unhandled exception has occurred while executing the request. System.InvalidOperationException: The view 'Index' was not found. The following locations were searched: /Views/Home/Index.cshtml /Views/Shared/Index.cshtml This error is generated by the Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware and specifically indicates that the MVC framework is unable to locate the 'Index.cshtml' file in both the 'Home' and 'Shared' directories, where it traditionally searches for views. I've verified the existence of the 'Index.cshtml' file in the correct location and ensured that the routing configurations are set up correctly. This setup was working seamlessly before the update to .NET 8.0.2. Update: I was able to resolve this issue by uninstalling the .NET 8.0.2 updates. After reverting to the previous version, the application started working as expected without any errors. It appears that the .NET 8.0.2 update may have introduced a change or incompatibility affecting the way ASP.NET Core MVC applications locate views.32KViews2likes6CommentsVersioning my Maui Android App
Previously the way to define version code for Android in Maui .csproj file was like this: <!-- Versions --> <ApplicationVersion>3.1.2</ApplicationVersion> <AndroidVersionCode>3</AndroidVersionCode> With the new release of Visual Studio Preview, this has changed to: <ApplicationVersion>3</ApplicationVersion> It works, from Visual Studio, I can bundle a new .aab package (see image below). We see the version code is defined to 3. Unfortunately the version is defined to 1.0.0 and I don't know how to change this. ...when imported on the Google Play Console, it look like this: Unfortunately, when imported I only see the versionCode 3 (which is defined in the .csproj file as ApplicationVersion). What about the versionName (in parentheses) ? Nothing is planned in the .csproj file ? When imported on the Google Play Console, I don't want to have 3 (1.0.0) but I want 3 (3.1.2)... https://developer.android.com/studio/publish/versioning versionCode — A positive integer used as an internal version number. versionName — A string used as the version number shown to users.26KViews0likes8CommentsOpen Source ASP.NET 8 MVC 5 Admin Template - Sneat
Hi All, Sharing here Sneat Free Asp.NET Core MVC Admin Template. If you’re a developer looking for the latest Free ASP.NET Core 8, MVC 5 Admin Panel Template that is developer-friendly, rich with features, and highly customizable look no further than Sneat. Incredibly versatile, this Free ASP.NET Dashboard also allows you to build any type of web application. For instance, you can create: SaaS platforms Project management apps E-commerce backends CRM systems Analytics apps Banking apps Education apps Fitness apps & many more. Features: Based on ASP.NET Core 8, MVC 5 UI Framework Bootstrap 5 Vertical layout 1 Unique Dashboard 1 Chart library SASS Powered Authentication Pages Fully Responsive Layout Organized Folder Structure Clean & Commented Code Well Documented You can check the GitHub repo as well: https://github.com/themeselection/sneat-bootstrap-html-aspnet-core-mvc-admin-template-free Hope you all like it.19KViews1like0Comments- 18KViews1like27Comments
How to add a timer to C# Service
Hi everyone I am new to coding in c # and trying to write a windows service in c #, my service seems to be working fine except for one thing: I try to make it run in a loop, say every 30 seconds, another program. But for the moment when I launch my service, it executes the program only once. My code: using System; using System.Runtime.InteropServices; using System.Diagnostics; // SET STATUS using System.ComponentModel;// SET STATUS using System.ServiceProcess; using System.Timers; //using System.ServiceProccess;// SET STATUS public enum ServiceType : int { // SET STATUS [ SERVICE_WIN32_OWN_PROCESS = 0x00000010, SERVICE_WIN32_SHARE_PROCESS = 0x00000020, }; // SET STATUS ] public enum ServiceState : int { // SET STATUS [ SERVICE_STOPPED = 0x00000001, SERVICE_START_PENDING = 0x00000002, SERVICE_STOP_PENDING = 0x00000003, SERVICE_RUNNING = 0x00000004, SERVICE_CONTINUE_PENDING = 0x00000005, SERVICE_PAUSE_PENDING = 0x00000006, SERVICE_PAUSED = 0x00000007, }; // SET STATUS ] [StructLayout(LayoutKind.Sequential)] // SET STATUS [ public struct ServiceStatus { public ServiceType dwServiceType; public ServiceState dwCurrentState; public int dwControlsAccepted; public int dwWin32ExitCode; public int dwServiceSpecificExitCode; public int dwCheckPoint; public int dwWaitHint; }; // SET STATUS ] public enum Win32Error : int { // WIN32 errors that we may need to use NO_ERROR = 0, ERROR_APP_INIT_FAILURE = 575, ERROR_FATAL_APP_EXIT = 713, ERROR_SERVICE_NOT_ACTIVE = 1062, ERROR_EXCEPTION_IN_SERVICE = 1064, ERROR_SERVICE_SPECIFIC_ERROR = 1066, ERROR_PROCESS_ABORTED = 1067, }; public class Service_PSTest : ServiceBase { // PSTest may begin with a digit; The class name must begin with a letter private System.Diagnostics.EventLog eventLog; // EVENT LOG private ServiceStatus serviceStatus; // SET STATUS public Service_PSTest() { ServiceName = "Test2"; CanStop = true; CanPauseAndContinue = false; AutoLog = true; eventLog = new System.Diagnostics.EventLog(); // EVENT LOG [ if (!System.Diagnostics.EventLog.SourceExists(ServiceName)) { System.Diagnostics.EventLog.CreateEventSource(ServiceName, "Application"); } eventLog.Source = ServiceName; eventLog.Log = "Application"; // EVENT LOG ] EventLog.WriteEntry(ServiceName, "Test2.exe Test2()"); // EVENT LOG } [DllImport("advapi32.dll", SetLastError = true)] // SET STATUS private static extern bool SetServiceStatus(IntPtr handle, ref ServiceStatus serviceStatus); protected override void OnStart(string[] args) { EventLog.WriteEntry(ServiceName, "Test2.exe OnStart() // Entry. Starting script 'c:\\temp\\Test.exe\\Test1.ps1' -SCMStart"); // EVENT LOG // Set the service state to Start Pending. // SET STATUS [ // Only useful if the startup time is long. Not really necessary here for a 2s startup time. serviceStatus.dwServiceType = ServiceType.SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING; serviceStatus.dwWin32ExitCode = 0; serviceStatus.dwWaitHint = 2000; // It takes about 2 seconds to start PowerShell SetServiceStatus(ServiceHandle, ref serviceStatus); // SET STATUS ] // Start a child process with another copy of this script try { Process p = new Process(); // Redirect the output stream of the child process. p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.FileName = "PowerShell.exe"; p.StartInfo.Arguments = "-ExecutionPolicy Bypass -c & 'c:\\temp\\Test.exe\\Test1.ps1' -SCMStart"; // Works if path has spaces, but not if it contains ' quotes. p.Start(); // Read the output stream first and then wait. (To avoid deadlocks says Microsoft!) string output = p.StandardOutput.ReadToEnd(); // Wait for the completion of the script startup code, that launches the -Service instance p.WaitForExit(); if (p.ExitCode != 0) throw new Win32Exception((int)(Win32Error.ERROR_APP_INIT_FAILURE)); // Success. Set the service state to Running. // SET STATUS serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING; // SET STATUS } catch (Exception e) { EventLog.WriteEntry(ServiceName, "Test2.exe OnStart() // Failed to start 'c:\\temp\\Test.exe\\Test1.ps1' " + e.Message, EventLogEntryType.Error); // EVENT LOG // Change the service state back to Stopped. // SET STATUS [ serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED; Win32Exception w32ex = e as Win32Exception; // Try getting the WIN32 error code if (w32ex == null) { // Not a Win32 exception, but maybe the inner one is... w32ex = e.InnerException as Win32Exception; } if (w32ex != null) { // Report the actual WIN32 error serviceStatus.dwWin32ExitCode = w32ex.NativeErrorCode; } else { // Make up a reasonable reason serviceStatus.dwWin32ExitCode = (int)(Win32Error.ERROR_APP_INIT_FAILURE); } // SET STATUS ] } finally { serviceStatus.dwWaitHint = 0; // SET STATUS SetServiceStatus(ServiceHandle, ref serviceStatus); // SET STATUS EventLog.WriteEntry(ServiceName, "Test2.exe OnStart() // Exit"); // EVENT LOG } } protected override void OnStop() { EventLog.WriteEntry(ServiceName, "Test2.exe OnStop() // Entry"); // EVENT LOG // Start a child process with another copy of ourselves try { Process p = new Process(); // Redirect the output stream of the child process. p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.FileName = "PowerShell.exe"; p.StartInfo.Arguments = "-ExecutionPolicy Bypass -c & 'c:\\temp\\Test.exe\\Test1.ps1' -SCMStop"; // Works if path has spaces, but not if it contains ' quotes. p.Start(); // Read the output stream first and then wait. (To avoid deadlocks says Microsoft!) string output = p.StandardOutput.ReadToEnd(); // Wait for the PowerShell script to be fully stopped. p.WaitForExit(); if (p.ExitCode != 0) throw new Win32Exception((int)(Win32Error.ERROR_APP_INIT_FAILURE)); // Success. Set the service state to Stopped. // SET STATUS serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED; // SET STATUS } catch (Exception e) { EventLog.WriteEntry(ServiceName, "Test2.exe OnStop() // Failed to stop 'c:\\temp\\Test.exe\\Test1.ps1'. " + e.Message, EventLogEntryType.Error); // EVENT LOG // Change the service state back to Started. // SET STATUS [ serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING; Win32Exception w32ex = e as Win32Exception; // Try getting the WIN32 error code if (w32ex == null) { // Not a Win32 exception, but maybe the inner one is... w32ex = e.InnerException as Win32Exception; } if (w32ex != null) { // Report the actual WIN32 error serviceStatus.dwWin32ExitCode = w32ex.NativeErrorCode; } else { // Make up a reasonable reason serviceStatus.dwWin32ExitCode = (int)(Win32Error.ERROR_APP_INIT_FAILURE); } // SET STATUS ] } finally { serviceStatus.dwWaitHint = 0; // SET STATUS SetServiceStatus(ServiceHandle, ref serviceStatus); // SET STATUS EventLog.WriteEntry(ServiceName, "Test2.exe OnStop() // Exit"); // EVENT LOG } } public static void Main() { Timer timer = new Timer(); // name space(using System.Timers;) void OnElapsedTime(object source, ElapsedEventArgs e) { System.ServiceProcess.ServiceBase.Run(new Service_PSTest()); } timer.Elapsed += new ElapsedEventHandler(OnElapsedTime); timer.Interval = 5000; //number in milisecinds timer.Enabled = true; } } Help will be welcome16KViews0likes2CommentsExample code for Maui Shell
I am using the transition from Xamarin forms to Maui as an excuse to start using Shell as well. Since Shell has been in the Maui previews for a long time now, I thought it would be easy to get started. But the template does not have Shell as an option, and for some reason I haven't been able to find an example project despite extensive search. Can anyone point me to a simple example of a Maui Shell 'Hello World' app?Solved15KViews0likes8CommentsHow to print on Bluetooth printer in dotnet maui
Dear All Can any one tell mw how can I access Blutooth printer in dotnet maui. Can we use Bluetooth printer as COM/LPT port so that we can send text file to print on that port. Or we should use It as Binary writer to print any graphics or PDF file on it. Thanks13KViews1like4CommentsBlazor WASM PWA – Applications updates, cache busting with notification or force refresh
My team is currently working on a Blazor application and after several bouts of confusion between developers and testers we stuck a version number on the home screen and discovered the updates weren’t going out to everyone as we were expecting. We ended up with several people on different versions of the application and fortunately we spotted this issue early in development. I’ve put together the options and info I’ve found while trying to find a solution to this that works for our particular situation in hopes that it will help someone else dealing with this and hopefully open a discussion on how people are handling this issue and find any alternative solutions. To look at what was happening behind the scenes, I set up a simple WASM PWA on .NET7 and have it hosted on an Azure App Service. I stuck a version number on the home page so I can easily see when the update has taken place. The behaviour: Blazor WASM PWA applications load the application into the browser based on the cache pulled in by the service workers (Javascript assets that act as a proxy between browsers and web servers for offline support and performance). In dev tools you can see what’s in the cache storage for the app (go to dev tools > application tab > cache storage). The picture below shows that the cache contains “blazor-resources” and “offline-cache”. The “offline-cache” is the important one that determines what the site is displaying and on pushing an update the “blazor-resources” is unaffected so for this purpose can be ignored. Now the standard behaviour on pushing an update to the app is that the service worker will install the new app cache in the background and enter the “waiting” state and will not activate the newly cached app until the current application service worker is released, by either closing the browser or hard refreshing the app (Ctrl + F5). This behaviour is by design to prevent having two tabs open with different versions of the application running at once. However users may never close the application or browser or whatever and that would mean they could be running long retired versions of your application for an indeterminant length of time. Below you can see the cache storage after an update has been pushed stacking up the old and new version of the offline-cache. Once the service worker has been released then the old cache is removed the latest will be activated. This will then display the new version of the app. The solution: Now, what if we want to change this behaviour to either prompt and update or force one? Either way we will want to remove the need to close browsers or hard refresh as that can be a bit of a tricky one to get end users to get on board with. The service workers actually have a method that can skip the “waiting” stage of the service worker lifecycle clear the old cache and activate the latest. This is the SkipWaiting method. In the Blazor solution there is the service-worker.published.js file found in the wwwroot folder. This file contains the methods for the service worker. In this file there is a OnInstall method and can be modified to the following adding in the SkipWaiting method: async function onInstall(event) { console.info('Service worker: Install'); self.skipWaiting(); // Fetch and cache all matching items from the assets manifest const assetsRequests = self.assetsManifest.assets .filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url))) .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url))) .map(asset => new Request(asset.url, { integrity: asset.hash, cache: 'no-cache' })); await caches.open(cacheName).then(cache => cache.addAll(assetsRequests)); } This additional line will now allow a standard refresh to update the application rather than requiring a hard refresh or closing the browser completely. When looking at the cache storage when an update is pushed you will see the second cache appear then the old cache disappear immediately. Note: Adding this behaviour will overwrite the intended behaviour and allow the potential of different version of the application running in different tabs. However we can look at avoiding that by forcing update later. Next, regardless of whether we want to prompt the user for an update or force it on them, we need a way of letting the site know it needs an update. My javascript is less than brilliant so I’ve used a solution by Wouter Huysentruit, full description here: https://whuysentruit.medium.com/blazor-wasm-pwa-adding-a-new-update-available-notification-d9f65c4ad13 This involves adding a js file called sw-registrator.js to the wwwroot folder that will allow an event to be triggered that can link to updating the site: window.updateAvailable = new Promise((resolve, reject) => { if (!('serviceWorker' in navigator)) { const errorMessage = `This browser doesn't support service workers`; console.error(errorMessage); reject(errorMessage); return; } navigator.serviceWorker.register('/service-worker.js') .then(registration => { console.info(`Service worker registration successful (scope: ${registration.scope})`); registration.onupdatefound = () => { const installingServiceWorker = registration.installing; installingServiceWorker.onstatechange = () => { if (installingServiceWorker.state === 'installed') { resolve(!!navigator.serviceWorker.controller); } } }; }) .catch(error => { console.error('Service worker registration failed with error:', error); reject(error); }); }); window.registerForUpdateAvailableNotification = (caller, methodName) => { window.updateAvailable.then(isUpdateAvailable => { if (isUpdateAvailable) { caller.invokeMethodAsync(methodName).then(); } }); }; Within index.html in the wwwroot folder we will need to register this new file instead of the service-worker.js. So we need to replace the reference to service-worker.js with the following: <script src="sw-registrator.js"></script> This will now raise an event once the cache refresh happens that can be used to trigger a prompt on the application or a refresh of the application. Now we need a razor component that will listen for the event and either throw up a refresh prompt or just force a refresh. Firstly I’ll do the prompt. For this make a new razor component and add the following code: @inject IJSRuntime _jsRuntime @inject NavigationManager uriHelper @if (_newVersionAvailable) { <button type="button" class="btn btn-danger shadow floating-update-button" onclick="window.location.reload()"> A new version of the application is available. Click here to upgrade. </button> } @code { private bool _newVersionAvailable = false; protected override async Task OnInitializedAsync() { await RegisterForUpdateAvailableNotification(); } private async Task RegisterForUpdateAvailableNotification() { await _jsRuntime.InvokeAsync<object>( identifier: "registerForUpdateAvailableNotification", DotNetObjectReference.Create(this), nameof(OnUpdateAvailable)); } [JSInvokable(nameof(OnUpdateAvailable))] public Task OnUpdateAvailable() { _newVersionAvailable = true; StateHasChanged(); return Task.CompletedTask; } } I personally like a red bar across the top as it’s very attention grabbing so you can add the following css file called WhateverYouCalledTheComponent.razor.css: .floating-update-button { position: relative; top: 0; padding: 1rem 1.5rem; width: 100%; } This component can then be placed at the top of MainLayout.razor above the body to ensure it appears anywhere on the app the user happens to be. This will then produce the following result once an update is pushed out: Once the banner is clicked, it will reload the site and the new update will be running. This is the setup that I will be implementing on my teams project as I wouldn’t want the site to force updates in case a user was in the middle of data entry. However if a forced refresh is desired, it’s a quick change to the razor component to allow that. Change the components code to the following: @inject IJSRuntime _jsRuntime @inject NavigationManager uriHelper @code { protected override async Task OnInitializedAsync() { await RegisterForUpdateAvailableNotification(); } private async Task RegisterForUpdateAvailableNotification() { await _jsRuntime.InvokeAsync<object>( identifier: "registerForUpdateAvailableNotification", DotNetObjectReference.Create(this), nameof(OnUpdateAvailable)); } [JSInvokable(nameof(OnUpdateAvailable))] public Task OnUpdateAvailable() { uriHelper.NavigateTo(uriHelper.Uri, forceLoad: true); StateHasChanged(); return Task.CompletedTask; } } Now on pushing an update you will see that the update is installed in the cache and once the event is triggered the old cache is removed and the site reloads wherever it happens to be. I’d be really interested to hear other peoples takes on this or if they’ve found other methods of achieving this, I’ve scoured the web and this was the combination of the best methods I came across but certainly open to improvement.12KViews0likes5CommentsHow to Resolve .NET Runtime Error 1026 after Windows 11 Update
I hope you're doing well. I am a teacher from Mexico and I'm facing a critical issue after a recent Windows 11 update to version 23H2. Ever since the update, I've been encountering a frustrating problem – a .NET Runtime Error 1026. This issue is causing applications to crash shortly after I launch them, making it impossible for me to access Mi Portal. Given that I heavily rely on Windows applications for my teaching tasks – from document editing to publications and printing, including crucial tasks like payslips handling – this situation has left me unable to perform my duties effectively. I understand that many educators are in a similar situation, where Windows OS and Office applications are our lifelines for seamless work. I urgently need a simple and effective solution to overcome this error and restore the functionality of my Windows 11 system. Your expertise and support in troubleshooting this .NET Runtime Error 1026 would be immensely appreciated. If anyone has encountered a similar issue or has successfully resolved it, I would be grateful for your insights. I need guidance or steps you can provide to help me swiftly resolve this issue and continue my teaching job without further disruptions. Warm regards and appreciation12KViews1like1CommentWhat's the future of RDLC ("client-side SSRS", aka "ReportViewer")?
This is the information I could gather so far: Getting an RDLC renderer for .NET 5+ is currently the fourth highest-voted feature on the SQL Server user wishlist. Unfortunately, there are currently no plans to do that (see the comments here). There are some enthusiast ports/recompilations floating around on github and nuget, but they are not official. The SQL Server Reporting Services Team Blog is dead, the last entry is from 2018. There's a third-party company providing an RDLC renderer, but Microsoft acquired them in 2018. Nothing has been heard since. There is currently no ReportViewer designer for Visual Studio 2022. Getting one is currently the fourth highest-voted feature on the Visual Studio 2022 wishlist. From a business perspective, I can totally understand that Microsoft is not giving this highly-loved feature the resources it needs. After all, they are basically giving away a great reporting engine for free, undermining their own SQL Server and Power BI sales. And they are not even hiding the fact that they'd rather have people purchase Power BI subscriptions, which is perfectly fine. They are a company, not a charity. Unfortunately, adding a dependency to a third-party cloud service is a no-go for many software development scenarios. Thus, I would like to start a discussion on the following points: It seems to me that MS no longer wants people to use their RLDC reporting engine in new projects. Is this observation correct? If you have a large repository of RDLC reports in your project, what are your migration plans? Are there drop-in replacements from third parties? Would Microsoft consider open-sourcing the RLDC engine, so that the community can "keep the product alive" for legacy scenarios and prevent this from being a blocker in .NET 5+ migrations? Best regards Heinzi12KViews8likes0CommentsHow do I convert the C# .dll file to .so file
Requirements: I wrote a standalone module (a separate dll file) in C#, mainly through COM real-time monitoring of a hardware, based on Win7 system. Originally to WPF program call, now Android system app also call this dll file. The application scenario is that a hardware device is connected to an Android tablet, on which an app will call my library files to monitor the hardware. There is no network. The plan is to throw the files directly to Android developers, who will directly call the interface in the files to communicate with the hardware. What is the best way for Android developers to use dll files, wrap them with other layers or rewrite them in another language 需求:我用C#语言写了一个独立模块(单独一个dll文件),主要是通过COM口实时监控一个硬件,基于Win7系统写的。原来是给WPF程序调用的,现在是安卓系统上app也要调用这个dll文件。应用场景是一个硬件设备上连着一个安卓平板,平板上有一个app要调用我的库文件监控硬件,没有网络,计划是将文件直接丢给安卓开发人员,安卓开发人员直接调用文件里的接口与硬件通讯。哪种方式能更好的使安卓开发人员使用dll文件,外面用其他需要封装一层还是用其他语言重新写11KViews0likes7CommentsUnique Device Identifier in MAUI
I am looking for a way to get a device identifier in NET MAUI that is cross platform compliant between Android/iOS/Windows. I originally had this code working in Xamarin Forms with the following: Android Context context = Application.Context; id = Settings.Secure.GetString(context.ContentResolver, Settings.Secure.AndroidId); iOS UIDevice.CurrentDevice.IdentifierForVendor.AsString().Replace("-", ""); Is there anything currently or planned in the future for use in NET MAUI. Thanks In Advance, Stuart Ferguson11KViews3likes1Comment