SignalR Error 500 on server - asp.net - asp.net-mvc

I have a simple chat application that works fine locally, but the SignalR throws an internal server error remotely.
The script that throws the error looks like this:
http://mydomainname.com/signalr/negotiate?clientProtocol=1.5&connectionData...
Here is the log:
I have looked at other answers on a similar topic but none seem to work for me.
These are the answers I referenced: SignalR Negotiate 404, SignalR Negotiate 404 on Subdomain.
Here is the client code:
$(function () {
// Reference the auto-generated proxy for the hub.
$.connection.hub.url = 'http://mydomainname.com/signalr';
$.connection.hub.logging = true;
var chat = $.connection.chatHub;
var name = '<%= username%>'
// Create a function that the hub can call back to display messages.
chat.client.addNewMessageToPage = function (name, message) {
// Add the message to the page.
bootbox.alert({
message: "<b>" + name + "</b>: " + message,
});
};
chat.client.sendMessage = function (name, message) {
// Add the message to the page.
$('#discussion').append('<li><strong>' + htmlEncode(name)
+ '</strong>: ' + $('#message').val() + '</li>');
};
// Start the connection.
$.connection.hub.start().done(function () {
// code to append message omitted.
});
});
On navigating to the error link I get a Cryptographic Exception as shown here: SignalR CryptographicException on AzureWebsites. Is there a solution to this problem?
I'm using asp.net 4.5 and SignalR 2. I have tried lots of things and I'm not sure why the internal server error exists. Any help will be greatly appreciated.

Like #Pawel said in the comment above, the problem was with the http://mydomainname.com/signalr/negotiate returning a 500 error: Cryptographic Exception in this case.
I managed to solve this by adding the Microsoft.AspNetCore.DataProtection.SystemWeb package - as described here: https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/compatibility/replacing-machinekey

Related

Call Graph API from SharePoint

I need to call Graph API from spfx webpart.
Previously we used the following method:
import { MSGraphClient } from '#microsoft/sp-client-preview';
But later we got to know that MSGraphClient is depreciated now in sp-client-preview.
I checked the following method which is mentioned in Microsoft docs also.
import { MSGraphClient } from '#microsoft/sp-http';
But it is giving an error as following:
Module '"d:/O365/upload-onedrive/node_modules/#microsoft/sp-http/dist/index-internal"' has no exported member 'MSGraphClient'
SPFx version we are using now is 1.6
Is there any way call Graph API from spfx now?
Of course we can use Graph in SPFx.
Graph+adal+SPFx steps:
Create an application in Azure portal. Click the manifest, then change "oauth2AllowImplicitFlow" value to true
Go to Settings->Required Permissions->ADD->Select an API->Microsoft Graph, select the permission and then Grant Permissions.
Build HelloWorld SPFx project : https://learn.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/get-started/build-a-hello-world-web-part
Add and IAdalConfig.ts and WebPartAuthenticationContext.js patch files
Tips: If you have no adal module in node_modules/#types folder, you'd better manually install the module using the command : npm install #types/adal#1.0.29
Add the following code to render()
// Make an AJAX request to the Graph API and print the response as JSON.
var getToken;
var getCurrentUser = function (access_token) {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://graph.microsoft.com/v1.0/me', true);
xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// Do something with the response
getToken=JSON.stringify(JSON.parse(xhr.responseText), null, ' ');
console.log('get Graph APi information=='+getToken);
} else {
// TODO: Do something with the error (or non-200 responses)
// console.log(' error');
}
};
xhr.send();
There is actually no reason to create any applications in the Azure side, it's all automatic and taken care of by SharePoint. See following documentation for details. We did change the API structure slightly between preview and GA, but the basics have remained the same with MSGraphClient usage and no reason for any manual access token handling.
https://learn.microsoft.com/en-us/sharepoint/dev/spfx/use-msgraph

Why does vsts-node-api always return Invalid Resource - 401?

I am attempting to use the vsts-node-api package in a custom Build task that I am writing and trying to use on on-prem tfs2017. I have leveraged some of the Sample code found on the github repo, and I've found that it returns an error of Invalid Resource. Doing some debugging in VSCode and then adding some debug logging to the rest code, I find that the rest call returns a 401. The error occurs after I get the WebApi and then try to connect.
I've attempted to use the PAT Handler, and the NtlmHandler, but no luck. If I hit the URI through my browser, I successfully get the JSON returned.. any help would be super appreciated.
export async function getWebApi(pwd:string): Promise<vm.WebApi> {
return new Promise<vm.WebApi>(async (resolve, reject) => {
try {
console.log("in the common getter");
let serverUrl = 'https://mylocalserver/tfs/mycollection';
let token = ' my PAT on the server, that has full access ';
let authHandler = vm.getPersonalAccessTokenHandler(token);
let option = {
ignoreSslError: true
};
let vsts: vm.WebApi = new vm.WebApi(serverUrl, authHandler,options);
console.log("got web api?");
let connData: lim.ConnectionData = await vsts.connect();
console.log('Hello ' + connData.authenticatedUser.providerDisplayName);
resolve(vsts);
}
catch (err) {
console.log("error in get api " + err.message);
reject(err);
}
});
thanks
It looks like this response from the VSTFS team is the way to go.
TLDR;
Generate a bearer OAuth token per build to talk back to VSTS.

How do I get Laravel to listen to private Pusher channels?

I read a few other questions similar to this but wasn't able to find a satisfactory answer, so just asking again with what I have done in my code so far.
in resources/assets/bootstrap.js I have
window.Echo = new Echo({
broadcaster: 'pusher',
key: '8c5cc1d9fe77464ac2df',
cluster: 'us2',
encrypted: true,
authEndpoint: '/chat4/public/authenticate-broadcasting',
});
and in my routes/web.php I have:
Route::post('/authenticate-broadcasting', function () {
return true;
});
but when I load the application page, in console I get:
POST http://laraveldemo-one.com/chat4/public/authenticate-broadcasting 500 (Internal Server Error)
Pusher : Couldn't get auth info from your webapp : 500
I installed Laravel Echo and Pusher correctly because if I use public channels, my application works perfectly, but I'm failing miserably using private channels, I'm not sure what else I can try as I have read thru the documentation a few times and can't find anything I'm missing. Help me please! :)
You must send csrf_token
You can send via meta tags or in Echo json parameter with
auth: {
headers: {
'X-CSRF-Token': 'some_csrf_token'
}
}
https://pusher.com/docs/client_api_guide/client_connect

Bridging a simple Node.js & Socket.io chat app with a Rails app (on Heroku)

I have a basic Node.js & Socket.io chat application running on Heroku that I want to integrate into my main rails website. I understand the way to do this is to have two separate Heroku apps - one for rails, one for Node.js.
It doesn't appear to be as simple as moving the client html from the node app to the rails app (giving it the other app's url in 'io.connect();').
The chat app server seems to automatically call the client index.html its own application, and not allow an external source to connect to it. Removing the code that does this (marked below) does not make it work.
I'm painfully new to Node.js & Socket.io and am hoping that this might be a relatively simple fix for a pro.
I believe the functionality I'm after here works in Liam Kaufman's excellent rails/node.js/socket.io example - his node.js server code is here: https://github.com/liamks/Chatty-Node-Server/blob/master/chat-server.js
I've tried mocking my app's code up to be like his, but haven't yet been able to make it work. He e.g. appears to use an 'http' server, whereas mine uses an 'express' server - I wondered if this might be relevant.
Any help would be greatly appreciated.
UPDATE: Ok, so a bizarre turn of events, thanks to redhotvengeance's reply below I've got this working - server is up on heroku and my client html and javascript connects to it. Great - code below. The problem is, however, that the client html file only connects when it's outside of the Rails app!! i.e. on my desktop!! The moment I put it in the rails application's public/ folder or in a view on my localhost, I get nothing! This makes no sense. I checked it wasn't because of any other random erroneous javascript in my asset pipeline conflicting by just creating a new rails app and dropping the html file in the public/ folder - again nothing - just a dead html page that doesn't connect. Does anyone have any idea what might be going on here? Does Rails have some security feature in place that stops connections to external servers or something??
UPDATE 2: I'm told this has something to do with the 'same origin policy', and I'm in trouble. Is there any way around it? Seems Liam didn't have this problem.
Client:
<script src="http://calm-sands-3826.herokuapp.com/socket.io/socket.io.js" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script>
var socket = io.connect('http://calm-sands-3826.herokuapp.com');
// on connection to server, ask for user's name with an anonymous callback
socket.on('connect', function(){
// call the server-side function 'adduser' and send one parameter (value of prompt)
socket.emit('adduser', prompt("What's your name?"));
});
// listener, whenever the server emits 'updatechat', this updates the chat body
socket.on('updatelog', function (username, data) {
$('#log').append('<b>'+username + ':</b> ' + data + '<br>');
});
// listener, whenever the server emits 'updateusers', this updates the username list
socket.on('updateusers', function(data) {
$('#users').empty();
$.each(data, function(key, value) {
$('#users').append('<div>' + key + '</div>');
});
});
</script>
<div style="float:left;width:100px;border-right:1px solid black;height:300px;padding:10px;overflow:scroll-y;">
<b>USERS</b>
<div id="users"></div>
</div>
<div style="float:left;width:300px;height:250px;overflow:scroll-y;padding:10px;">
<div id="log"></div>
</div>
Server:
var port = process.env.PORT || 5001;
var io = require('socket.io').listen(parseInt(port));
io.configure(function(){
io.set("transports", ["xhr-polling"]);
io.set("polling duration", 10);
io.set("close timeout", 10);
io.set("log level", 1);
})
// usernames which are currently connected to the chat
var usernames = {};
io.sockets.on('connection', function (socket) {
// when the client emits 'adduser', this listens and executes
socket.on('adduser', function(username){
// we store the username in the socket session for this client
socket.username = username;
// add the client's username to the global list
usernames[username] = username;
// echo to client they've connected
socket.emit('updatelog', 'SERVER', 'you have connected');
// echo globally (all clients) that a person has connected
socket.broadcast.emit('updatelog', 'SERVER', username + ' has connected');
// update the list of users in chat, client-side
io.sockets.emit('updateusers', usernames);
});
// when the user disconnects.. perform this
socket.on('disconnect', function(){
// remove the username from global usernames list
delete usernames[socket.username];
// update list of users in chat, client-side
io.sockets.emit('updateusers', usernames);
// echo globally that this client has left
socket.broadcast.emit('updatelog', 'SERVER', socket.username + ' has disconnected');
});
});
If what you're trying to do is connect pages in your Rails app to your seperate Node.js app running socket.io, then skip setting up Express entirely. You're not looking to actually serve pages from your Node app, just connect users to the socket.io server.
Let's say your Node.js app on Heroku is called: my-awesome-socket-app.
my-awesome-socket-app:
var io = require('socket.io').listen(parseInt(process.env.PORT));
io.configure(function () {
io.set("transports", ["xhr-polling"]);
io.set("polling duration", 10);
});
io.sockets.on('connection', function (socket) {
socket.on('disconnect', function () {
io.sockets.emit('user disconnected');
});
});
Then, in the Rails pages you want to connect to the socket.io server:
<script src="http://my-awesome-socket-app.herokuapp.com/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://my-awesome-socket-app.herokuapp.com');
socket.on('connect', function (data) {
console.log('connected!');
});
</script>

Backbone Model from Hub in SignalR

How can i create/convert this script into model in Backbone that can use SignaR Hubs? For example:
<script type="text/javascript">
$(function () {
// Proxy created on the fly
var chat = $.connection.chat;
// Declare a function on the chat hub so the server can invoke it
chat.addMessage = function (message) {
alert("message");
};
// Start the connection
$.connection.hub.start();
});
</script>
EDIT
I did come up with this:
window.Message = Backbone.Model.extend({
hub: undefined,
initialize: function () {
this.hub = $.connection.message;
},
addMessage: function (message) {
alert(message);
},
connect: function () {
$.connection.hub.start();
var messages = this.hub.getAll();//get messages
}
});
but this is not working due to the following error:
this error: :55885 Unexpected response code: 200
If you use default settings SignalR will first try to send a websockets poll to the server. The :55885 is simply the port number of your server. Websockets protocol expects a response status code of 101 (see http://dev.w3.org/html5/websockets/).
If running IIS, unless you run Windows 8 with ASP.NET 4.5 your webserver, it will not recognize a web sockets request and (begin speculation) treat it as a normal get request and return status code 200 (OK) (end speculation) which is an unexpected response in the eyes of the websockets initiator. When this happens SignalR falls back to longpolling instead.
This might not answer your question but it will help you understand the error you get (which is likely not the reason why your code doesn't work)
Also, check out http://srtsolutions.github.com/backbone.signalr/ which is a Backbone.js/SignalR integration Nuget package.

Resources