SignalR cannot invoke client listening function - javascript

So I am trying to implement SignalR in a project my code is as follows:
MtHub.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
namespace HaldanMT
{
public class MtHub : Hub
{
public void RemoveResource(string message)
{
Clients.All.RemoveResource(message);
}
}
}
custom.js:
$(document).ready(function () {
$.connection.mtHub.client.removeResource = function (message) { // This is the client listener that will fire once the server invokes the message. This is not taking place
console.log("finished");
RemoveResource(message); // Function to be invoked once the signalR message has been received from the server
}
});
function RemoveSelf(message){
$.connection.hub.start()
.done(function () {
console.log("Fire SignalR");
$.connection.mtHub.server.removeResource(message); // Invoke the SingalR server function that would in turn invoke the client listening function
})
.fail(function () {
console.log("Error With SignalR");
});
}
function RemoveResource(message){
alert(message); // Display message
}
HTML:
<button onclick="RemoveSelf('This is a message');">Click Me</button>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.1.js"></script>
<script src="/signalr/hubs" type="text/javascript"></script>
<script src="~/Scripts/custom.js" type="text/javascript"></script>
Now...The correct function is fired on the button click event but the response to the client does not get invoked. If I place the SignalR invoking js function within the document ready surrounded by the onclick event of the button it works just fine. But I require the SignalR invoking js function to be fired in the function RemoveSelf(message) as other things need to take place within my code.
So my question is: Does SignalR require the server side code to be invoked via a element listener, and not within a standard function. Most examples I find are using jquery event based listeners and not a traditional function.
Thank you in advance.

The SignalR Server side code does not require invocation via element listener, but that's kind of a double-edge sword because JavaScript essentially works off events.
Your code should work exactly as it sits, but here's my code exactly and it works 100% (I don't see really many differences between our code. Could just be a typo somewhere) :
Hub
[HubName("mtHub")]
public class MtHub : Hub
{
public void RemoveResource()
{
Clients.All.RemoveResource("yo");
}
}
JavaScript (this is code inside client-side.js)
$(function() {
$.connection.mtHub.client.removeResource = function () {
alert("see it worked");
}
});
var CallIt = function() {
var connection = $.connection.mtHub;
$.connection.hub.start().done(function () {
alert("connected");
connection.server.removeResource().done(function () {
console.log("hi");
});
});
}
HTML
<h2 onclick="CallIt()">Fun Stuff</h2>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
<script src="~/Scripts/jquery.signalR-2.2.1.js"></script>
<script src="~/signalr/hubs"></script>
<script src="~/Scripts/client-side.js"></script>
If this doesn't work, can you let me know what errors you get?

Your client methods have the wrong casing for the method names, you are using "RemoveResource" and they should be "removeResource"
This is incorrect:
function RemoveResource(message){
alert(message); // Display message
}
This should fix the problem:
function removeResource(message){
alert(message); // Display message
}

Related

Some JQuery function not working after executing Blazor.Run from file blazor.server.js

I created the Blazor Server application (.net 5.0).
Added it to startup.cs services.AddServerSideBlazor().
Then integrated the Bootstrap template, and the trials with adventures began..
In the _Host.chtml file, section, I added <script src="assets/js/sb-admin-2.js"></script> that contains the following definition
$("#sidebarToggle, #sidebarToggleTop").on('click', function (e) {
$("body").toggleClass("sidebar-toggled");
$(".sidebar").toggleClass("toggled");
if ($(".sidebar").hasClass("toggled")) {
$('.sidebar .collapse').collapse('hide');
};
});
and it is associated with a part of the markup
<!-- Sidebar Toggler (Sidebar) -->
<div class="text-center d-none d-md-inline">
<button class="rounded-circle border-0" id="sidebarToggle"></button>
</div>
In the same place, in _Host.chtml file, the last directive I specified
<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
document.addEventListener("DOMContentLoaded",
function () {
Blazor.start({
logLevel: 1, // LogLevel.Debug
configureSignalR: builder => builder.configureLogging("debug") // LogLevel.Debug
});
});
</script>
Now about the problem.
With this configuration, the jQuery code defined in the .js file is not executed by the click event.
Experimentally, I found out that if you do not execute the Blazor.Start() directive, then the button with id=sidebarToggle is pressed and the jQuery defined in the .js file is executed.
when blazor.run() was not running
after execution, this handler is not there
After hitting the same issue, I came up with a simple solution. I wrapped all my DOM-Ready functions in one wrapper init function and then called it After Render of the page.
JavaScript (Layout.cshtml)
function initUi() {
(function ($) { /** sidebar event logic here **/ })(window.jquery);
}
Blazor (MainLayout.razor)
#code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("initUi");
}
}
}

Can't explicitly render Google ReCaptcha and have a callback function working

I am building a form on a website, and I am having and issue getting a function to run when the ReCaptcha is submitted. This function removes the disabled attribute on the submit button.
There is also a chance that multiple forms may be used on one page so I implemented the following solution to allow multiple captacha forms on one page:
https://stackoverflow.com/a/33535769/2506219
It seems I can either allow multiple ReCaptcha forms or have the submit button allowed but not both.
Here is the code:
HTML
<div class="g-recaptcha" data-callback="verifyCallback"></div>
<script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>
JavaScript
<script>
var CaptchaCallback = function() {
$('.g-recaptcha')
.each(function(index, el) {
grecaptcha.render(el, { 'sitekey': 'XXXX' });
});
};
function verifyCallback() {;
$('#submitBtn').prop('disabled', false);
}
</script>
Thank-you.
Worked it out!
I needed to call the function from the callback, having it in the HTML doesn't work
var CaptchaCallback = function() {
$('.g-recaptcha')
.each(function(index, el) {
grecaptcha.render(el, { 'sitekey': 'XXXX', 'callback': verifyCallback });
});
};

SignalR server to client method not working

Based on various resources the signalr code should be working, but I can't make it to send notifications from the server to client. Here is html/javascript part:
<script src="/Scripts/jquery-1.6.4.min.js"></script>
<script src="/Scripts/jquery.signalR-2.2.1.min.js"></script>
<script src="/signalr/js"></script>
<script type="text/javascript">
$(function () {
var cHub = $.connection.cHub;
$.connection.hub.logging = true;
cHub.client.sendMessage = function (content) {
$("#container-hub").append($("<p />").html(content));
};
$.connection.hub.start().done(function() {
$('[id$=bGo]').click(
function() {
cHub.server.send('Sync process started');
});
});
});
</script>
<div id="container-hub" style="background: red; height: 100px; width: 100%;"></div>
Hub.cs class:
using Microsoft.AspNet.SignalR;
namespace CMS.Objects
{
public class CHub : Hub
{
public void Send(string message)
{
// Call the broadcastMessage method to update clients.
Clients.All.sendMessage(message);
}
}
}
Startup.cs class:
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(CMS.CStartup))]
namespace CMS
{
public class CStartup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
And here is how I am calling the method sendMessage method:
private void ShowMessage(string message)
{
var clients = GlobalHost.ConnectionManager.GetHubContext<CHub>().Clients;
clients.All.sendMessage(message);
}
When the button bGo is clicked the message is getting appended to the container-hub div, but nothing when I call sendMessage method.
EDIT
Some additional findings; when I call sendMessage from within the OnConnected method it works:
public override Task OnConnected()
{
Clients.All.sendMessage("Connection Initialised");
return base.OnConnected();
}
After spending some decent time to investigate the problem I have finally found the solution. Not 100% sure, but I think the problem was with using the UpdatePanel on the page. Wrapped signalR javascript code to Sys.Application.add_load instead of using jQuery's $(function () { and it started working.
The reason I mentioned that I am not 100% sure is that the UpdatePanel with the ScriptManager has been removed multiple times giving no results before posting the question.

Client side event that fires after ASPxClientGridView.ApplyFilter performs its work

This link explains how to handle it on the server side via the ASPxGridView.AfterPerformCallback event:
http://www.devexpress.com/Support/Center/p/Q274366.aspx
How can I handle it on the client side?
I am working on a custom server control and I have this client side function on my control:
applyFilterToGridView: function () {
this.theGridView.ApplyFilter(this.filterCondition);
this.filterAppliedEvent();
}
Because ApplyFilter does a callback, this.filterAppliedEvent() is not called at the right time which should be after the filtering is complete. this.filterAppliedEvent() is a client side function.
This event is fired after the filter is applied:
protected void theGridView_AfterPerformCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewAfterPerformCallbackEventArgs e)
{
if (e.CallbackName == "APPLYFILTER")
{
}
}
Is there some way to to tell the client to call filterAppliedEvent from the AfterPerformCallback event?
I would prefer to be able to run this.filterAppliedEvent() after AfterPerformCallback on the client side if possible.
Thanks in advance.
EDIT ( Solution thanks to Filip ):
C#:
protected void theGridView_AfterPerformCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewAfterPerformCallbackEventArgs e)
{
if (e.CallbackName == "APPLYFILTER")
{
ASPxGridView gv = sender as ASPxGridView;
gv.JSProperties["cp_FilterApplied"] = "true";
gv.JSProperties["cp_VisibleRowCount"] = gv.VisibleRowCount;
}
}
theGridView.ClientSideEvents.EndCallback = "function(s,e){"theGridView.theGridView_OnEndCallback(s, e);}";
JS:
theGridView_OnEndCallback: function (s, e) {
if (s.cp_FilterApplied) {
if (s.cp_FilterApplied.indexOf('true') != -1) {
this.adjustGridViewSize();/*Uses visible row count.*/
delete s.cp_FilterApplied;
}
}
}
In theGridView_AfterPerformCallback add entry to JSProperties collection, e.g. cp_FilterApplied.
Add EndCallback client side event handler.
In EndCallback handler execute this.filterAppliedEvent() if cp_FilterApplied exists.
Delete that property so that subsequent callback doesn't execute filterAppliedEvent method.
Look at my answer to this question for code example.
It's really the same problem, just set js property in theGridView_AfterPerformCallback instead of ASPxGridView1_RowUpdated and adjust names/js code to your needs.

Javascript pageLoad not executing in a master page

What causes the following pageLoad to not execute in a master page? The first alert executes as expected, but the pageLoad function is not being invoked. How can I use the function within a master/content page?
<script type="text/javascript">
alert('test');
function pageLoad(sender, args) {
alert('pageLoad');
}
</script>
I'm assuming a script manager control is present in your master page? I'm not sure if the client-side pageLoad method is only called on the initial page load. I do know that if you're looking for ajax postback page load hooks, try the client-side PageRequestManager.
MAke sure that the code below is place inside the script manager.
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<script type="text/javascript" >
(function() {
var prm = Sys.WebForms.PageRequestManager.getInstance();
if (prm)
{
prm.add_endRequest(
function (sender, args) {
// do your stuff
// Handle a weird occurence where an error is returned but the error code is 0, i.e. no error.
if(args.get_error() && args.get_error().name === 'Sys.WebForms.PageRequestManagerServerErrorException')
{
args.set_errorHandled(args._error.httpStatusCode == 0);
}
});
}
})();
</script>
<%-- Other markup --%>
</asp:ScriptManager>
Window Load Event
window.onload = function() {
alert('pageLoad');
}
Self Executing Function
(function() {
alert('pageLoad');
})();

Categories

Resources