I created a new Empty Project in VS 2013, configured it to run using OwinHost and installed the following packages in order:
PM> Install-Package Owinhost
PM> Install-Package Microsoft.Owin
PM> Install-Package Microsoft.Owin.StaticFiles
PM> Install-Package Microsoft.AspNet.SignalR.JS
PM> Update-Package jQuery
PM> Install-Package Microsoft.AspNet.SignalR.Owin
Then, I added a Hub class as follows:
using Microsoft.AspNet.SignalR;
namespace OwinHosting
{
public class MyHub : Hub
{
public void Send(string name, string message)
{
Clients.All.addMessage(name, message);
}
}
}
In the startup.cs I added this:
using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(OwinHosting.Startup))]
namespace OwinHosting
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HubConfiguration {EnableCrossDomain = true };
app.MapHubs(config);
app.UseStaticFiles("/Web");
}
}
}
Finally, I added a Web folder, moved the Scripts folder to it and added the index.html page:
<!DOCTYPE html>
<html>
<head>
<title>SignalR Simple Chat</title>
<style type="text/css">
.container {
background-color: #99CCFF;
border: thick solid #808080;
padding: 20px;
margin: 20px;
}
</style>
</head>
<body>
<div class="container">
<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" />
<input type="hidden" id="displayname" />
<ul id="discussion"></ul>
</div>
<!--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="http://localhost:8888/signalr/hubs"></script>
<!--Add script to update the page and send messages.-->
<script type="text/javascript">
$(function () {
//Set the hubs URL for the connection
$.connection.hub.url = "http://localhost:8888/signalr";
// Declare a proxy to reference the hub.
var chat = $.connection.myHub;
// Create a function that the hub can call to broadcast messages.
chat.client.addMessage = 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 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.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
</script>
When I run the page, it asks for the "username". When I type a message and hit "send", it just doesn't respond with anything.
I used Chrome Tools, it seems "chat" variable inside the "click" event is undefined for some reason.
Any idea?
Thanks
I think your issue is that you don't have the right NuGet packages installed.
The reason your chat chat variable is undefined is likely because your http://localhost:8888/signalr/hubs script is not being found, and that script is responsible for defining $.connection.myHub.
Since you are using the latest version (2.0.3) of the SignalR JS client, you should also be using the latest SignalR server components. The Microsoft.AspNet.SignalR.Owin package you installed no longer exists in SignalR 2.x.x. The latest Microsoft.AspNet.SignalR.Owin package actually depends on Microsoft.AspNet.SignalR.Core 1.2.1 which is out of date.
The easiest way to get started self-hosting SignalR, would probably be to uninstall all your SignalR and Owin related packages and follow this tutorial: http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-signalr-20-self-host
This tutorial is based on using the Microsoft.AspNet.SignalR.SelfHost which depends on Microsoft.Owin.SelfHost instead of OwinHost.
It's very important that you install the Microsoft.Owin.Cors package and call app.UseCors(CorsOptions.AllowAll); like in the tutorial since the HubConfiguration.EnableCrossDomain property no longer exits.
Related
Index.cshtml
#{
ViewBag.Title = "Home Page";
}
<div id="content"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script>
<script src="~/Scripts/react/react.min.js"></script>
<script src="#Url.Content("~/Scripts/app/app.jsx")"></script>
app.jsx
var HelloWorld = React.createClass({
render: function () {
return (
<div>Hello World!!</div>
);
}
});
getting error in browser like
Failed to load resource: the server responded with a status of 500
(Internal Server Error)
Resolved this issue with following steps,
1) Make a sure installed React.Web.Mvc4 Package, it is named in NuGet manager as
ReactJS.NET
2) Install the following packages from NuGet manager,
JavaScriptEngineSwitcher.V8
JavaScriptEngineSwitcher.V8.Native.win-x64
JavaScriptEngineSwitcher.V8.Native.win-x86
3) In App_Start directory update a file ReactConfig.cs
public static void Configure()
{
JsEngineSwitcher.Current.DefaultEngineName = V8JsEngine.EngineName;
JsEngineSwitcher.Current.EngineFactories.AddV8();
}
4) Clean, Build the solution.
First, your code seems to be ok.
You can look at the url that give you error 500 on the browser.
localhost/.../.jsx
you may have something like this
If you looks at https://reactjs.net/getting-started/aspnet.html
On your project you must have reactconfig.cs
you need to configurare as in the picture
that's it.
Try to transpile your .jsx files to .js with babel or web compiler (install from VS extensions) and reference those from the view. Also, remove the second react lib:
<script src="~/Scripts/react/react.min.js"></script>
Resolved by adding this to ConfigureServices in Startup.cs:
services.AddJsEngineSwitcher(options =>
{
options.DefaultEngineName = V8JsEngine.EngineName;
options.EngineFactories.AddV8();
}
);
I have created a asp.net webapi and hosted it through azure.
This works fine when I run host/api/carparks. It also works when I run an ODATA query string
host/api/carparks?$Filter%20eq%20%27Liverpool%27
Google chrome returns the results as JSON as I want them.
The problem I am having is, I need to create a "Client" application to visualize my data. I have created a really simple for loop to return my data for testing purposes, once I have data returned I can start creating my application.
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script type="text/javascript">
function getStations() {
var town = document.getElementById("town").value;
var stationList = "<p>";
var uri = "http://localhost:38852/api/carparks?$filter=Town%20eq%20%27" + town + "%27";
$.getJSON(uri,
function (data) {
$('#here_data').empty(); // Clear existing text.
// Loop through the list of products.
$.each(data, function (key, val) {
stationList += val.Name + '<br />';
});
stationList += "</p>";
document.getElementById("here_data").innerHTML = stationList;
});
}
$(document).ready(getStations);
</script>
</head>
<body onload="getStations()">
<h1>Stations API</h1>
<p>Enter town</p>
<input type="text" id="town" value="Derby" />
<input type="button" value="Find Stations" onclick="getStations()" />
<div id="here_data">
<p>Car parks go here</p>
</div>
</body>
</html>
My client app works perfectly when I run my web api locally but when I change the getJSON request URI to my azure one (Which works in the browser!) nothing happens.
I have tried uploading my client app to azure and testing it that way but nothing :(
Is there any Azure settings that need to be changed?
Looks very much like a cross-origin issue.
The issue does not occur when you call the Service directly in your browser but only when you issue an Ajax call from a different domain (localhost vs. *.azurewebsites.net).
If you want to access your Web Api service with an Ajax call from a different domain you need to enable Cross Origin Resource Sharing (CORS).
A detailed article is found here:
http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
Quoted from the link:
Install-Package Microsoft.AspNet.WebApi.Cors
Open the file App_Start/WebApiConfig.cs. Add the following code to the
WebApiConfig.Register method.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// New code
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Next, add the [EnableCors] attribute to the TestController class:
using System.Net.Http; using System.Web.Http; using
System.Web.Http.Cors;
namespace WebService.Controllers
{
[EnableCors(origins: "http://mywebclient.azurewebsites.net", headers: "*", methods: "*")]
public class TestController : ApiController
{
// Controller methods not shown...
}
}
For the origins parameter, use the URI where you deployed the
WebClient application. This allows cross-origin requests from
WebClient, while still disallowing all other cross-domain requests.
Later, I’ll describe the parameters for [EnableCors] in more detail.
Do not include a forward slash at the end of the origins URL.
Thanks to #viperguynaz and #florian I have fixed my issue. I changed the CORS option in Azure portal. (When I first did it I didn't remove the forward slash at the end of the URL). I removed the slash and it works.
I have also used the info given by #florian to help me understand CORS more.
Thanks again
1 happy joe :)
I have been using SignalR for a while in current versions of chrome, IE and iOS Safari. I've always noticed that the "spinner" that indicates that the page is loading just continues to spin.
We are now doing some further testing and seeing that the signalR connect is just running until it times out.
/signalr/connect?transport=serverSentEvents&clientProtocol=1.5&connectionToken=XXXX&connectionData="%"5B"%"7B"%"22name"%"22"%"3A"%"22chathub"%"22"%"7D"%"5D&tid=1
In older browsers, this looks to the user as if the page has not finished loading. Moreover, when the connect finally times out, the application simply stops working (or in some cases throws an error).
I've been able to reproduce this with the tutorial from MS in both the version provided and after upgrading the tutorial to SignalR 2.2.0 and jQuery 2.1.3 via Nuget
Here's the link to the tutorial:
http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr
1) Are there best practices for making a connection to signalR such that the connection doesn't hold up the completion of the initial page rendering?
2) What about best practices for handling timeouts/reconnects?
Given MS's current tutorial doesn't handle these situations, I'm looking for more real world experiences and possibly some sample code for both scenarios.
Here's MS's tutorial as a starter.
<!DOCTYPE html>
<html>
<head>
<title>SignalR Simple Chat</title>
<style type="text/css">
.container {
background-color: #99CCFF;
border: thick solid #808080;
padding: 20px;
margin: 20px;
}
</style>
</head>
<body>
<div class="container">
<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" />
<input type="hidden" id="displayname" />
<ul id="discussion"></ul>
</div>
<!--Script references. -->
<!--Reference the jQuery library. -->
<script src="Scripts/jquery-2.1.3.min.js"></script>
<!--Reference the SignalR library. -->
<script src="Scripts/jquery.signalR-2.2.0.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 () {
// Declare a proxy to reference the hub.
var chat = $.connection.chatHub;
// Create a function that the hub can call to broadcast messages.
chat.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 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.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
</script>
</body>
</html>
I created an application with signalR references in visual studio.
Created a hub. When running application on IIS Express, everything works
fine. When I transfer it to IIS8, in firebug I see that URL's of signalR are wrong,
for instance:
http://localhost/signalr/negotiate?connectionData=......
The problem that there is a missing site name, should be:
http://localhost/MYSITE/signalr/negotiate?connectionData=......
This is the script I am using to init connection:
<script type="text/javascript">
var proxy;
$(function () {
var connection = $.hubConnection();
proxy = connection.createHubProxy('chatHub');
proxy.on('newMessage', onNewMessage);
connection.start();
$('#send').click(onSend);
});
function onNewMessage(message) {
$('#messages').append('<li>' + $('#message').val() + '</li>');
}
function onSend() {
proxy.invoke('newMessage', $().val());
}
</script>
I tried to send connection to $.hubConnection(), but then site name is getting doubled:
http://localhost/MYSITE/MYSITE/signalr/negotiate?connectionData=......
Use a tilde to refer to the application root directory when including scripts/other resources. I have a similar setup and this works for me in development and production environments:
<script src="~/Scripts/jquery.signalR-1.1.2.js" type="text/javascript"></script>
<script src="~/signalr/hubs" type="text/javascript"></script>
This is something I have been trying to figure out, but I am not sure exactly how to do it. I have a flex application that logs into facebook, but after that I can't access any of the facebook api. Right now I am using this HTML to log in:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<!-- Include support librarys first -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<script type="text/javascript" src="http://connect.facebook.net/en_US/all.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
//This example uses the javascript sdk to login before embedding the swf
var APP_ID = "[My App ID Here]";
var REDIRECT_URI = "http://apps.facebook.com/isotesthoskins/";
var PERMS = "publish_stream,offline_access"; //comma separated list of extended permissions
function init() {
FB.init({appId:APP_ID, status: true, cookie: true});
FB.getLoginStatus(handleLoginStatus);
}
function handleLoginStatus(response) {
if (response.session) { //Show the SWF
//A 'name' attribute with the same value as the 'id' is REQUIRED for Chrome/Mozilla browsers
swfobject.embedSWF("isotest.swf", "flashContent", "760", "500", "9.0", null, null, null, {name:"flashContent"});
} else { //ask the user to login
var params = window.location.toString().slice(window.location.toString().indexOf('?'));
top.location = 'https://graph.facebook.com/oauth/authorize?client_id='+APP_ID+'&scope='+PERMS+'&redirect_uri='+REDIRECT_URI+params;
}
}
$(init);
</script>
And everything logs in fine, but when I try this in the application after I am logged in, nothing happens.
Facebook.api("/me", function(response){
changeText.text = response.name;
});
I don't need to init because it was done by the javascript login, right? I might be wrong about that though.
Looks like you are calling the API using the Flex SDK.
That is not going to work, as the token is not shared between JS and Flex.
You should login on the Flex side or thunk into the JS to make the call.