How to manually reconnect Blazor server App? - signalr

I have customized Blazor Server SignalR settings like show below here.
What are my options to reconnect, without forcing reload of page ?
<button id="refreshButton" class="btn btn-info ms-1" style="display:none" onclick="Reconnect()">Refresh Page</button>
<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
function Reconnect()
{
console.log("attempting to reconnect");
window.location.reload(true); //this works but looking for better option
}
window.addEventListener('beforeunload', function () {
Blazor.defaultReconnectionHandler._reconnectionDisplay = document.getElementById("refreshButton");
});
window.addEventListener('pagehide', () => {
Blazor.disconnect();
});
Blazor.start({
reconnectionHandler: {
onConnectionDown: (options, error) => {
document.getElementById("refreshButton").style="";
console.error("Connection is down " + error)
} ,
onConnectionUp: () => {
console.log("Up, up, and away!")
document.getElementById("refreshButton").style="display:none";
}
}
});
</script>

Related

SignalR in ASP.NET empty website not working

I am very new to the term SignalR . I was try to configure the signalR into my empty website and Added following code.
In App_Code
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(Super.App_Code.Startup))]
namespace Super.App_Code
{
public class Startup
{
public static void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
and the hub class Inside App_Code
namespace Super.App_Code
{
[HubName("toastHub")]
public class ToastHub : Hub
{
public void BroadcastToast(string type ,string msg)
{
Clients.All.sendToast(type , msg);
}
}
}
and in Default.aspx
<head runat="server">
<title></title>
<link rel="stylesheet" href="content/toastr.min.css" />
<script src="Scripts/jquery-1.6.4.js" type="text/javascript"></script>
<script src="Scripts/jquery.signalR-2.4.1.js" type="text/javascript"></script>
<script src="Scripts/toastr.min.js" type="text/javascript"></script>
<script src="signalr/hubs" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#SuccessLink").click(function () {
console.log("Success Click");
$.connection.toastHub.client.broadcastToast('success', 'you have done');
});
$("#ErrorLink").click(function () {
console.log("Error Click");
$.connection.toastHub.client.broadcastToast("error", "you have not done");
});
$.connection.hub.start().done(function () {
console.log('SignalR connected');
})
.fail(function (data) {
console.log('SignalR failed to connect: ' + data);
});
$.connection.toastHub.client.sendToast = function (type, msg) {
console.log("sendToast Called");
toastr[type](msg);
};
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<a id="SuccessLink" style="color: lightgreen">Success Toast</a><br />
<a id="ErrorLink" style="color: red">Error Toast</a>
</div>
</form>
</body>
</html>
but when i run my website the javascript console says this when click on one of the tag
SignalR connected
Default.aspx:20 Success Click
Default.aspx:21 Uncaught TypeError: $.connection.toastHub.client.broadcastToast is not a function
at HTMLAnchorElement.<anonymous> (Default.aspx:21)
at HTMLAnchorElement.handle (jquery-1.6.4.js:3001)
at HTMLAnchorElement.eventHandle (jquery-1.6.4.js:2635)
Am i doing anything wrong please help me any help would be greatful .i am totally new to SignalR .
signalr/hub
if (typeof ($.signalR) !== "function") {
throw new Error("SignalR: SignalR is not loaded. Please ensure jquery.signalR-x.js is referenced before ~/signalr/js.");
}
var signalR = $.signalR;
function makeProxyCallback(hub, callback) {
return function () {
// Call the client hub method
callback.apply(hub, $.makeArray(arguments));
};
}
function registerHubProxies(instance, shouldSubscribe) {
var key, hub, memberKey, memberValue, subscriptionMethod;
for (key in instance) {
if (instance.hasOwnProperty(key)) {
hub = instance[key];
if (!(hub.hubName)) {
// Not a client hub
continue;
}
if (shouldSubscribe) {
// We want to subscribe to the hub events
subscriptionMethod = hub.on;
} else {
// We want to unsubscribe from the hub events
subscriptionMethod = hub.off;
}
// Loop through all members on the hub and find client hub functions to subscribe/unsubscribe
for (memberKey in hub.client) {
if (hub.client.hasOwnProperty(memberKey)) {
memberValue = hub.client[memberKey];
if (!$.isFunction(memberValue)) {
// Not a client hub function
continue;
}
// Use the actual user-provided callback as the "identity" value for the registration.
subscriptionMethod.call(hub, memberKey, makeProxyCallback(hub, memberValue), memberValue);
}
}
}
}
}
$.hubConnection.prototype.createHubProxies = function () {
var proxies = {};
this.starting(function () {
// Register the hub proxies as subscribed
// (instance, shouldSubscribe)
registerHubProxies(proxies, true);
this._registerSubscribedHubs();
}).disconnected(function () {
// Unsubscribe all hub proxies when we "disconnect". This is to ensure that we do not re-add functional call backs.
// (instance, shouldSubscribe)
registerHubProxies(proxies, false);
});
proxies['toastHub'] = this.createHubProxy('toastHub');
proxies['toastHub'].client = { };
proxies['toastHub'].server = {
};
return proxies;
};
signalR.hub = $.hubConnection("/signalr", { useDefaultPath: false });
$.extend(signalR, signalR.hub.createHubProxies());
}(window.jQuery, window));
Something is not correctly initialized with your SignalR project, I guess accessing a hubContext should have a Dependency Injector in your startup.cs. But doing context injection with DI for SignalR is an advanced level problem.
However, please try this minimal sample, if it's working for you: https://github.com/bezzad/MVC-SignalR-2
Looks to me like you need to just change the calls to broadcastToast from client to server. As that method is in the Hub and so requires the server instead.
$.connection.toastHub.client.broadcastToast
To
$.connection.toastHub.server.broadcastToast

File upload not working with angular and webmethod

I am basically trying to upload a file using angular and a webmethod.
I took the code from this blog but it does not work. The request is successfull as seen from fiddler but the web method never gets invoked.
Am I doing something wrong?
Following is my code .
angular
.module('loader', ['ui.router', 'ui.bootstrap', 'ui.filters'])
.controller('loader-main', function($rootScope, $scope, WebServices) {
$scope.uploadNewFile = function() {
WebServices.uploadFile($scope.myfile);
}
}).factory('WebServices', function($rootScope, $http) {
return {
postFile: function(method, uploadData) {
var uploadUrl = "myASPXPAGE.aspx/" + method;
return $http.post(uploadUrl, uploadData, {
transformRequest: angular.identity,
headers: {
'Content-Type': undefined
}
}).success(function(data) {
///Control reaches here but never hits the server method
});
},
uploadFile: function(filedata) {
var fd = new FormData();
fd.append('file', filedata);
return this.postFile("UploadFile", fd);
}
};
}).directive('fileModel', ['$parse',
function($parse) {
return {
restrict: 'A',
link: function($scope, element, attr) {
var model = $parse(attr.fileModel);
var modelSetter = model.assign;
element.bind('change', function() {
$scope.$apply(function() {
modelSetter($scope, element[0].files[0]);
});
});
}
}
}
]);
<div class="row">
<div class="col-xs-5">
<div class="col-xs-4">Browse to File:</div>
<div class="col-xs-1">
<input type="file" id="uploadFile" class="btn btn-default" file-model="myfile" />
<input type="button" class="btn btn-primary" value="Load File" data-ng-click="uploadNewFile()" />
</div>
</div>
</div>
And here is my WebMethod
[WebMethod]
public static string UploadFile()
{
System.Diagnostics.Debugger.Break();
return "Done";
}
Figured it out. You cannot have Content-Type as multipart/form-data in webmethods. Instead created a HttpHandler to upload the file and everything works just fine.

Working example of recaptcha in meteor

Can anyone help with a working example of recaptcha in meteor without using iframes?
I cannot make the recaptcha scripts run even when I try to run them from the client.js using jquery append.
After doing some investigations I found that I had to manually integrate the reCaptcha.
The client side code:
HTML:
<form id="mySecuredForm" novalidate>
<!-- labels and inputs here -->
<div class="row">
<div id="captcha-container">
<div id="rendered-captcha-container">loading...</div>
</div>
</div>
<div class="row">
<button type="submit" id="submit" class="submit-button">Submit</button>
</div>
</form>
JS
if (Meteor.isClient) {
Template.myTemplate.rendered = function() {
$.getScript('http://www.google.com/recaptcha/api/js/recaptcha_ajax.js', function() {
Recaptcha.create('add_your_public_key_here', 'rendered-captcha-container', {
theme: 'red',
callback: Recaptcha.focus_response_field
});
});
}
Template['myTemplate'].events({
'submit form#mySecuredForm': function(event) {
event.preventDefault();
event.stopPropagation();
var formData = {
captcha_challenge_id: Recaptcha.get_challenge(),
captcha_solution: Recaptcha.get_response()
//add the data from form inputs here
};
Meteor.call('submitMySecuredForm', formData, function(error, result) {
if (result.success) {
//set session vars, redirect, etc
} else {
Recaptcha.reload();
// alert error message according to received code
switch (result.error) {
case 'captcha_verification_failed':
alert('captcha solution is wrong!');
break;
case 'other_error_on_form_submit':
alert('other error');
break;
default:
alert('error');
}
}
});
}
Server side code
function verifyCaptcha(clientIP, data) {
var captcha_data = {
privatekey: 'add_private_key_here',
remoteip: clientIP
challenge: data.captcha_challenge_id,
response: data.captcha_solution
};
var serialized_captcha_data =
'privatekey=' + captcha_data.privatekey +
'&remoteip=' + captcha_data.remoteip +
'&challenge=' + captcha_data.challenge +
'&response=' + captcha_data.response;
var captchaVerificationResult = null;
var success, parts; // used to process response string
try {
captchaVerificationResult = HTTP.call("POST", "http://www.google.com/recaptcha/api/verify", {
content: serialized_captcha_data.toString('utf8'),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': serialized_captcha_data.length
}
});
} catch(e) {
return {
'success': false,
'error': 'google_service_not_accessible'
};
}
parts = captchaVerificationResult.content.split('\n');
success = parts[0];
if (success !== 'true') {
return {
'success': false,
'error': 'captcha_verification_failed'
};
}
return {
'success': true
};
}
Meteor.methods({
"submitMySecuredForm": function(data) {
//!add code here to separate captcha data from form data.
var verifyCaptchaResponse = verifyCaptcha(this.connection.clientAddress, data);
if (!verifyCaptchaResponse.success) {
console.log('Captcha check failed! Responding with: ', verifyCaptchaResponse);
return verifyCaptchaResponse;
}
console.log('Captcha verification passed!');
//!add code here to process form data
return {success: true};
});
There is also the possibility to listen to the post event on the server side. The http calls can be done synchronous as above or asynchronous with fibers/futures.
Server side http call to google API was inspired from:
https://github.com/mirhampt/node-recaptcha/blob/master/lib/recaptcha.js

Have Meteor update a string every second

This is Meteor's default HTML:
<head>
<title>random-test</title>
</head>
<body>
{{> hello}}
</body>
<template name="hello">
<h1>Hello World!</h1>
{{greeting}}
<input type="button" value="Click" />
</template>
And this is Meteor's default Javascript code:
if (Meteor.isClient) {
Template.hello.greeting = function () {
return "Welcome to random-test.";
};
Template.hello.events({
'click input' : function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
I changed the Javascript so I could have it update {{greeting}} every second:
if (Meteor.isClient) {
Template.hello.greeting = "hi";
Meteor.setInterval(function() {
Session.set("greeting", "hello");
console.log("Hi");
}, 1000);
Template.hello.events({
'click input' : function () {
// template data, if any, is available in 'this'
if (typeof console !== 'undefined')
console.log("You pressed the button");
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
It is console.logging "hi" every second. However, it is either not updating the value of greeting or Session.get isn't updating its value as it should (according to Meteor docs).
You need to return the Session.get('greeting') in a helper:
Template.hello.greeting = function() {
return Session.get('greeting');
}
Having Template.hello.greeting = "hi"; makes the template not dependent on Session.get('greeting'), so changes to that "session variable" won't cause any re-renderings. Or what do you expect to happen?

Partial View via Ajax all Javascript References are broken

i have a PartialView in my MVC Appliction, which returns my View if there are any Errors in the ModelState. In the _Layout site are many javascript ( jQuery, JQuery.validate, ... ) references which i use in the partai view.
Here the Code:
Javascript submit:
$(function () {
$('form').submit(function (e) {
e.preventDefault();
if ($('form').valid()) {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
if (!result.Success) {
$('#formcontent').html(result); // Show PartailView with Validationmessages
}
else {
}
}
});
}
});
});
Parent Site:
<div id="formcontent" class="tc-form">
#{ Html.RenderPartial( "_ConfigurationPartial", Model ); }
</div>
Partial View:
#model SettingsViewModel
#{ Layout = null; }
#using( Html.BeginForm() )
{
#Html.ValidationSummary( false, SystemStrings.ValidationSummaryMessage )
<ol class="last">
<li class="row">
#Html.LabelFor( m => m.PasswordMinimumLength )
#Html.EditorFor( m => m.PasswordMinimumLength )
#Html.ValidationMessageFor( m => m.PasswordMinimumLength, "*" )
</li>
<li class="row">
#Html.LabelFor( m => m.PasswordNeverExpires )
#Html.EditorFor( m => m.PasswordNeverExpires )
#Html.ValidationMessageFor( m => m.PasswordNeverExpires, "*" )
</li>
<li class="row">
#Html.LabelFor( m => m.PasswordExpirationValue )
#Html.EditorFor( m => m.PasswordExpirationValue )
#Html.ValidationMessageFor( m => m.PasswordExpirationValue, "*" )
#Html.EditorFor( m => m.PasswordExpirationUnit )
#Html.ValidationMessageFor( m => m.PasswordExpirationUnit, "*" )
</li>
</ol>
<div class="tc-form-button">
<input type="submit" value="Save" title="Save" class="t-button t-state-default" />
#Html.ActionLink( "Cancel", "Configuration", "System", null, new { #class = "t-button" } )
</div>
}
<script type="text/javascript">
jQuery(document).ready(function () {
$('#PasswordNeverExpires').change(function () {
setState($(this).is(':checked'));
});
});
function setState(isDisabled) {
if (isDisabled) {
// ...
}
else {
// ...
}
}
Controller:
[HttpPost]
public ActionResult Configuration( SettingsViewModel model )
{
if( !ModelState.IsValid )
{
this.PopulateViewData();
return PartialView( "_ConfigurationPartial", model );
}
else
{
// ... do save
return Json( new { Success = true }, JsonRequestBehavior.AllowGet );
}
}
If the partialView is load via ajax all my Javascript are broken. There is no second ajax submit, it is a normal post. So the partialvew is rendered without any layout informations. It seems that all the javascript references are not found. Is there any way to refresh the DOM or something else? Must i have all the javascript in the PartailView? What is the correct way for this?
Regards
This code is outside of Partial View:
<script type="text/javascript">
jQuery(document).ready(function () {
var oldvalue=$('#PasswordNeverExpires').val();
$('#PasswordNeverExpires').change(function(){
oldvalue=$(this).val();
})
});
</script>
Then I change your code in PartialView a little:
jQuery(document).ready(function () {
if($('#PasswordNeverExpires').val()!=oldvalue){
//your scripts put here.
}
});
The above code was not tested but It should work.
Your problem is that you bind the submit event to the form when the page is loaded for the first time. When you reload the form through ajax you need to rebind the submit event to your new form.
You can also live bind the event, which you do only once
$("form").live("submit", function(e) {
e.preventDefault();
if ($('form').valid()) {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function(result) {
if (!result.Success) {
$('#formcontent').html(result); // Show PartailView with Validationmessages
}
else {}
}
});
}
});
read more here

Resources