I've been researching this issue for 3 days now and cannot find a solution. I created a SignalR Hub with the following code:
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
namespace Messenger.Hubs
{
public class MessengerHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
}
Simple enough, the startup code is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Messenger.Hubs;
namespace Messenger
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddSignalR();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("c:/myapp/Messenger");
});
app.UseMvc();
}
}
}
I pretty much cut and pasted the code from a solution posted on the internet somewhere, I forget where, not stackoverflow though. I then created the following client in a Xamarin (v4.12.3.81) project using Visual Studio 2017 (v15.9.10). That code is:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR.Client;
namespace SignalR.Client.Hubs
{
public class SampleHub
{
// MessengerHub is a appliaction folder aliased as MessengerHub
// the direct path on the machine is c:\mywebapp\messenger
private const string _hubUrl = "http://example.com/MessengerHub";
private readonly HubConnection _hubConnection;
public event EventHandler<string> OnMessageReceived;
public SampleHub()
{
var builder = new HubConnectionBuilder().WithUrl(_hubUrl);
_hubConnection = builder.Build();
}
public async Task<bool> ConnectAsync()
{
try
{
await _hubConnection.StartAsync();
_hubConnection.On("messageReceived", (string platform, string message) =>
{
if (OnMessageReceived != null)
{
OnMessageReceived(this, string.Format("{0}: {1}", platform, message));
}
});
}
catch (Exception ex)
{
var msg = ex.Message;
//Console.WriteLine($"Connection error: {ex.Message}");
return false;
}
return true;
}
public async Task<int> GetNumberAsync(int number)
{
return await _hubConnection.InvokeAsync<int>("GetNumber", number);
}
public Task Send(string message)
{
return _hubConnection.SendAsync("Send", message);
}
}
}
The code in the activity that uses that client is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Views.InputMethods;
using SignalR.Client.Hubs;
namespace MyXamarinApp
{
[Activity(Label = "Messenger")]
public class Messenger : Activity
{
protected override async void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
SetContentView(Resource.Layout.Messenger);
RequestedOrientation = Android.Content.PM.ScreenOrientation.Portrait;
try
{
var input = FindViewById<EditText>(Resource.Id.Input);
var messages = FindViewById<ListView>(Resource.Id.Messages);
var inputManager = (InputMethodManager)GetSystemService(InputMethodService);
var adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, new List<string>());
messages.Adapter = adapter;
var hub = new SampleHub();
await hub.ConnectAsync(); // <---- fails here
input.EditorAction +=
delegate
{
inputManager.HideSoftInputFromWindow(input.WindowToken, HideSoftInputFlags.None);
if (string.IsNullOrEmpty(input.Text))
return;
hub.Send(input.Text);
input.Text = "";
};
hub.OnMessageReceived +=
(sender, message) => RunOnUiThread(() =>
adapter.Add(message));
}
catch (Exception ex)
{
var msg = ex.Message;
}
}
}
}
The hub is (I believe) running correctly on the server, I set logging on and this is what is in the log:
Hosting environment: Production
Content root path: C:\mywebapp\Messenger
Application started. Press Ctrl+C to shut down.
The attempt to connect to the hub generates the following error:
{System.Net.Http.HttpRequestException: 404 (Not Found)
at System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode () [0x0002a] in <25ebe1083eaf4329b5adfdd5bbb7aa57>:0
at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection+<NegotiateAsync>d__44.MoveNext () [0x00226] in <843c441fa9954906b53e3710152bebb9>:0
--- End of stack trace from previous location where exception was thrown
--- at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection+<GetNegotiationResponseAsync>d__51.MoveNext () [0x00077] in <843c441fa9954906b53e3710152bebb9>:0
--- End of stack trace from previous location where exception was thrown
---
at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection+<SelectAndStartTransport>d__43.MoveNext () [0x00169] in <843c441fa9954906b53e3710152bebb9>:0
--- End of stack trace from previous location where exception was thrown
---
at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection+<StartAsyncCore>d__40.MoveNext () [0x00118] in <843c441fa9954906b53e3710152bebb9>:0
--- End of stack trace from previous location where exception was thrown
--- at System.Threading.Tasks.ForceAsyncAwaiter.GetResult () [0x0000c] in <843c441fa9954906b53e3710152bebb9>:0
at Microsoft.AspNetCore.Http.Connections.Client.HttpConnection+<StartAsync>d__39.MoveNext () [0x0008b] in <843c441fa9954906b53e3710152bebb9>:0
--- End of stack trace from previous location where exception was thrown
--- at Microsoft.AspNetCore.SignalR.Client.HttpConnectionFactory+<ConnectAsync>d__3.MoveNext () [0x0009d] in <d50de232736c4c8f910083ea0cb358a8>:0
--- End of stack trace from previous location where exception was thrown
---
at Microsoft.AspNetCore.SignalR.Client.HttpConnectionFactory+<ConnectAsync>d__3.MoveNext () [0x00142] in <d50de232736c4c8f910083ea0cb358a8>:0
--- End of stack trace from previous location where exception was thrown
---
at Microsoft.AspNetCore.SignalR.Client.HubConnection+<StartAsyncCore>d__47.MoveNext () [0x00130] in <f381011e9b214489bcb373743f31ed9d>:0
--- End of stack trace from previous location where exception was thrown
---
at System.Threading.Tasks.ForceAsyncAwaiter.GetResult () [0x0000c] in <f381011e9b214489bcb373743f31ed9d>:0
at Microsoft.AspNetCore.SignalR.Client.HubConnection+<StartAsync>d__39.MoveNext () [0x00091] in <f381011e9b214489bcb373743f31ed9d>:0
--- End of stack trace from previous location where exception was thrown
---
at SignalR.Client.Hubs.SampleHub+<ConnectAsync>d__6.MoveNext () [0x00037] in C:\Users\<username>\Documents\Visual Studio 2017\Projects\signalr_client\signalr_client\Resources\layout\Client.cs:28 }
This is what I see in the IIS Log for the site.
"POST /MessengerHub/negotiate HTTP/1.1" 303 446
"GET /MessengerHub/negotiate HTTP/1.1" 404 1509
I have no idea what to try next.