How to integrate ASP.NET 5 with signalr - signalr

I'm trying to make an ASP.NET 5 web app using SignalR. I've created an empty web app, I've added an index.html page with some contents but I can't integrate SignalR. So far, in order to use SignaR, I've carried out the following step:
1) I've added the following dependency in the project.json file:
"Microsoft.AspNet.SignalR.Server": "3.0.0-rc1-final"
2) In the Startup class, I've added
services.AddSignalR();
to the ConfigureServices method, and
app.UseSignalR();
to the Configure method.
3) I've added to the project a class deriving from Microsoft.AspNet.SignalR.Hub and inserted a public method into it.
After this, in index.html I've added the logic trying to access the method but when I launch the app firefox console says
Error: $ is not defined
Here is the javascript code:
<script>
var app = angular.module("myapp", []);
app.controller("myctr", function ($scope) {
$scope.input = "";
$scope.output = "";
$.connection.myHub1.client.JSMet1 = function (x) {
$scope.$apply(function () {
$scope.output = x;
});
};
$scope.AggiornaTesto = function () {
$.connection.myHub1.server.cSMet1($scope.input);
};
$.connection.hub.start();
});
</script>
As you can see I also use AngulaJS.

Error: $ is not defined
Its because you haven't added jQuery reference to your page, please read this article from Microsoft, it will step by step demonstrate you how to implement SingnalR with ASP.NET MVC projects.

Related

Lightswitch HTML - chat application upgrade

I wanted to know if anyone has given this a go and got it working?
http://lightswitchhelpwebsite.com/Blog/tabid/61/EntryId/182/Connecting-To-SignalR-With-LightSwitch-HTML-Client.aspx
Basically my issue is i cant open the file to begin with, whether it be Visual Studio 2012, 2013 or 2015, so I have followed the guide and used the files from the downloaded project for this error message to occur:
which is caused by this line under the sendmessage_execute function:
chat.server.send(screen.displayname, screen.message);
im hoping someone has got this working and could point out anything different from the user guide, heres what I have used/done:
Under the PROJECT.Server I have:
created a folder called SignalR with the file ChatHub.cs in
added the json2.js (both) and signalR (both) files to the scripts
folder
Under the Project.HTMLClient
added the json2.js (both) and signalR (both) files to the scripts
folder
referenced the scripts including the localhost in the default.htm file
Created a screen. called ChatScreen and added all the referenced code here from the guide online (3 strings and 1 button)
i also installed the Nu-GET as instructed
More research for this was required, I found this post which explains how to do it a lot easier and in an application for both 2013/2015, works a treat and can easily be adapted for other screens
https://blogs.msdn.microsoft.com/rmattsampson/2013/03/14/asp-net-signalr-and-lightswitch-vs-2012-update-2-vs-2013-and-later/
I have also managed to edit there block of code to list all messages in a string, this is not stored and refresh's each time but its now possible to have a conversation while on the same screen
var string;
myapp.ChatScreen.created = function (screen) {
string = "";
$(function () {
chat = $.connection.chatHub;
chat.client.broadcastMessage = function (message) {
string = string + message + ";";
screen.updates = string.split(';').join("\r\n");
console.log(string.split(';').join("\r\n"))
};
$.connection.hub.start()
.done(function () {
})
.fail(function () {
alert("Could not Connect! - ensure EnableCrossDomain = true");
});
});
};
It would be better practice using an array and displaying it this way but the code above demonstrates it works

Running Angular and Web API in Visual Studio with IIS Express

I have a Visual Studio 2013 solution with a Web API project and a Web UI project (using Angular). I am using IIS Express.
Is there a way to set these projects up so that the Angular code can call the Web API project without hard-coding in the localhost and port number?
return $http.get("http://localhost:1561/api/products")
.then(function (response) {
return response.data;
});
If I hard-code localhost:1561 instead of just using the "/api/products" style I have to manually change the code before deploying to production and change it back to run it during development.
Is there an easier way?
Thanks!
var rootPath;
if (location.hostname === 'localhost') {
rootPath = 'http://localhost:1561';
} else {
rootPath = 'http://' + location.hostname;
}
return $http.get(rootPath + '/api/products')
.then(function (response) {
return response.data;
});
I actually wrote a simple utility method that returns the absolute URL so in your code you just have to type the relative URL. Below is this method which you should be able to call from your JS passing the relative URL (i.e. /api/products) or by converting it into a helper extension method...
// Code
public static string ToAbsoluteUrl(string relativeUrl)
{
if (string.IsNullOrEmpty(relativeUrl))
return relativeUrl;
if (HttpContext.Current == null)
return relativeUrl;
if (relativeUrl.StartsWith("/"))
relativeUrl = relativeUrl.Insert(0, "~");
if (!relativeUrl.StartsWith("~/"))
relativeUrl = relativeUrl.Insert(0, "~/");
var url = HttpContext.Current.Request.Url;
var port = url.Port != 80 ? (":" + url.Port) : String.Empty;
return String.Format("{0}://{1}{2}{3}",
url.Scheme, url.Host, port, VirtualPathUtility.ToAbsolute(relativeUrl));
}
From what I understand, it is not possible to do what I was attempting to do. Here are the options:
1) Use IIS on the local machine. That way you can set up the paths/virtual directories as necessary. This also makes it easier to call the API from other browsers during debugging. Note: This does require that you then run Visual Studio in admin mode from this point forward.
2) Put the two projects into one. For me this was not a valid option because I am need to deliver the UI code completely separate from the API code.
Hope this helps others trying to work with Angular and Web API.

How to do coldfusion mapping in application level

I have below directory structure -
rootFolder
---CFC (contains all cfc file)
---SERVICES (contains all service file)
application.cfc
I have created one service named (userService.cfc) which have the below script
import services.userService;
component accessors="true" alias="services.userService"
{
remote userService function init()
{
return This;
}
remote any function getUser()
{
var userObj = new cfc.sessionUser();
return userObj;
}
}
If i call this service from inside the application, this is working fine
Again if i am trying to call it from outside the application, need to change this statement as below and again it is working fine.
import rootFolderName.services.userService;
component accessors="true" alias="rootFolderName.services.userService"
{
remote userServicefunction init()
{
return This;
}
remote any function getUser()
{
var userObj = new rootFolderName.cfc.sessionUser();
return userObj;
}
}
But If i put this code on another rootFolder suppose on "rootFolderName1" name i have to changed all the place where i used the rootFolderName. I got one solution by CFADMIN folder mapping on server level. but i want it on application level.
Can we configure it on Application.cfc? I have used Mappings also but that is not working.
Actually i have two separate application one flex application which is trying to access the second application services remotely. second application have cfc and sevices.
Please help on this.
I would review Ben Nadel's post on the use of ExpandPath() in writing app level CF mappings
http://www.bennadel.com/blog/2519-ExpandPath-Works-With-ColdFusion-s-Per-Application-Mappings.htm

signalR script reference?

All the signalR examples shows
<script src="/signalr/hubs" type="text/javascript"></script>
without explainning enough what is it used for .
For the Html page it is a location of folder . and there is no script there.
Why and how this line is being used ?
The /signalr/hubs page is a JavaScript file that is auto generated by SignalR which contains generated hub proxies for every hub in your SignalR project.
For instance (got this from http://shootr.signalr.net/signalr/hubs) lets take a look at the code snippet.
proxies.h = this.createHubProxy('h');
proxies.h.client = { };
proxies.h.server = {
changeViewport: function (viewportWidth, viewportHeight) {
return proxies.h.invoke.apply(proxies.h, $.merge(["changeViewport"], $.makeArray(arguments)));
},
fire: function () {
return proxies.h.invoke.apply(proxies.h, $.merge(["fire"], $.makeArray(arguments)));
},
...
"this" refers to the hub connection, or rather $.connection.hub. So we're essentially saying proxies.h = $.connection.hub.createHubProxy('h');
Now 'h' is a hub on the server See https://github.com/NTaylorMullen/ShootR/blob/master/ShootR/ShootR/Server/GameHub.cs, more specifically look at the hub name attribute.
Next we have proxies.h.client; this is the endpoint for where users are able to declare their client side functions that will be invoked from the server.
We then have proxies.h.server, this references all the public hub methods on the GameHub.cs. So some of the functions are changeViewport, and fire. This code is auto generated on the server to represent each of your hubs.
Lastly at the end of the signalr/hubs file we extend all of the dynamically created hubs onto the $.connection object so users can then access them via
var myGameHub = $.connection.h;
Hope this helps!

Mock/Fake ASP.NET Service References and QUnit testing

I'm just getting into QUnit testing, and have run into a problem on my first page :S
We use ASP.NET Service References to take advantage of async data loading on html pages, creating a reference to a web service in the same project. What ASP.NET does behind the scenes (ScriptManager control) is create a JS file representing the service methods and handling all the AJAX calling.
Using this, I have a page that calls one of these methods in the document.ready jQuery event. I'm now trying to test against this js file using QUnit, but avoid having the js file call the actual web service and use a mock service instead. Here's what I have for an attempt so far:
main.js (production code file)
var Service;
$(document).ready(function () {
//class definition created by asp.net behind the scenes
Service = MyProject.services.DataService;
//the method that calls the service
LoadData();
});
function LoadData() {
Service.GetData(OnGetDataSuccess, OnGetDataFailure);
}
main-test.js (test QUnit code, main.js is referenced in this page)
function SetupMockService(result) {
Service = { "GetData": function (OnSuccess, OnFailure) {
GetDataCalled = true;
OnSuccess(result);
//this is required in an asyncTest callback, I think?
start();
}, "GetDataCalled": false};
}
$(document).ready(function () {
module("LoadData");
asyncTest("LoadData should call GetData from service", function () {
SetupMockService(result);
LoadData();
equals(Service.GetDataCalled, true, "GetData has been called");
});
This test fails. The LoadData method is called as part of the original (main.js) document.ready event, so it still calls the production web service, and the tests fail because that GetDataCalled variable is never set (or defined in production). Am I doing the asyncTest wrong? (This is my first day with QUnit, so I could very well be)
The other way I can see this working is if I can override the main.js document.ready event, but I'm not quite sure on how to do that. I also don't want to add "testEnvironment == true" checks to my production main.js code.
Turns out I had things a bit backwards, as well as one obvious mistake. Here's the resulting code that works
main-tests.js
//the test itself isn't calling async methods, so it doesn't need to use asyncTest
test("LoadData should call GetData from service", function () {
SetupMockService();
LoadData();
equals(Service.GetDataCalled, true, "GetData has been called");
});
function SetupMockService() {
//redefining the Service variable specified in main.js with a mock object
Service = { "GetData": function (OnSuccess, OnFailure) {
//I forgot the "this" part... d'oh!
this.GetDataCalled = true;
}, "GetDataCalled": false
};
}
This still doesn't fix the issue with the original main.js's document.ready code being executed, but I'll figure that out.

Resources