A signalr API (.NET 6) is hosted on IIS with "web garden" mode. Client frequently closes a connection with the following message: "System.Net.Http.HttpRequestException: Response status code does not indicate success: 404 (Not Found)."
When IIS config is changed not to use webgarden (max worker processes is set to 1) - error does not occur.
I have read that redis backplane would be a solution in such case (webgarden) but inlcuding it in my project did not help - the same error message occurs in same scenarios.
Here is my sample code from the Startup:
services.AddSignalR(options =>
{
options.EnableDetailedErrors = true;
})
.AddHubOptions<MyHub>(options =>
{
options.AddFilter<MyFilter>();
})
.AddNewtonsoftJsonProtocol()
.AddStackExchangeRedis(o =>
{
o.ConnectionFactory = async writer =>
{
var config = new ConfigurationOptions
{
AbortOnConnectFail = false
};
config.EndPoints.Add(IP_ADDR, PORT_NO);
config.DefaultDatabase = DEFAULT_DB;
var connection = await ConnectionMultiplexer.ConnectAsync(config, writer);
connection.ConnectionFailed += (_, e) =>
{
Console.WriteLine("Connection to Redis failed.");
};
if (!connection.IsConnected)
{
Console.WriteLine("Did not connect to Redis.");
}
else
{
Console.WriteLine("Connected to Redis.");
}
return connection;
};
});
Did I miss somethig in my code? Or maybe it is about IIS configuration?
Related
I newbe to Signal R Core here. i am try to connect to a Signal R client to A Serverless hub. In my example for now i just want to create multiple instances of en get a connection every time a new one is connected.
static async Task Main(string[] args)
{
var client = new HttpClient();
var response = await client.GetAsync("http://localhost:7071/api/negotiate?userid=1");
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
var d = JsonConvert.DeserializeObject<dynamic>(responseBody);
string urlString = Convert.ToString(d.Url);
var connection = new HubConnectionBuilder()
.ConfigureLogging(logging =>
{
// Set the log level of signalr stuffs
logging.AddFilter("Microsoft.AspNetCore.SignalR", LogLevel.Debug);
})
.WithUrl(urlString, options => options.AccessTokenProvider = () => Task.FromResult(Convert.ToString(d.AccessToken)))
.Build();
connection.On<NewConnection>("newConnection", c => OnReceiveMessage(c));
await connection.StartAsync();
// while (connection.State == HubConnectionState.Connected)
// {
// }
Console.Read();
}
private static void OnReceiveMessage(NewConnection connection)
{
Console.WriteLine($"user {connection.UserId} with connctionid {connection.ConnectionId} has been connected");
}
On my Javascript client this is working but on my Net client it keeps disconnecting everytime right after connection:
[2022-10-02T11:03:27.542Z] Executing 'Functions.OnConnected' (Reason='(null)', Id=3878244a-50cd-47a6-b8c6-98ed1c0dd5c6)
[2022-10-02T11:03:27.544Z] KimOo3chMz6M9zxEPAlpzQ has connected
[2022-10-02T11:03:27.549Z] Executed 'Functions.OnConnected' (Succeeded, Id=3878244a-50cd-47a6-b8c6-98ed1c0dd5c6, Duration=7ms)
[2022-10-02T11:03:27.571Z] Executing 'Functions.OnDisconnected' (Reason='(null)', Id=693bec34-3ed3-434c-93fb-e366c1113e4a)
[2022-10-02T11:03:27.572Z] KimOo3chMz6M9zxEPAlpzQ has disconnected
Not sure what i am missing at the moment.
Found the answer. This behavior was cause by the fact that websockets are not supported by default in Net-Core console app. by changing this to longpolling this as solved.
I have an ASP.NET Core application that needs to communicate with the browser through websockets.
The server is configured as follows :
var webSocketOptions = new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
};
app.UseWebSockets(webSocketOptions);
app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
using (var WS = await context.WebSockets.AcceptWebSocketAsync())
{
// do some stuff or even nothing
} // <<<<<<<<<<<<<< connection dies here
}
else
{
context.Response.StatusCode = 400;
}
}
else
{
await next();
}
});
The connection works properly with the browser, but at the end of the following block, the connection automatically dies.
using (var WS = await context.WebSockets.AcceptWebSocketAsync())
{
// do some stuff or even nothing
} // <<<<<<<<<<<<<< connection dies here
There is no exception in my code, but still the connection dies. I guess this is normal since the variable WS is destroyed after using.
I would like to know please how can I make a websocket connection last and not destroyed immediately after the server gets a connection request.
Also, I see that with this code
WS = await context.WebSockets.AcceptWebSocketAsync()
a new web socket is created for every connection attempt, even if it's coming from the same client that had previously connected. Is possible to change that behavior please ?
Thanks,
Cheers
I have an ASP web app.
The app opens a websocket communication server. The websocket server works properly.
var webSocketOptions = new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
};
app.UseWebSockets(webSocketOptions);
app.Use(async (context, next) =>
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
using (WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync())
{
//do some stuff
}
}
else
{
context.Response.StatusCode = 400;
}
}
else
{
await next();
}
});
When I open my domain example.com and go to Chrome Web Console, the following code works :
var socket = new WebSocket("wss://www.example.com/ws");
However when I add the security constraint :
webSocketOptions.AllowedOrigins.Add("https://www.example.com");
The websocket connection doesn't work anymore. I'm getting the error
VM376:1 WebSocket connection to 'wss://www.example.com/ws' failed: Error during WebSocket handshake: Unexpected response code: 403
Can anyone help please on how to use webSocketOptions.AllowedOrigins ?
I want the Websocket access be allowed only when a request is made from my website www.example.com
Thanks
You have to configure "webSocketOptions.AllowedOrigins" inside your startup middleWare
here a microsoft websocket doc:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/websockets?view=aspnetcore-3.1
We are unable to connect to a signalR hub deployed on server (Windows Server 2008 Enterprise SP2 and IIS 6) through a console application, we tested everything locally on a PC and it was working fine, but deployed on a server (IIS 6) we became unable to connect remotely or even locally on the server itself.
No experience in SignalR but the same client is working fine on a normal PC. (client and hub in the same pc).
We tested the connectivity and the permissions to the server and it's all fine.
We are able to reach the hub url (http://hr1/HRNotificationHub) when we call it remotely via a web browser , but when we add signalR/hubs we get 404 error in the browser also.
static void Main(string[] args) //Client
{
try
{
IHubProxy _hub;
string url = #"http://localhost/HRNotificationHub/";
var connection = new HubConnection(url);
_hub = connection.CreateHubProxy("HRHub");
connection.Start().Wait();
_hub.On("ReceiveMessage", x => Console.WriteLine(x));
string line = null;
while ((line = System.Console.ReadLine()) != null)
{
_hub.Invoke("BroadcastMessageToAll", line).Wait();
}
Console.Read();
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException.ToString());
Console.Read();
}
}
public class Startup //Server
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration()
{
EnableDetailedErrors = true,
EnableJSONP = true,
EnableJavaScriptProxies = true
};
app.MapSignalR(hubConfiguration);
}
}
[HubName("HRHub")]
public class HRHub : Hub //Hub Class
{
public void BroadcastMessageToAll(string message)
{
Clients.All.newMessageReceived(message);
var newMessage = message + "-newmessage";
Clients.All.ReceiveMessage(newMessage);
}
public void JoinAGroup(string group)
{
Groups.Add(Context.ConnectionId, group);
}
public void RemoveFromAGroup(string group)
{
Groups.Remove(Context.ConnectionId, group);
}
public void BroadcastToGroup(string message, string group)
{
Clients.Group(group).newMessageReceived(message);
}
}
Locally, it is working under IIS Express, which is normal.
On the server though, you are running IIS 6 which is not a supported version. Please check the documentation. You need at minimum IIS 7, but IIS 8 if you expect to use web sockets.
All what I have done to solve this issue was adding the line in the webconfig of the project deployed on the server:
<modules runAllManagedModulesForAllRequests="true" />
I'm trying out the Signal R and built a server dll (windows service library/c#) that runs as a Windows Services. I have build also a client application (asp.net web application) to communicate with the server.
But i'm getting always the error(Firefox) "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%5D&_=1482829095207. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)."
Chrome error "
Failed to load resource: the server responded with a status of 400 (Bad Request)"
XMLHttpRequest cannot load http://localhost:8080/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%5D&_=1482830200155. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:50259' is therefore not allowed access. The response had HTTP status code 400.
Note: Edge and also IE gives me errors
I have read almost every post about this subject on Stackoverflow, but non of these solutions seems to work.
The code i'm using for the server side:
namespace SignalRService
{
public class StartupConfiguration
{
public void Configuration(IAppBuilder app)
{
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableDetailedErrors = true,
EnableJSONP = true,
};
map.RunSignalR(hubConfiguration);
});
}
}
}
Services.cs
public void StartService()
{
LogMessage("SignalRService started", true);
Running = true;
WebApp.Start<StartupConfiguration>(ConfigurationManager.AppSettings["SignalRServerUrl"]);
}
EnvironmentSettings.config:
<add key="SignalRServerUrl" value="http://localhost:8080"/>
Hubs.cs
namespace SignalRService.Hubs
{
[HubName("TestHub")]
public class TestHub: Hub
{
public static Dictionary<string, List<HubClient>> clients = new Dictionary<string, List<HubClient>>();
[HubMethodName("Subscribe")]
public async Task Subscribe(string Id)
{...... }}
ClientSide (Javascript/Jquery)
var signalrHubConnection;
var signalrHubConnectionProxy;
var signalRServerUrl = "http://localhost:8080";
var currentTimeout;
var count = 0;
var startSignalRConnection = function () {
console.log("Start");
signalrHubConnection = $.hubConnection(signalRServerUrl);
console.log("Running");
signalrHubConnection.logging = true;
signalrHubConnectionProxy = signalrHubConnection.createHubProxy('TestHub');
console.log("--Subscribe starting");
signalrHubConnection.start()
.done(function () {
signalrHubConnectionProxy.invoke('Subscribe', Id.toString());
console.log("Subscribe ending");
})
.fail(function (test) {
if (count < 5) {
console.log(test.toString());
clearTimeout(currentTimeout);
currentTimeout = setTimeout(function () {
count++;
startSignalRConnection();
}, 300000); // retry after 5 minutes
}
}
);
signalrHubConnectionProxy.on('IncomingMessage',
function (message) {
console.log("Message = " + message.toString());
}
);
};
Test.aspx
<script src="https://code.jquery.com/jquery-3.1.1.min.js" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/signalr/jquery.signalr-2.2.1.min.js"></script>
Did I something wrong?
The error implied that the SignalR url is different from the requesting url (origin). So, SignalR is on localhost, but your main website (the site that holds the client side example) obviously is accessed using "localhost".
Maybe you're accessing it using an IP (eg http://127.0.0.1/) or your PC name (eg http://badassPC/), whereas they must match under the default SignalR setting. I am pretty certain it doesn't matter if the port is different, and also doesn't matter if they are on the same domain (eg www.mysite.com and signalr.mysite.com)
Note there is a workaround that I wouldn't recommend unless you really really know what you're doing as there is a quite serious security risk otherwise: https://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client#crossdomain