I have created a sample .net core app with azure signalr service and hosted at local iis.
i) I am using below url in postman to call hub method:
http://azuresignalr:5002/api/v1-preview/hub/:NotificationHub
ii) calling with postman with below body:
{
"Message": {
"target": "BroadcastMessage",
"arguments": [
"test method"
]
}
}
iii) My c# class :
public class NotificationHub:Hub
{
public string TestConnection()
{
return "connected";
}
[HttpPost]
public void BroadcastMessage([FromBody]object message)
{
message = "Modified Message from Azure Signal R server " + message;
Clients.All.SendAsync("broadcastMessage", message);
}
}
but I am getting 404 error in postman.
Any help or document regarding its implementation is highly appreciated.
You can't do that, because no connection is established. A hub is not the same like a controller which you can use for creating restendpoints.
Normally your client should create a connection to the server, after that you can communicate over this "channel".
Why do you do this?
(For details signalr information start with https://www.asp.net/signalr)
Related
THIS IS MY CODE
This code is a Device controller that is one of the controllers I have created..
// GET: api/Devices
[HttpGet]
public async Task<ActionResult<IEnumerable<Device>>> GetDevice()
{
return await _context.Device.ToListAsync();
}
// GET: api/Devices/5
[HttpGet("{id}")]
public async Task<ActionResult<Device>> GetDevice(Guid id)
{
var device = await _context.Device.FindAsync(id);
if (device == null)
{
return NotFound();
}
return device;
}
I have deployed ASP.NET Core Web API and able to access the Get request, follow the below steps
Create an ASP.NET Core API in Visual studio
Below is the file structure
ProductsController.cs
Use post method in ProductController.cs use the below
[HttpGet]
public ActionResult<IEnumerable<Product>> GetAll() => Ok(_productService.GetAll());
[HttpGet("{id}")]
public ActionResult<Product> Get(Guid id) => Ok(_productService.Get(id));
Deployed the Web-app to Azure app service from visual studio
I have tried the Get request and got the below output
Now Goto Get ID and use the copied id there as click on send
After that you will get the value with the help of ID as below
My goal is to:
In scheduled functions - add message to SignalR
In SPA application (vue.js) subscribe to the event and call API to update the view
For now I'm trying to get anything to/from SignalR in my Function app (isolated, .net 6.0).
What I have in a function app:
[Function("negotiate")]
public HttpResponseData Negotiate(
[HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequestData req,
[SignalRConnectionInfoInput(HubName = "AdminHub", ConnectionStringSetting = "AzureSignalRConnectionString")] SignalRConnectionInfo connectionInfo)
{
_logger.LogInformation($"SignalR Connection URL = '{connectionInfo.Url}'");
var response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
response.WriteString($"Connection URL = '{connectionInfo.Url}'");
return response;
}
}
[Function("SendMessage")]
[SignalROutput(HubName = "AdminHub", ConnectionStringSetting = "AzureSignalRConnectionString")]
public SignalRMessage SendMessage(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] Microsoft.Azure.Functions.Worker.Http.HttpRequestData req)
{
return
new SignalRMessage
{
Target = "cancelToHandle",
MethodName = "cancelToHandle",
Arguments = new[] { "hello" }
};
}
[Function("SignalRTest")]
public static async Task SignalRTest([SignalRTrigger("AdminHub", "messages", "cancelToHandle", ConnectionStringSetting = "AzureSignalRConnectionString")] string message, ILogger logger)
{
logger.LogInformation($"Receive {message}.");
}
Negotiate function is not called. When should it be called?
If I call SendMessage, no error, but nothing happens in SignalR service. Should I see connections and messages there? (zero in the Metrics for now).
I've tried to create a test "emulator" client - just a console application:
var url = "http://<azureSignalRUrl>/AdminHub";
var connection = new HubConnectionBuilder()
.WithUrl(url)
.WithAutomaticReconnect()
.Build();
// receive a message from the hub
connection.On<string, string>("cancelToHandle", (user, message) => OnReceiveMessage(user, message));
await connection.StartAsync();
// send a message to the hub
await connection.InvokeAsync("SendMessage", "ConsoleApp", "Message from the console app");
void OnReceiveMessage(string user, string message)
{
Console.WriteLine($"{user}: {message}");
}
and it throws the exception ": 'A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (:80)'
I think I'm missing overall understanding of what is supposed to happen:
when should negotiate function be triggered
can I see messages that I send in Azure portal (in SignalR service)?
how can I easily receive them in testing purposes
what do parameters/properties mean (target / method name / category). Example:
SignalRTriggerAttribute has the following constructor
public SignalRTriggerAttribute(string hubName, string category, string #event, params string[] parameterNames);
and Output binding receives any custom model I create?
which settings should be set in SignalR service - for now all I set it Serverless mode + CORS
Here are the few link which will help in using SignalIr service extension in functions
Using SignalIr service extension
https://github.com/Azure/azure-functions-dotnet-worker/blob/main/samples/Extensions/SignalR/SignalRFunction.cs
Below is the sample link for triggering negotiate function
https://github.com/Log234/azure-functions-signalr-dotnet-isolated-demo/blob/main/SignalRDemo/NegotiationFunctions.cs
for complete understanding of SignalIR here is the Github and MS document.
I've been looking for an answer on Internet for days with regards to [Authorize] over the SignalR Hub class. I'm using Azure B2C to authenticate users. Everything works great when the class is not decorated with [Authorize], however I require the user to be authorized, so that I can access the Claims. All my Controllers are authenticating correctly.
[Authorize]
public class SignalRHub : Hub
{
My SignalR Service is running on Azure and started on the server as follows:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(AzureADB2CDefaults.BearerAuthenticationScheme)
.AddAzureADB2CBearer(options => Configuration.Bind("AzureAdB2C", options));
.....
services.AddSignalR().AddAzureSignalR(ConnectionString)
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseEndpoints(endpoint =>
{
.....
endpoint.MapHub<AzureSignalRSevice.SignalRHub>("/rhub");
});
}
The Debugger is indicating when the client tries to connect:
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/1.1 POST https://localhost:44301/rhub/negotiate?negotiateVersion=1 0
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler: Information: AzureADB2CJwtBearer was not authenticated. Failure message: No SecurityTokenValidator available for token: {Token}
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService: Information: Authorization failed.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler: Information: AuthenticationScheme: AzureADB2CJwtBearer was challenged.
The client code is as follows:
var connection = new HubConnectionBuilder().WithUrl("https://localhost:44301/rhub", options =>
{
options.AccessTokenProvider = () => Task.FromResult(token);
}).Build();
All the articles I have read say that the token is passed as a parameter, however in my instance it is being sent in the Authorization header correctly.
I have tried to configure the JwtBearerOptions and pass the token to context.Token, however I get the same Authentication failure.
services.Configure<JwtBearerOptions>(AzureADB2CDefaults.JwtBearerAuthenticationScheme, options =>
{
}
OnChallenge is hit when it fails with invalid_token in the context.
All the Packages are the most recent and up to date running on Core 3.1.2
I've been though many articles, this was the best so far
https://github.com/dotnet/aspnetcore/issues/10582
It doesn't use B2C Authetication though.
I have it working !
The solution is to include the Authentication Scheme
[Authorize(AuthenticationSchemes = AzureADB2CDefaults.BearerAuthenticationScheme + ", " + AzureADB2CDefaults.JwtBearerAuthenticationScheme)]
public class SignalRHub : Hub
{
}
I'm developing an application where IOT devices are connected with the Azure IOT Hub. and its realtime data can be visible on the web view. However, I'm facing an error, I'm trying to bind the data Azure function with SignalR, but when I run the application I receive the following error message.
The listener for function 'SignalR' was unable to start. Microsoft.Azure.EventHubs.Processor: Encountered error while fetching the list of EventHub PartitionIds. System.Private.CoreLib: The link address '$management' did not match any of the expected formats.
Error Description Image
I've tried everything to fix it but failed every time. I'd really appreciate if someone would help me find the solution to this problem.
Here is the script I'm using from this link
Here is my SignalR.cs class
public static class SignalR
{
[FunctionName("SignalR")]
public static async Task Run(
[IoTHubTrigger("messages/events", Connection = "IoTHubTriggerConnection", ConsumerGroup = "$Default")]EventData message,
[SignalR(HubName = "broadcast")]IAsyncCollector<SignalRMessage> signalRMessages,
ILogger log)
{
var deviceData = JsonConvert.DeserializeObject<DeviceData>(Encoding.UTF8.GetString(message.Body.Array));
deviceData.DeviceId = Convert.ToString(message.SystemProperties["iothub-connection-device-id"]);
log.LogInformation($"C# IoT Hub trigger function processed a message: {JsonConvert.SerializeObject(deviceData)}");
await signalRMessages.AddAsync(new SignalRMessage()
{
Target = "notify",
Arguments = new[] { JsonConvert.SerializeObject(deviceData) }
});
}
}
Here is my SignalRConnection.cs class
public static class SignalRConnection
{
[FunctionName("SignalRConnection")]
public static SignalRConnectionInfo Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
[SignalRConnectionInfo(HubName = "broadcast")] SignalRConnectionInfo info,
ILogger log) => info;
}
Here is my local.settings.json file
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"AzureSignalRConnectionString": "",
"MSDEPLOY_RENAME_LOCKED_FILES": 1,
"IoTHubTriggerConnection": ""
},
"Host": {
"LocalHttpPort": 7071,
"CORS": "*"
}
}
for IoTHubTriggerConnection, I'm using the connection string of iothubjohnsoncontrol (displayed in image below).
IOT Hub Keys Image
for AzureSignalRConnectionString, I'm using the connection string of signalrjohnsoncontrol (displayed in image below).
SignalR Keys Image
Could you please check if you have given EventHub Compatible name and EventHub compatible connections string from here
Please try replacing messages/events with EventHub-Compatible name and IoTHubTriggerConnection as EventHub compatible endpoint from portal.
Almost similar discussion here :
https://github.com/Azure/azure-event-hubs-dotnet/issues/103
I have a usecase like that to Push Iot data to Azure data explorer and this is what my Function looks like
Iot Hub Connection string which is EventHub compatibale
Hope this helps.
I had a Microsoft Bot Framework project that connect to Web API(that not hosted in azure).
in local host everything was work fine. but when i was deployed the Bot to an Azure app service. it's seem that the call is failed(and the Bot not return any response).
this is my post request:
public static string Post(List<ActionInputParams> data, string url)
{
using (WebClient wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "application/json;charset=utf-8";
try
{
var res = wc.UploadString(url, "POST", JsonConvert.SerializeObject(data));
return res;
}
catch (Exception ex)
{
return "error " + ex.Message;
}
}
}
my question: there is a problem to call to external Web API from Azure app service? or i just missing something?
in the "log stream" i getting a 500 error:
HTTP Error 500.0 - Internal Server Error
The page cannot be displayed because an internal server error has occurred.