Incorrect path to SignalR generated on client - signalr

So I have been plugging away trying to get SignalR to work with my Web Api instance that used OWIN and authentication. After figuring out CORS (thanks to SO help) I am almost there.
My web client fails with a Javascript error on the console.
http://localhost:45325/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22myhub%22%7D%5D&_=1460577212205 404 (Not Found)
if I take this URL and put it in the browser sure enough I get a 404 error. However if I add /signalr/ to the path as such ...
http://localhost:45325/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22myhub%22%7D%5D&_=1460577212205
I get a proper JSON response with the SignalR connectionid and everything ...
{
"Url": "/signalr",
"ConnectionToken": "<token here>",
"ConnectionId": "0bf84c7a-0a28-4da9-bb9f-551de894cf0e",
"KeepAliveTimeout": 20,
"DisconnectTimeout": 30,
"ConnectionTimeout": 110,
"TryWebSockets": true,
"ProtocolVersion": "1.5",
"TransportConnectTimeout": 5,
"LongPollDelay": 0
}
So it looks as though everything is working other than the fact that the URL the client is generating to connect to the SignalR hub is missing the /signalr.
Here is my client side Javascript that connects to the Hub. Where can I specify the path needs to include /signalr? Because I thought I already was ...
<script src="scripts/jquery-2.2.2.min.js"></script>
<script src="scripts/jquery.signalR-2.2.0.js"></script>
<script>
(function ($) {
$(function () {
var connection = $.hubConnection('/signalr/', {useDefaultPath: false});
var myHubProxy = connection.createHubProxy('MyHub');
myHubProxy.on('notify', function (username) {
console.log(username + ' has logged in');
alert(username + ' has logged in');
});
connection.url = 'http://localhost:45325';
connection.start()
.done(function() {
alert('Connected to MyHub: Connection ID = ' + connection.id);
})
.fail(function(e) {
console.log('Connection error: ' + e);
});
});
})(jQuery);
</script>
You may notice that I did not include <script src="signalr/hubs"></script>. This is because I am created the proxy myself instead of relying on the auto-generated proxy

I figured it out! It should have been obvious to me ...
In my Javascript on the client I needed to add the \signalr path ...
connection.url = 'http://localhost:45325/signalr';
Perhaps I should have seen that in my public void Configuration(IAppBuilder) method inside the Startup.cs class of my Web Api I had the following ..
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
// EnableJSONP = true; // I am not using as CORS is working just fine
};
map.RunSignalR(hubConfiguration);
});
I was specifying the subdirectory "/signalr"

Related

SingalR ASP.NET Cross Domain Connection Issue

I am trying to implement an ASP.NET SignalR app as mentioned here.
I have implemented the client as mentioned here. For the client I am using code without the generated proxy.
Client and server successfully connect when both are on the same domain but unable to communicate when hosted cross domain. Although the code mentioned for cross domain in the above articles is already implemented. Since my client and server are hosted in Azure, is there a setting in Azure that needs to be enabled for cross domain communication or there is something else that I am missing?
Here is the error i am getting:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin is therefore not allowed access. The response had HTTP status code 500.
My startup class is:
public void Configuration(IAppBuilder app)
{
//app.UseCors(CorsOptions.AllowAll);
// Any connection or hub wire up and configuration should go here
//app.MapSignalR();
// Branch the pipeline here for requests that start with "/signalr"
app.Map("/signalr", map =>
{
// Setup the CORS middleware to run before SignalR.
// By default this will allow all origins. You can
// configure the set of origins and/or http verbs by
// providing a cors options with a different policy.
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
// You can enable JSONP by uncommenting line below.
// JSONP requests are insecure but some older browsers (and some
// versions of IE) require JSONP to work cross domain
// EnableJSONP = true
};
// Run the SignalR pipeline. We're not using MapSignalR
// since this branch already runs under the "/signalr"
// path.
map.RunSignalR(hubConfiguration);
});
}
And the client code is:`
$(function (){
var ChatServerUrl ="http://chatserverurl.net/home/";
var ChatUrl = ChatServerUrl + "signalr";
var connection = $.hubConnection(ChatUrl, { useDefaultPath: false });
connection.logging = true;
var chatHubProxy = connection.createHubProxy('chatHub');
chatHubProxy.on('addNewMessageToPage', function (name, message) {
console.log("AddNewMessageToPage Function!");
// Add the message to the page.
$('#discussion').append('<li><strong>' + htmlEncode(name)
+ '</strong>: ' + htmlEncode(message) + '</li>');
});
// Get the user name and store it to prepend to messages.
$('#displayname').val(prompt('Enter your name:', ''));
// Set initial focus to message input box.
$('#message').focus();
// Start the connection.
//connection.start({ withCredentials : false }).done(function () {
connection.start({ withCredentials: true }).done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chatHubProxy.invoke('Send', $('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
console.log("SignalR Connected!");
});
});`
Please try this according to what the below links suggest
https://learn.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client

Calling WCF service with json output from angularjs with windows authentication

I've got a wcf Service which has a method which send its output in jsonformat. The service is hosted in an https-Environment.
i'm calling it with angularjs-resource:
var hrdemo = angular.module('hrdemo', ["ngResource"]);
hrdemo.controller('HrDemoCtrl', function ($scope, hrdbservice) {
$scope.items = hrdbservice.get({ 'Id': 1 });
var a = $scope.items.length;
});
hrdemo.factory('hrdbservice', function ($resource) {
return $resource('http://hrservice/HrService.svc/:Id', { Id: "#Id" }, { get: { method: 'JSONP' } });
});
Angularjs runs in an ASP.Net-Web Application.
When calling the Service I get something like an xhr-problem.
1) How can i authenticate with my Windows authentication over angularjs
2) What can I do to fix the xhr-problem?
May the withCredentials option is what you are searching for $http.post(url, {withCredentials: true, ...}). Also there is a specific shortcut for performing a JSONP request in AngularJS - $http.jsonp()
AngularJS Docs

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

XDomainRequest in IE is giving Access is Denied error

This is the code I am using is as follows down below:
I am using IE9 and am unable to see the request being sent in the Network tab. I do have Access-Control headers set in the JSP as:
<% response.setHeader("Access-Control-Allow-Origin", "*");%>
Code to get the AJAX HTML Content from the JSP:
if ($.browser.msie && window.XDomainRequest) {
var xdr = new window.XDomainRequest();
xdr.open("GET", "http://dev01.org:11110/crs/qw/qw.jsp?&_=" + Math.random());
xdr.contentType = "text/plain";
xdr.timeout = 5000;
xdr.onerror = function () {
console.log('we have an error!');
}
xdr.onprogress = function () {
console.log('this sucks!');
};
xdr.ontimeout = function () {
console.log('it timed out!');
};
xdr.onopen = function () {
console.log('we open the xdomainrequest');
};
xdr.onload = function() {
alert(xdr.responseText);
};
xdr.send(null);
} else { ...... }
I am getting a Access is Denied Error. Any help would be much appreciated!
Requests must be targeted to the same scheme as the hosting page
In your example you are doing request to:
http://dev01 ...
And you should do this from HTTP protocol.
For example:
If your site, where js script is located: http://dev.org
You can do this:
xhr = new XDomainRequest();
xhr.open("GET", "http://dev01.org?p=1");
but this throws "Access denied":
xhr = new XDomainRequest();
xhr.open("GET", "https://dev01.org?p=1");
My experience with XDomainRequest is that it doesn't respect Access-Control-Allow-Origin: *. Instead, you must specify the domain. This can be obtained from the HTTP_REFERER header if you need to dynamically generate it, or if you are only expecting requests from one domain you can set it manually. This article might help.
<% response.setHeader("Access-Control-Allow-Origin", "http://dev01.org");%>

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