I have created a single page app using AngularJS and ASP.NET MVC 3. When deploying a new version of the application, it's possible for users to be already logged in as the application is being updated. If these users don't either refresh their browser or log out and back in again to get the new JavaScript files, they will encounter lots of errors and could potentially create invalid data.
Question: in a single page app, is there an elegant way to either prompt users to either refresh their browser or log out and back in again?
I suppose this would be possible through Web Sockets / SignalR, but are there other options?
One generic way I could see is to have your angular app send a client-version # with any http request, and your .NET side watch for that number and when it's out of date ( a newer version has been deployed ) send an error response which you would capture in your angular app. You could then just trigger a refresh or prompt the user to refresh and get the latest version.
Related
I was not sure how to name the question but here is what I need to do and I'm looking for some advice how to handle it architecture-wise. I'm Java / Kotlin developer very familiar with Spring Boot and very basic knowledge of front end as a whole - just so you know my origin.
Here is the flow of my new application:
user retrieves a generated link with lots of params that he can click in his browser
when he clicks on that link I want to retrieve those params in backend, run some longish external API calls & calculations (up to 10 seconds) and then return results one by one (some websocket or server sent events) and present them in SPA application (preferably React) with results nicely presented so he can pick one of the options I calculated, fill out some form and pay for it.
Maybe I'm confused - I've worked with many front end developers but I never thought how to actually "start" a SPA when someone clicks on some URL with params and then handle all those passed params via backend.
Is what I just wrote doable with React rendered on client side and Spring Boot as the backend? Or do I have to use React server side rendered because I have this static URL with params?
Could someone clarify how I should approach this?
Generally when a SPA is hosted on a domain, the webserver will be configured to redirect all requests on all paths to the root url. So it doesn't matter what path on your domain the user is trying to access, the SPA will still get loaded.
Then in your React SPA you inspect window.location to find the path and params in the url. You then call the backend (most likely on another domain) sending it the params via a web request. It then sends back a response with a random key, and continues to start the time consuming process in the background. When results come in, they are persisted globally in a dictionary against the random key (could be to a database, could be held in memory if you only are going to need one back-end server). Then on another API endpoint, the React front end can poll with the random key and get the current status of the processing, displaying it to the user.
How can I deploy and Angularjs app and ensure that all my users get the update when it happens? I have a breaking change that needs to be deployed and would cause some downstream issues should a user continue using the old version. Are there any tools or best practices on how to handle this?
Like in the comments says you cant do it with session expires, one alternative you can do, its handle in the backend to check if an update was release and with push notifications cand inform to client. Forcing to reload the app.
An intrusive will do the same thing but without notification, only if response tell there is an update reload page, according api response.
When I make a change to my Backbone web application code on my server, how can I make user's browsers update so they see those changes.
Being a SPA the page rarely if ever refreshes. So even if place hashes/timestamps on my script tags it still wont be adequate enough, ie, this isn't ideal IMO:
...
<script src="js/main.js?t=SOME_HASH"></script>
Does Backbone have a way to handle this?
Backbone being a JS framework that merely gives structure to your applications, it doesn't handle stuff like this. This is something that involves configuration of server and you need to tackle it yourself.
Since you said you have an SPA that rarely refreshes - Your app is probably contacting the server via lots of AJAX requests. You can add an interceptor to these requests on the server that checks if stuff changed on server and sends a shouldReload: true with the response.
You should also have an AJAX interceptor client side that checks for this in response and reloads the page/lets users know about updates on server and give option to reload/restart.
Another option is to implement websockets/polling so that server can push notification about changes to clients. socket.io is a plugin that uses web sockets and falls back to polling.
P.S: You also need to bust the cache as you mentioned in question
I am working on new project to display an online stock price screen for a user. We already have this in a combination of php, MySQL and AJAX, but it is very slow and lots of requests are generated on the server. So I want to change the technology.
I have the database in MySQL. One process is already updated: the last price of stock in my database. I fetch those records and display them in the screen. After searching Google, I feel I have to use socket.io, node.js and angularjs. After this I am planning the following:
Front End in angular.js
Socket.io with nodes.js
Nodes.js
Restful API call initiated on nodes.js every 10 seconds for page.php. This page will fetch all symbols of market (around 1000) from the MySQL database and send back a json object. (Can I directly call a MySQL query from node.js and received the json object, and will this reduce the php in-between?)
Socket.io emits this query to every client connect on the site.
Then the angular front-end will display only the symbol which is selected by the user and highlight the changes on the screen.
I have the following problems, as I have limited knowledge of the above technologies.
How do I receive the json object from socket.io into angular.js?
How can I make the logic in the angular page to display only the symbol which user selected from a 1000 symbols response and highlight the change price field only?
How will I connect three and server with MySQL or php?
One thing is read for middle ware i can use the expressJS.AS I want my front end in AngularJS how can i fit the express in between Angular and socket.io and node.js
You need to include socket.io client code on your site, and here is a good example how to turn an external library like socket.io into a service http://www.html5rocks.com/en/tutorials/frameworks/angular-websockets/
I think that the best solution here would be to subscribe via socket.io only the element user wants to see i.e. websockets for selected element and pooling every minute or so for other elements to not generate that much of a traffic on sockets
user opens element A
socket.emit('subscribe', {add: 'A'})
then user switch to element B
socket.emit('subscribe', {add: 'B', remove: 'A'})
I'm developing an Asp.net MVC + Web API + AngularJS SPA. I would like to have several types of registration/authentication:
own profile provider
external providers ie Google, FB etc.
Possible scenarios
As I'm having an SPA it would be best if I could keep my user on my page while external (or internal for that matter) would be taking place. I'd display a modal layer with particular content loaded (maybe even inside an iframe). Can this be done? Online examples?
Have login/registration capability implemented as usual Asp.net MVC full page reload controller/views and then redirect back to my SPA when that is successful. Also redirect to external provider if users wanted to authenticate/register using external provider.
Any other possibility?
Questions
How did you do this similar scenario in your SPA or how would you recommend to do it?
Should I be using particular authentication patterns regarding this - for instance provide my internal authentication/registration similar to external one so SAP would always behave in the same way
I will also have to authenticate my Web API calls subsequently after user athenticated themselves in the SPA. Any guidance on that?
I can only comment on my own experience, maybe it is helpful. We use the same stack as you, Asp.net MVC + Web API + AngularJS. We use server-side MVC for authentication (Microsoft.AspNet.Identity), since we are not exposing a public API at this stage and the only consumer of the API will be our SPA this works perfectly with the least amount of effort.
This also enables us to set a UserContext Angular service on the server once logged in that can be shared through your entire Angular app, the Google Doubleclick Manager guys goes into some of the benefits of this approach during there ng-conf presentation. Since Web Api supports Asp.Net Identity, authentication and authorization works seamlessly between MVC and Web Api.
To sum up the major pros and cons:
Pros:
Very easy and quick to implement.
Works across MVC and Web Api.
Clientside code does not need to be concerned with authentication code.
Set UserContext Angular service on server side once during login, easily shared throughout SPA using Angular DI. See presentation as mentioned above.
Integrates with external providers as easily as you would with any normal MVC app.
Cons:
Since the browser does not send the hash # part of the URL to the server, return URL on login will always be the root of your SPA. E.g. suppose your SPA root is /app, and you try to access /app#/client when you aren't authenticated, you will be redirected to the login page, but the return URL will be /app and not /app#/client as the server has no way to know the hash part of the URL as the browser never sends this.
Not really supported design if you plan to make your your Web Api available outside your SPA. Imagine a console app trying to connect to your API?
So in short, the MVC view that we use to bootstrap our SPA is protected with [Authorize] as well as our Web Api methods. Inside the MVC view we also initialize our UserContext Angular service using Razor to inject whatever user properties we want to expose. Once the SPA is loaded via the single Razor view, everything else is handled via Angular.
We have used what Beyers described before and it works well for most apps, and I use it frequently.
In our current application we are working on the premise that separation of concern should apply to route management.
Normal lifecycle:
User goes to www.server.com
Server sends down index.html
Client makes request for minified assets (.js, .css., etc.)
Angular loads -- a directive removes the loading class from the body (revealing the login section)
The Angular LoginCtrl makes an autologin attempt. (Login and Autologin in an Angular service).
The server returns a HTTP 401
The login screen remains visible.
User successfully logs in ( server gives the browser a authToken cookie; angular does not know or care)
Angular sets some isAuthenticated variables in the BodyCtrl and LoginCtrl
The login section receives a class of .hidden and the content recieves a class of .visible (insert ng-hide/show animations for fun)
User starts filling out a form, but takes an obligitory, 30 minute phone call from relative.
Server has expired his session 10 minutes ago
User finishes and submits form but the server return unauthorized (401)
http-auth-interceptor intercepts the 401 from the server, caches the submit call and publishes a "login-required' event.
The BodyCtrl listens and sets isAuthenticated = false and then the ng-class and ng-show/hide do there work on the login and content sections.
User re-signs in and 'login-confirmed' event is published
http-auth-interceptor posts cached call.
User is happy
(the content section can also display some public views as our rest api has some routes that are made public -- displaying the public views is handled by a simple function similar to isAuthenticated)
Angular Ctrl structure:
index.html
<body>
<!-- I am a fullscreen login element, z-index=2000-->
<div data-ng-controller="LoginCtrl" data-ng-hide="isAuthenticated()"</div>
<div data-ng-controller="ContentCtrl">
<!-- fullscreen class has a z-index=2001 -->
<section data-ng-view data-ng-class="{fullscreen: isViewPublic()}"></section>
<!-- header and nav go here -->
</div>
</body>
We could get a little more creative on how display the public views/routes but you get the idea. We only have a few public routes and they are mainly for registration, password resets, etc.
Disclaimer: I have yet to integrate with and oauth/external authentication services. Hopefully this setup will still hold water.
Any critique of this process is welcome.
By no means am I familiar with Microsoft backends, but still I'll give it a try ;-) :
Good resources on how the authentication/authorisation should be done in Angular-based SPA:
https://github.com/fnakstad/angular-client-side-auth
live demo: http://angular-client-side-auth.herokuapp.com/login
As you requested there are 2 methods of authenticating:
own profile
external providers.
It redirects to the provider website though :-/
NodeJS on the backend
Good ng-conf talk on how authorisation is done in Google Doubleclick Manager application: http://www.youtube.com/watch?v=62RvRQuMVyg&t=2m29s
It's not quite what you want (authentication), but the solution begins to kick in on the authentication phase. Furthermore it may be useful later and the approach Ido is presenting seems really sound.
Slides: https://docs.google.com/file/d/0B4F6Csor-S1cNThqekp4NUZCSmc/edit
Last but not least: Mastering Web Application Development with AngularJS.
A brilliant Angular book by Paweł Kozłowski and Pete Bacon Darwin.
It has a whole chapter or two dedicated to auth- stuff. It shows some complex solutions, such as retrial and session-expired interceptors. But even if you will not use approaches from the book directly, those chapters are still a must-reads since they may give you an inspiration for devising your own auth- solutions.
Remark - http-auth-interceptor: As it is mentioned in the book, the securityInterceptor solution was originally invented by Witold Szczerba. See the blog post.
http-auth-interceptor code, mentioned by #CorySilva, is actually sample code to concepts explained in the post.
btw: Those 2 chapters are great, but I hope that the Community comes up with some easier solutions in the future. Every time I read this interceptor promise api-based code I get a severe headache :)
btw2: If somebody doesn't consider oneself an Angular expert, the entire book is definetly a must-read and great complement after reading the Guide
As for building the login page with ASP - I suggest using ASP only as a backend and middleware and drawing whole the app with Angular.
You can start with your approach and switch to the pure-Angular SPA if it will begin to require more and more crazy hacks to make technologies play together nicely.
But I might be wrong and this particular case won't require applying any hacks.