Forcing reload of Blazor client after publishing changes - azure-web-app-service

I have a Blazor app that I'm deploying to Azure for some alpha testing. I've managed to do this and I can run the app from the website just fine.
The problem comes when I make changes to the client and server projects and republish them. Whatever browser is running the client will run whatever is already in the browser cache until the browser history is cleared. That means until the history is cleared the app appears broken because the client requests on the old version don't match the new server API - not to mention my client side changes don't get tested.
How can I force a reload of the client when I publish my changes? Do I have to tell the browser not to cache my app (not sure how on blazor) and take the performance hit until my app stabilizes? Or is there a way to force a client reload after the first API call using some middleware or something?
Or am I missing something?
Edit: It may be relevant that I used the PWA template provided in Blazor WebAssembly 3.2.0 Preview 2. I'm still running the app from a browser, but it seems possible that enabling the PWA option changed the behavior of the app even when running it as a regular website.

Since your app is a PWA, you can declare a js file for registration in the navigator.serviceWorker object. This my.js file can contain a const CACHE_VERSION = 1.0. Updating this value should force the client to download the latest files. See Jeremy Likness' blog post for more info.

if you are working on dot net core3.X PWA app, you can add comment in service-worker.published.js so that when browser will compare its cached service worker with updated one, browser will track the changes and load new one.

If anyone looks solution for Azure Pipelines and Azure Static Web App deployment, here is what worked for me:
Added following line on top of service-worker.published.js file.
const CACHE_VERSION = '{#CACHE_VERSION#}'
Added Bash step to *.yaml file, just change your app location accordingly.
- master
pool:
vmImage: ubuntu-latest
steps:
- checkout: self
submodules: true
- bash: 'sed -i ''s/{#CACHE_VERSION#}/$(Build.BuildId)/'' MathApp/wwwroot/service-worker.published.js'
- task: AzureStaticWebApp#0
inputs:
app_location: 'MathApp'
output_location: 'wwwroot'
azure_static_web_apps_api_token: $(deployment_token)

This is an extension to the above solution if you are working with Github actions.
Add following step in .github\workflows\whatever-file-name-you-have.yml
- name: UpdateVersion
uses: datamonsters/replace-action#v2
id: sub
with:enter code here
files: 'Your.App/wwwroot/service-worker.published.js'
replacements: '%%CACHE_VERSION%%=${{ github.run_id }}'
I have used {{ github.run_id }} to get a unique-ish value, but you could opt for any other random string either from https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context or bring your own version.
And the main solution lies in editing service-worker.published.js
const CACHE_VERSION = '%%CACHE_VERSION%%'
const cacheName = `${cacheNamePrefix}${CACHE_VERSION}`;

This answer is intended to complement Ryan Hill's answer:
Blazor automatically updates to the newer version (at least in .NET 5, possibly earlier too). This happens when the application is first closed and restarted in ALL browser tabs including the installed app (which is another browser tab).
The following article helped me a lot:
https://learn.microsoft.com/en-us/aspnet/core/blazor/progressive-web-app?view=aspnetcore-5.0&tabs=visual-studio#installation-and-app-manifest-1
Also helpful:
https://www.eugenechiang.com/2021/05/22/forcing-reload-of-blazor-client-after-publishing-changes/

I finally found an answer for this that helped me. If you do not need PWA, you can remove it and Chrome (and probably other browsers) should stop clinging on to an old client even after deleting cache and fully reloading. Because after having done this my Chrome still reloaded it. For my app I do not need to use this caching feature or to be able to install it as an app.
I found the answer here:
Blazor Chrome caching issues
How to remove PWA:
Delete the following files from wwwroot:
/wwwroot/manifest.json
/wwwroot/service-worker.js
/wwwroot/service-worker.published.js
Delete this line from /wwwroot/index.html
<script>navigator.serviceWorker.register('service-worker.js');</script>
Delete those lines from your csproj file
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
<ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js" />
Also... to actually get rid of the app in Chrome, because I had already loaded it this way, I installed it as an app and then uninstalled the app and removed it from Chrome. That finally got me out of this whole loop with Chrome keeping the app and refusing to fully update it in the browser cache / memory / wherever it kept the app

Related

What could be causing this mystery GCloud App Deploy error? (NodeJS, AppEngine. Standard Environment)

ERROR: (gcloud.app.deploy) Error Response: [9] Cloud build 6axxx...xxx9b status: FAILURE.
I'm trying to understand if I can use a NodeJS / Express server with Google Cloud App Engine, Standard Mode. My application started out from an Express-Generator framework. There is a single page app, and some function calls back to server via custom routes. Nothing terribly crazy.
I set up repo, and $ git clone https://gitlab.com/my_repo into the GCloud shell. Test, test and retest using the sandbox (local development server.) Test url is of the form: https://8080-dot-xxxxxx-dot-devshell.appspot.com Yipee.
Next step is hard deploy: I start with $ gcloud app create followed by $ gcloud app deploy (had to make a side trip to ensure correct authorization and billing stuff is whole, etc...) . Website / server totally works as intended. URL is of the form https://my-custom-XYZ-website.appspot.com/ Works great.
I can check the version at the Google Cloud Platform -- App Engine -- Version console The output there shows me:
Version: 20181120t103136
Status: Deployed
Traffic Allocation: 100%
Instances: 1
Runtime: Node10
Environment: Standard
Size: 748.8 KB
Deployed: (Date/Time by me)
So that's the background. The problem is now I can no longer update the content. I can easily push code to the terminal interface, but the command $ gcloud app deploy fails for any sort of update / new version. Sigh.
Log related info -- Build steps:
Fetcher = successful
Builder = status, Step Failed
Builder Arguments
--name=us.gcr.io/my-custom-XYZ-website/app-engine-tmp/app/ttl-2h:12xxxxxxa5a0 --directory=/workspace --destination=/srv --cache-repository=us.gcr.io/my-custom-XYZ-website/app-engine-tmp/build-cache/ttl-7d --cache --base=gcr.io/gae
runtimes/nodejs10:nodejs10_10_13_0_20181111_RC00
Directory /workspace/
"builder": Permission denied for "d71xxxxxxxxxxxxxxxxxx88b5" from request "/v2/my-custom-XYZ-website/app-engine-tmp/build-cache/ttl-7d/node-cache/manifests/d71xxxxxxxxxxxxxxxxxx88b5". : None
app.yaml
# [START runtime]
runtime: nodejs10
# [END runtime]
handlers:
- url: /images
static_dir: public/images
- url: /javascript
static_dir: public/javascript
- url: /red-canoe
static_dir: public/alt-content
- url: /stylesheets
static_dir: public/stylesheets
- url: /.*
secure: always
redirect_http_response_code: 301
script: auto
Any idea on how to identify and correct what's wrong here?
Note: I did create another simple test product in node.js, and I can easily update the versions there. That test product had only a simple app.js with a simple Hello World response. Version #2 had Hello There, World (okay, so yeah, not the worlds most robust test...). But the version update, via $ gcloud app deploy worked just fine there. I did note the version size on the Hello World app was around 245kb or so.
So, after a whole lot of testing I think I figured out what is happening here.
The node.js application actually utilizes three different Google related components / tools.
Google Firebase Authentication
Google Sheets API, V4
Google App Engine (Deployment)
When I'm created those components, the system prompts me to either create a new project or utilize an existing project. I chose the exact same project for all three tools. I believe the fact that these were all tied together messed up the ability to perform updates to Google App Engine vcloud app deploy
The fix was to delete that three combo project, and create three separate projects
MyProject_Sheets
MyProject_Firebase_Auth
MyProject_AppEngineDeploy
This works reliably. All done.
And for anybody who may be interested in the Firebase / Sheets API stuff I did here, check out this link. I built an online phone directory, protected by login via mobile phone, with contact data stored on a private Google sheet.

Just created Azure Mobile App service calls return http 400 error

Here's what I'm doing.
Install latest Azure SDK (by the date)
Open Visual Studio 2013
Create a new Azure Mobile App project. The simple service is created with TodoItem DataObject and 2 simple controllers - TodoItemController and ValuesController
Do not change anything
Start the project
The service is started and hosted in local IISExpress on url http://localhost:50993/ (the port may vary).
The "This mobile app is up and running" web page is opened in the browser. But http 400 error is returned when I try to invoke some GET-actions: for example http://localhost:50993/api/values or http://localhost:50993/tables/TodoItem.
Any ideas? Is something wrong in my environment or is that me doing something wrong?
Thanks.
I guess you can opt out of version checking by setting a value of true for the app setting MS_SkipVersionCheck. Specify this either in your web.config or in the Application Settings section of the Azure Portal.
This generally happens when you don't add a ZUMO-API-VERSION header to the request. This is required when making requests from a REST client, but the mobile client SDKs add the header automatically.
To fix, add the header ZUMO-API-VERSION with value of 2.0.0.
To learn more, see https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-client-and-server-versioning/.
Adding
http://localhost:50993/tables/Location?ZUMO-API-VERSION=2.0.0
at the end will do the trick.

Content Security Policy violation in a fresh Ember app

Today I created my first Ember App using the ember-cli:
ember new my-app
cd my-app
ember serve
so that it appears by url localhost:4200.
I fail on the next step:
Change content of the basic template application.hbs
After I perform some text changes I hit Cmd+S and reload the page the content remains the same.
The browser console is "clean", but I get error messages in the terminal
Content Security Policy violation: {}
The content of application.hbs:
<h2 id="title">This is a test message</h2>
{{outlet}}
My environment:
ember version: 0.2.3, node: 0.12.2, npm: 2.7.6.
I've searched for answers on Stack, but mostly they concern apps that have some external data requests, but my project is brand new and fresh, so I'm confused.
Looking forward to your replies,
Thanks!
UPDATE:
Some additional info:
I figured out that the problem is that the ember app does not "hear" the trigger, when a file has been changed. I don't receive a
file changed templates/application.hbs
notification in the terminal. Something globally is blocking or interrupting the regular app run.
Still looking forward receiving your suggestions !
Apparently the problem has nothing to do with Content Security Policy violation. It is a local issue of the file system. The terminal didn't display messages that changes were triggered in the template file application.hbs - as a result no updates.
The current solution is starting the ember server with an option:
ember serve --watcher=polling
As soon as I figure out the initial problem I'll return and update this answer.
Cheers

Err_connection_refused using meteor uploads

I am deploying a meteor application to a digital ocean droplet with meteor upload. Everything goes well, the application gets deployed, database works, seeding of data works etc. But there is one problem i can't seem to be able to solve.
I use the meteor-uploads package (https://github.com/tomitrescak/meteor-uploads) for file uploads. Locally everything goes well, the file gets uploaded, finished callback gets called etc. But once I have deployed the application to the server it keeps giving me on of these errors, :
POST http://*ip*/upload net::ERR_CONNECTION_REFUSED
POST http://*ip*/upload net::ERR_EMPTY_RESPONSE
POST http://*ip*/upload net::ERR_CONNECTION_RESET
Any ideas are welcome, I have searched all over for a solution but none seems to fit my problem. I also installed to a fresh droplet but that didn't help. In none of my browsers (Mac Chrome, safari & firefox) does it work, on my phone (Android 5.0) I get the same errors. I am using the newest Meteor version 1.1.0.1
On local host you don't need to set the environmental variables, but the host services provides you should.
Check this tutorial to see how to put the environment variables.
Because the file-upload needs a startup-server-configuration, like this.
//file:/server/init.js
Meteor.startup(function () {
UploadServer.init({
tmpDir: process.env.PWD + '/.uploads/tmp',
uploadDir: process.env.PWD + '/.uploads/',
checkCreateDirectories: true //create the directories for you
})
});
But im not sure if putting this on a startup will work on digital ocean, like i say you you enter it, run printing and check if the /.uploads/ exists

Is there a way to refresh your phonegap application - eg, build the page and start running the scripts from the beginning?

Is there any way to do this?
E.g., if a user starts the app with no internet connection, no remote scripts can be loaded, and the application basically can't run and I display a "No internet" page. But if the user gets internet later and the application is still running, is there any way to just "restart" ?
how about -
document.location = "index.html"
PhoneGap applications are just like an embedded website - you should be able to go to any hyperlink you wish (mind the whitelists).
Of course, if you also want to detect when it's again online, you should use the PhoneGap Network API to bind to those online/offline events.
In general thought, have you ever thought of using the HTML5 manifest functionality to actually let your local PhoneGap app cache those remote scripts? That way your app could still run, even when offline (except if it needs remote data to "do your thing")...
Hope this helps!
Try this
navigator.app.loadUrl("file:///android_asset/www/index.html", {wait:2000, loadingDialog:"Wait,Loading App", loadUrlTimeoutValue: 60000});
Accepted solution works, but might fail if you have an SPA with html5 url routing.
Here's a safest solution:
// keep startup url (in case your app is an SPA with html5 url routing)
var initialHref = window.location.href;
function restartApplication() {
// Show splash screen (useful if your app takes time to load)
navigator.splashscreen.show();
// Reload original app url (ie your index.html file)
window.location = initialHref;
}

Resources