Firefox Desktop Notifications not showing when multiple tabs are open - asp.net

By Web Notification I mean this (The Notification interface of the Notifications API is used to configure and display desktop notifications to the user).
I have Asp.Net MVC web app and I have a button in my page which supposed to push a notification to clients.
I also used signalr to push message and call notification function.
my layout.cshtml looks like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
</head>
<body>
<button id="btn" type="button">click</button>
#RenderBody()
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.1.min.js"></script>
<script src="~/signalr/hubs"></script>
<script>
jQuery(function ($) {
var myHub = $.connection.chatHub;
myHub.client.addNewMessageToPage = function (title, message) {
var options = {
body: message,
tag: 'aaa'
}
// check permissions if already granted
if (Notification.permission === "granted") {
var notification = new Notification(title, options);
} else if (Notification.permission !== 'denied') {
// request permission
Notification.requestPermission(function (permission) {
// If the user accepts, let's create a notification
if (permission === "granted") {
var notification = new Notification(title, options);
}
});
}
console.log('the hub method called sucessfully');
}
$.connection.hub.logging = true;
$.connection.hub.start().done(function () {
$('#btn').on('click', function () {
myHub.server.send('foo', 'bar');
});
});
});
</script>
</body>
</html>
The problem is, the push notifications stops working/showing in firefox when I have multiple pages of my app open. (it works when single tab is open).
this bug only happens in firefox and works well in chrome and IE.
update 1:
I think its not signalr problem since the hub method is invoked.
this line is called on all tabs:
console.log('the hub method called sucessfully');
and signalr logging says that:
SignalR: Invoking myhub.Send jquery.signalR-2.2.1.min.js
SignalR: Triggering client hub event 'addNewMessageToPage' on hub 'MyHub'. jquery.signalR-2.2.1.min.js
foo bar
SignalR: Invoked myhub.Send jquery.signalR-2.2.1.min.js

This is a Firefox bug.
The way worked for me was call the Notification in a different time. This is not a complete fix but is working well.
var randomTime = Math.floor((Math.random() * 20) + 1) * 50;
setTimeout(function () {
newNotification = new Notification(Title, NotificationContent);
}, randomTime);

Your question is similar to this one.
And I suggest to use IWC-SignalR from this answer.

This problem is related to Web Socket. You have to enable your websocket first.
$.connection.hub.logging = true;
then you can user socket start function to detect your connections.
$.connection.hub.start({ transport: 'webSockets' }).done(function () { .. });

Related

Firebase Hosting Flutter Web App not clearing Cache of first deploy

We build a flutter web app and deployed it via firebase hosting. Unfortunately, we didn't configure any caching settings in our initial deploy.
Now we deployed a newer version of our website but people still get the old website shown form the first deploy. What we tried so far:
Adding version no. to our index.html:
<"script src="main.dart.js?version=1" type="application/javascript"></script>
Adding meta Data in our header in index.html:
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
In our firebase.json we added the following headers:
"headers": [
{
"source": "**",
"headers": [
{
"key": "Cache-Control",
"value": "max-age=10"
}
]
}
]
All of these attempts were without any luck. We think that the problem is that the newer version doesn't have those entries in the files. How can we force this to update to our newest version? We even consider opening a new firebase project if that might help.
Try this:
In your flutter app, in the index.html within the web folder, add a version number after the src="main.dart.js
So your new line will look like this:
<script src="main.dart.js?version=1" type="application/javascript"></script>
Then increment the version number to 2, etc before you do each build.
update june 2021: add this line in index.html as the last script in the body
I see Flutter now include this script by default in index.html if project is created recently which has serviceWorkerVersion element which updates the version when compiling:
<script>
var serviceWorkerVersion = null;
var scriptLoaded = false;
function loadMainDartJs() {
if (scriptLoaded) {
return;
}
scriptLoaded = true;
var scriptTag = document.createElement('script');
scriptTag.src = 'main.dart.js';
scriptTag.type = 'application/javascript';
document.body.append(scriptTag);
}
if ('serviceWorker' in navigator) {
// Service workers are supported. Use them.
window.addEventListener('load', function () {
// Wait for registration to finish before dropping the <script> tag.
// Otherwise, the browser will load the script multiple times,
// potentially different versions.
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
navigator.serviceWorker.register(serviceWorkerUrl)
.then((reg) => {
function waitForActivation(serviceWorker) {
serviceWorker.addEventListener('statechange', () => {
if (serviceWorker.state == 'activated') {
console.log('Installed new service worker.');
loadMainDartJs();
}
});
}
if (!reg.active && (reg.installing || reg.waiting)) {
// No active web worker and we have installed or are installing
// one for the first time. Simply wait for it to activate.
waitForActivation(reg.installing ?? reg.waiting);
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
// When the app updates the serviceWorkerVersion changes, so we
// need to ask the service worker to update.
console.log('New service worker available.');
reg.update();
waitForActivation(reg.installing);
} else {
// Existing service worker is still good.
console.log('Loading app from service worker.');
loadMainDartJs();
}
});
// If service worker doesn't succeed in a reasonable amount of time,
// fallback to plaint <script> tag.
setTimeout(() => {
if (!scriptLoaded) {
console.warn(
'Failed to load app from service worker. Falling back to plain <script> tag.',
);
loadMainDartJs();
}
}, 4000);
});
} else {
// Service workers not supported. Just drop the <script> tag.
loadMainDartJs();
}
If you do not want to use the server worker caching, you can provide --pwa-strategy=none. Otherwise, the app will update after the new version has been downloaded and the page revisited.
Example:
flutter build web --release --pwa-strategy=none
It will Generate a service worker with no body. This is useful for local testing or in cases where the service worker caching functionality is not desirable
By default, it is set to offline-first: Attempt to cache the application shell eagerly and then lazily cache all subsequent assets as they are loaded. When making a network request for an asset, the offline cache wil be preferred.
Reference:
https://github.com/flutter/flutter/issues/71333#issuecomment-736732314
flutter help build web
When you build flutter web then in directory build/web generated a version.json file.
just increase build_number and version in this file.

MVC 5 ASP.NET Identity & SignalR

I have the default Visual Studio 2013 MVC template. I'm getting an error "JavaScript runtime error: '$' is undefined" after I log in using ASP.NET Identity and navigate to the Match.cshtml page I created which is below. Any ideas why it's not seeing the jquery '$'?
[EDIT]
If I make a normal HTML page everything works so this somehow must be related to using a layout or something around that. I'm using the default templates _Layout page.
#using Microsoft.AspNet.Identity
#if (Request.IsAuthenticated)
{
<!--Script references. -->
<!--Reference the jQuery library. -->
<script src="Scripts/jquery-2.1.0.min.js"></script>
<!--Reference the SignalR library. -->
<script src="Scripts/jquery.signalR-2.0.3.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="signalr/hubs"></script>
<!--Add script to update the page and send messages.-->
<script type="text/javascript">
$(function () {
var clientID = "";
var server = $.connection.gameServer;
// Create a function that the hub can call to broadcast messages.
server.client.broadcastMessage = function (name, message) {
// Html encode display name and message.
var encodedName = $('<div />').text(name).html();
var encodedMsg = $('<div />').text(message).html();
// Add the message to the page.
$('#discussion').append('<li><strong>' + encodedName
+ '</strong>: ' + encodedMsg + '</li>');
};
// get the ID from the server for our team
server.client.responseID = function (id) {
clientID = id;
}
// Start the connection.
$.connection.hub.start().done(function () {
server.server.requestID();
// todo: define all the GUI events that need to send requests to the server for validation
$('#sendmessage').click(function () {
// Call the Send method on the hub.
server.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
</script>
}
else
{
<div>Please login!</div>
}
I needed to wrap my scripts in my Match view inside the scripts section.
#section scripts{
#Scripts.Render("~/Scripts/jquery.signalR-2.0.3.min.js")
#Scripts.Render("~/signalr/hubs")
etc...

How to correctly login user in mobile app built with PhoneGap

Im building a mobile app on a PhoneGap. I've created several static HTML pages (stored on the phone locally) and trying to load some data from server using AJAX.
$( document ).bind( "mobileinit", function() {
$.support.cors = true;
$.mobile.allowCrossDomainPages = true;
});
$(document).ready(function () {
ajaxDeferred = $.ajax({
url: 'http://example.com/api/isAuthorized'
type: method,
data: parameters,
timeout: 40000
});
ajaxDeferred
.done(function(data) {
alert(data.result);
})
.fail(onFailHandler);
});
On a server side I have this code
public ActionResult IsAuthorized()
{
FormsAuthentication.SetAuthCookie("shade", true);
return this.Json(
new
{
result = this.HttpContext.User.Identity.IsAuthenticated
},
JsonRequestBehavior.AllowGet
);
}
I expect:
On the first run recieve "False" result since user is not authorized
On the second run recieve "True", because of SetAuthCookie
When I try it in a browser, it works as expected.
But whatever I run mobile app i alwayes recieve False, like cookies are not being tranfered.
So the question is how to correctly login user with AJAX, is it possible?
What are best practises? For unknown reason this simple scenario is not covered by PhoneGap manuals.
Ok, I found an answer:
$(document).ready(function () {
...
});
is not suitable. Instead one have to use
document.addEventListener(
"deviceready",
function() {
... at this point cookies are working fine!
},
false);
Access-Control-Allow-Origin and Access-Control-Allow-Credentials headers are not required as well as other cross-domain techniques

Need to get profile information after successful login to facebook

Totally new to this API I am working on a web site that uses Facebook API to allow them to log in. The code is old and now does not work so I am trying to upgrade to use new SDK. I am correctly getting them to login using this:
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function () {
FB.init({
appId: '<%= System.Configuration.ConfigurationManager.AppSettings["ApiID"] %>', // App ID
channelUrl: 'http://<%= Request.ServerVariables["SERVER_NAME"] %>/channel.html', // Channel File
status: true, // check login status
cookie: true, // enable cookies to allow the server to access the session
xfbml: true // parse XFBML
});
// Additional initialization code here
};
// Load the SDK Asynchronously
(function (d) {
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) { return; }
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
} (document));
</script>
and this link:
<strong>Login using Facebook</strong>
This seems to work as then you can open facebook.com and you are logged in correctly. However I cannot seem to find how to check this in C#. I have this so far:
//Facebook Authenticated, created session and API object
_connectSession = new FacebookClient();
//example of getting access code
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("client_id", System.Configuration.ConfigurationManager.AppSettings["ApiID"]);
parameters.Add("redirect_uri", Request.Url.AbsoluteUri);
parameters.Add("client_secret", System.Configuration.ConfigurationManager.AppSettings["Secret"]);
parameters.Add("scope", "publish_stream,email");
IDictionary<string, object> result = (IDictionary<string, object>)_connectSession.Get("/oauth/access_token", parameters);
string accessToken = (string)result["access_token"];
However I get this error:
(OAuthException - #1) Missing authorization code
If anyone can point me in the direction of how in C# I can get the profile information as we already have the ID in our database I just need to log them in as one of our users.
You're missing the code parameter needed to fetch the access_token - the exception appears to be correct. Check the server side-flow in the Authentication documentation
You likely just need to include the code parameter you received when the user was redirected back to your app from the auth dialog - the other parameters in your call to fetch the access token look correct
I have this test page below, which is code straight from Facebook developers. It is suppose to prompt you to login and then put your picture and name in the elements. While it logs you in correctly it does not update.
** updated code, this now works *
<%# Page Language="C#" AutoEventWireup="true" CodeFile="testfb.aspx.cs" Inherits="testfb" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head id="Head1" runat="server">
<title></title>
<script type="text/javascript" src="/js/jquery-1.6.1.min.js" charset="utf-8"> </script>
<script src="/js/jquery-ui-1.8.custom.min.js" type="text/javascript"></script>
</head>
<body>
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function () {
FB.init({
appId: '111081862265698', // App ID
channelUrl: '//<%= Request.ServerVariables["SERVER_NAME"] %>/channel.html', // Channel File
status: true, // check login status
cookie: true, // enable cookies to allow the server to access the session
xfbml: true // parse XFBML
});
FB.login(function (response) {
if (response.authResponse) {
alert('Welcome! Fetching your information.... ');
FB.api('/me', function (response) {
alert('Good to see you, ' + response.name + '.');
var image = document.getElementById('image');
image.src = 'http://graph.facebook.com/' + response.id + '/picture';
var name = document.getElementById('name');
name.innerHTML = response.name
});
} else {
alert('User cancelled login or did not fully authorize.');
}
});
};
// Load the SDK Asynchronously
(function (d) {
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) { return; }
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
} (document));
</script>
<div align="center">
<img id="image"/>
<div id="name"></div>
</div>
<div class="fb-login-button" scope="email">
Login with Facebook
</div>
</body>
</html>

How to connect with new Facebook C# SDK v5.0?

I've been using the old v3.0 C# SDK for some time and Facebook have decided to deprecate that API and also block it so I can no longer use it. I'm trying to upgrading to v5.0 but it seems a lot more different and I can't get it to authenticate.
All I need is a Facebook login button which people click, login and allow permissions to my app (which works) but then I want to be able to call Get() on the C# SDK in the code behind to get their friends. This is what I have in my aspx page which works fine to allow them to login:
<input type="button" id="fblogin" value="Login to Facebook" disabled="disabled"/>
<div id="fb-root"></div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId: 'myappid',
cookie: true,
xfbml: true,
oauth: true
});
function facebooklogin() {
FB.login(function(response) {
if (response.authResponse) {
// user authorized
// make sure to set the top.location instead of using
var accessToken = response.authResponse.accessToken;
window.location.reload();
} else {
// user cancelled
}
},
{
scope: 'publish_stream'
});
};
$(function() {
// make the button is only enabled after the facebook js sdk has been loaded.
$('#fblogin').attr('disabled', false).click(facebooklogin);
});
};
(function() {
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
} ());
However when I'm trying to connect to the Facebook client as below it throws an error which says
(OAuthException) An active access token must be used to query
information about the current user."} System.Exception
{Facebook.FacebookOAuthException}
FacebookClient client = new FacebookClient(myappid, mysecretkey)
SomeDictionary object = client.Get("/me/friends");
What am I missing to get this active authtoken? How can I access it in the code behind? Also what's the difference between using FacebookClient and FacebookWebClient?
In your web.config file you also have to set:
<facebookSettings appSecret="your app secret" appId="your app id" />
and to get the current user:
var facebookApp = new FacebookApp();
facebookApp.Api("/4");

Resources