Signal-R Calling another server method after receiving previous call data - .net-core

I am just reading the Microsoft tutorial on Signal-R and want to use it instead of Ajax in .Net Core, Considering the following code from Microsoft, Is there any way we can do another server call, after receiving data from the first call in the broadcastMessage function (that is defined as a javascript function)?
<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>
So that we can examine data received and conditionally initiate another call.
Or if all server calls should be put inside $.connection.hub.start().done(function () {?

You can call other methods after the message is received like this:
TypeScript example:
//Start connection with message controller
public startConnectionMessage = () => {
this.hubMessageConnection = new signalR.HubConnectionBuilder()
.configureLogging(signalR.LogLevel.Debug)
.withUrl('http://localhost:20000/notifications')
.build();
this.hubMessageConnection
.start()
.then(() => {
//after connection started
console.log('Notifications Service connection started!');
// Start the Group Listener.
this.addTranferGroupMessageListener();
// Get ConnectionID.
this.GetConnectionID();
})
.catch(err => console.log('Error while starting connection: ' + err))
}
// Group channel listner.
public addTranferGroupMessageListener = () => {
this.hubMessageConnection.on("groupMessage", (data: any) => {
console.log(data);
});
}
private GetConnectionID() {
this.hubMessageConnection.invoke("GetConnectionID")
.then((connectionID: string) => {
console.log("Recived connectionID = " + connectionID);
// call the method to register AppContextData.
this.sendApplicationContextData(connectionID)
}).catch((error: Error) => {
console.log("Error: " + error);
})
}
private sendApplicationContextData(connectionID: string) {
// add the received connectionID to the payload.
this.connection.ConnectionID = connectionID;
console.log("Sending ApplicationData.");
console.log(this.connection);
//inovke server side method to pass AppContext data.
this.hubMessageConnection.invoke("RegisterAppContextData", this.connection)
.then()
.catch((error: Error) => {
console.log("Error: " + error);
});
}
You can see that after connection is established, I invok a hub method that simply returns me a connectionID and based on connectionID I invoke another method sending that parameter. The server side hub methods are:
public string GetConnectionID()
{
return this.Context.ConnectionId;
}
public async Task RegisterAppContextData(AppContextData data)
{
// Calls the groups Manager.
await this.MapClientToGroups(data);
}

Related

Messages doesn't start to show unless sending one message in signalR

I am using signalR in my ASP.NET application, I opened the chat view in two different pages noting that I am using groups method. If I start the conversation from one of those two users, the messages doesn't showing up in the other user's page unless he sent one message.
The messages should be prevent once both users have been opened the view, please any way to solve this??
Java Script file:
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
//Disable the send button until connection is established.
document.getElementById("sendButton").disabled = true;
connection.on("ReceiveMessage", function (user, message) {
var li = document.createElement("li");
document.getElementById("messagesList").appendChild(li);
// We can assign user-supplied strings to an element's textContent because it
// is not interpreted as markup. If you're assigning in any other way, you
// should be aware of possible script injection concerns.
li.textContent = `${user} says ${message}`;
});
connection.start().then(function () {
document.getElementById("sendButton").disabled = false;
}).catch(function (err) {
return console.error(err.toString());
});
document.getElementById("sendButton").addEventListener("click", function (event) {
var user = document.getElementById("userInput").value;
var message = document.getElementById("messageInput").value;
var roomId = document.getElementById("RoomId").value;
connection.invoke("JoinRoom", roomId).catch(function (err) {
return console.error(err.toString());
});
connection.invoke("SendMessage", user, message, roomId).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});
Chat Hub:
public async Task SendMessage(string user, string message, string RoomId)
{
//await Clients.All.SendAsync("ReceiveMessage", user, message);
await Clients.Group(RoomId).SendAsync("ReceiveMessage", user, message);
}
public async Task JoinRoom(string RoomId)
{
await Groups.AddToGroupAsync(Context.ConnectionId, RoomId);
}
As our friend mentioned, the previous code was adding the user to the room when he sent a message so I modified the code and added this lines, which mean adding the user to the room as soon the connection has been accomplished.
connection.invoke("JoinRoom", roomId).catch(function (err) {
return console.error(err.toString());
Those lines have been added to the function connection.start()

sending request via Fetch API from ASP.NET razor view

I'm trying to send a request via Feth
ch API to the remote api that serves over Http. I'm getting this error on my developer tools window.
Here is js.
(function () {
login();
})();
function login() {
document.getElementById("submitBtn").addEventListener("click", function () {
sendLoginAjax();
});
};
function sendLoginAjax(userName, password) {
var form = document.getElementById("loginForm");
var params = "UserName=" + userName + "&Password" + password + "&IPs=";
// Bind the FormData object and the form element
const FD = new FormData();
FD.append("func", "Login");
FD.append("params", params);
fetch("http://isapi.mekashron.com/soapclient/soapclient.php?URL=http://isapi.icu-tech.com/icutech-test.dll%2Fwsdl%2FIICUTech", {
method: 'POST',
body: FD
}).then(result => result.json()).then(
(result) => {
console.log(result);
}
);
}
I don't know what I should do to solve it.
Have any fix?

SignalR Multiple Hub Connection .NET Core

I have 2 Hub classes,
SystemNotificationHub.cs
public class SystemNotificationHub : Hub { }
QuotationChatHub.cs
public class QuotationChatHub: Hub { }
SystemNotificationHub is defined in _Layout.cshtml so user is connected to hub continously,
and when user enters to QuotationChat.cshtml page, I want also same user to connect the QuotationChatHub, so in a simple manner I'd like the user to connect multiple hubs at the same time.
I cannot let user to connect more than 1 hub at the same time. How can I achive this?
StartUp endPoint Configurations
endpoints.MapHub<SystemNotificationHub>("/systemNotificationHub");
endpoints.MapHub<QuotationHub>("/quotationHub");
quotationChat.js
$(function () {
if (connection === null) {
connection = new signalR.HubConnectionBuilder()
.withUrl("/quotationHub")
.build();
connection.start().then(function () {
document.getElementById('sendButton').onclick = function () {
connection.invoke("BroadcastFromClient")
.catch(function (err) {
return console.error(err.toString());
});
};
});
}
});
notification.js
$(function () {
if (connection === null) {
connection = new signalR.HubConnectionBuilder()
.withUrl("/systemNotificationHub")
.build();
connection.on("Notify", function (response) {
});
connection.on("HubError", function (response) {
alert(response.error);
});
connection.start().then(function () {
connection.invoke("NotificationMethod")
.catch(function (err) {
return console.error(err.toString());
});
});
}
});
As far as I know, this issue is related with your if condition in your codes.
You have checked connection is null or not before creating the connection builder. But all two js use the same connection model.
To solve this issue, I suggest you could try to create a new connection for systemNotificationHub for example connection1 and then your code will work well.
More details, you could refer to below codes:
quotationChat.js not changed.
notification.js:
//Define a new connection1 as the new js object as connection
$(function () {
if (connection1 === null) {
connection1 = new signalR.HubConnectionBuilder()
.withUrl("/systemNotificationHub")
.build();
connection1.on("Notify", function (response) {
});
connection1.on("HubError", function (response) {
alert(response.error);
});
connection1.start().then(function () {
connection.invoke("NotificationMethod")
.catch(function (err) {
return console.error(err.toString());
});
});
}
});

API is sending no data when calling from another project & showing HTTP error 204

I have a method in an ASP.net API, which sends JWT token when it gets a Request with HTTP Get Method. On fiddler when I call this API, everything works fine; but when I call same API with another project (made in angular 8) I get HTTP 204 Error and no data.
In Angular Project I call this API on NgOnInit of my Component.
Here is code of API
[HttpGet("[action]")]
public string GetToken()
{
try
{
string key = "FIPL#321456222222222222222222222222222222222222222222222222222222222222222222"; //Secret key which will be used later during validation
var issuer = "http://localhost:1424/"; //normally this will be your site URL
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
//Create a List of Claims, Keep claims name short
var permClaims = new List<Claim>();
permClaims.Add(new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()));
//permClaims.Add(new Claim("valid", "1"));
//permClaims.Add(new Claim("userid", "1"));
//permClaims.Add(new Claim("name", "bilal"));
//Create Security Token object by giving required parameters
var token = new JwtSecurityToken(issuer, //Issure
issuer, //Audience
permClaims,
expires: DateTime.Now.AddDays(1),
signingCredentials: credentials);
var jwt_token = new JwtSecurityTokenHandler().WriteToken(token);
enter image description here
return (String)jwt_token;
}
catch (Exception ex)
{
return (string)ex.Message ;
}
}
Here is code of angular where API is called.
ngOnInit() {
let obj = JSON.parse(localStorage.getItem("Auth"));
this.DepartmentModel._iBPNo = obj.BPNo;
this.DepartmentModel._iLoginNo = obj.LoginNo;
//Here I am Calling the API to get token
this.httpServices.get("http://localhost:52484/api/Token/gettoken/", null, (data) => {
alert(JSON.stringify(data));
localStorage.setItem("Token", JSON.stringify(data));
}, (error) => {
console.log(error);
});
if (JSON.parse(sessionStorage.getItem("PDEP"))) {
this.DeptNo = JSON.parse(sessionStorage.getItem("PDEP"));
this.LoadData();
}
}
Here is link to my fiddler Page Response.
You can try subscribing to an HTTP request directly :
this.httpServices.get("http://localhost:52484/api/Token/gettoken").subscribe((data) => {
alert(JSON.stringify(data));
localStorage.setItem("Token", JSON.stringify(data));
}, (error) => {
console.log(error);
});

Send email when user is created on firestore using Cloud Functions

I'm trying to send the email verification link after the user is created on my flutter app, but the email isn't sent and in my Cloud Functions Log I'm receiving the message when I deploy:
{"#type":"type.googleapis.com/google.cloud.audit.AuditLog","status":{"code":9,"message":"FAILED_PRECONDITION"},"authenticationInfo":{"principalEmail":"*************"},"requestMetadata":{"callerIp":"186.216.140.62","callerSuppliedUserAgent":"FirebaseCLI/6.5.0,gzip(gfe),gzip(gfe)","requestAttributes":{"time":"2019-03-29T23:21:10.130Z","auth":{}},"destinationAttributes":{}},"serviceName":"cloudfunctions.googleapis.com","methodName":"google.cloud.functions.v1.CloudFunctionsService.UpdateFunction","authorizationInfo":[{"permission":"cloudfunctions.functions.update","granted":true,"resourceAttributes":{}},{"resource":"projects/pppppp-9800a/locations/us-central1/functions/sendVerificationEmail","permission":"cloudfunctions.functions.update","granted":true,"resourceAttributes":{}}],"resourceName":"projects/pppppp-9800a/locations/us-central1/functions/sendVerificationEmail","request":{"#type":"type.googleapis.com/google.cloud.functions.v1.UpdateFunctionRequest","function":{"labels":{"deployment-tool":"cli-firebase"},"eventTrigger":{"eventType":"providers/cloud.firestore/eventTypes/document.create","resource":"projects/pppppp-9800a/databases/(default)/documents/users/{userId}","service":"firestore.googleapis.com"},"sourceUploadUrl":"https://storage.googleapis.com/gcf-upload-us-central1-dc1829cf-3a07-4951-be81-1a15f892ed8d/8ea3f162-c860-4846-9064-04a855efca2f.zip?GoogleAccessId=service-73683634264#gcf-admin-robot.iam.gserviceaccount.com&Expires=1553903464&Signature=******************","name":"projects/pppppp-9800a/locations/us-central1/functions/sendVerificationEmail"}}}
My code:
exports.sendVerificationEmail = functions.firestore.document('users/{userId}').onCreate((snap, context) => {
const user = snap.data();
console.log("----------------------");
console.log("user created: " + user.uidColumn);
admin.auth().generateEmailVerificationLink(user.email).then((link) => {
console.log("**********" + link);
sendVerificationEmail(user.emailColumn, link);
return 0;
}).catch(e => {
console.log(e);
})
return 0;
});
function sendVerificationEmail(email, link) {
var smtpConfig = {
host: 'smtp.gmail.com',
port: 465,
secure: true, // use SSL
auth: {
user: 'myappemail#gmail.com',
pass: 'password'
}
};
var transporter = nodemailer.createTransport(smtpConfig);
var mailOptions = {
from: "qeaapp#gmail.com", // sender address
to: email, // list of receivers
subject: "Email verification", // Subject line
text: "Email verification, press here to verify your email: " + link,
html: "<b>Hello there,<br> click here to verify</b>" // html body
};
transporter.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
} else {
console.log("Message sent: " + response.message);
}
return 0;
});
return 0;
}
When I the the command firebase deploy I get the message functions: failed to update function sendVerificationEmail
HTTP Error: 400, Change of function trigger type or event provider is not allowed
I'm new in JS and I don't know what these erros mean
Delete your first function called sendVerificationEmail, then redeploy. It looks like you maybe initially deployed it as something other than a Firestore trigger.

Resources