blazorextensions / signalr Goto Github PK
View Code? Open in Web Editor NEWSignalR Core support for Microsoft ASP.NET Core Blazor
License: MIT License
SignalR Core support for Microsoft ASP.NET Core Blazor
License: MIT License
I am looking to use signalr client in my blazor (client side) app.
My first thought was to add the official signalr.client nuget package:
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.0.0-preview6.19307.2" />
Then I stumbled accross this project which wraps the typescript version - i'm assuming there must be a reason why the Microsoft.AspNetCore.SignalR.Client
package I have referenced above won't work in blazor client applications and why this project exists? Are you able to clarify what the reason is as that will help me decide what to do!
Cheers
Hello everything ok and very nice you just have to correct the shipment of messages to everyone, if I misunderstood
Blazor reached version 0.9.0, SignalR should upgrade too.
Potentially some dependencies like Blazor.Extensions.Logging will need to be upgraded to 0.9.0 first.
My use case had me build a hub that only sends data to the client in two methods - one that sends a simple POCO with data (i send it directly, i don't convert it to JSON or serialize it myself) and another that sends an IEnumerable of POCOs (similar to the former, but a different one).
When testing the same hub against a simple JS client, Both are received properly deserialized and "unboxed" - simply the object and the array (as JS interprets it) themselves.
When trying the same with the Blazor client, The single object is received as a SimpleJson.JsonObject class instead while the IEnumerable doesn't arrive and the method callback on the client receives a null object.
Attached is a small repro solution to show the issue - A server running a single SignalR hub with a method for the clients to trigger the two receiving callbacks, A demo JS client and a demo Blazor client - Both with simple button operation to connect and trigger the data callbacks. See the console on both for results.
Thanks!
How can we add support for Additional languages? Like Hindi or Tamil or Malayalam or Arabic?
This is the error i get when trying to build the connection:
(preview 5, server-side blazor.)
Microsoft.JSInterop.JSException: "Could not find 'BlazorExtensions' in 'window'.
Error: Could not find 'BlazorExtensions' in 'window'.
at Anonymous function (https://localhost:5001/_framework/blazor.server.js:8:20872)
at Array.prototype.forEach (native code)
at d (https://localhost:5001/_framework/blazor.server.js:8:20823)
at Anonymous function (https://localhost:5001/_framework/blazor.server.js:8:21427)
at Promise (native code)
at e.jsCallDispatcher.beginInvokeJSFromDotNet (https://localhost:5001/_framework/blazor.server.js:8:21397)
at Anonymous function (https://localhost:5001/_framework/blazor.server.js:1:16644)
at Array.prototype.forEach (native code)
at e.prototype.invokeClientMethod (https://localhost:5001/_framework/blazor.server.js:1:16619)
at e.prototype.processIncomingData (https://localhost:5001/_framework/blazor.server.js:1:14619)"
Pr submitted! #49
Hi, got this error after updating to preview 9:
11>Unhandled Exception: Mono.Linker.MarkException: Error processing method: 'System.Void Blazor.Extensions.HubConnection::.ctor(Microsoft.JSInterop.IJSRuntime,Blazor.Extensions.HttpConnectionOptions)' in assembly: 'Blazor.Extensions.SignalR.dll' ---> Mono.Cecil.ResolutionException: Failed to resolve Microsoft.JSInterop.DotNetObjectRef`1<!!0> Microsoft.JSInterop.DotNetObjectRef::Create(!!0)
11> at Mono.Linker.Steps.MarkStep.HandleUnresolvedMethod(MethodReference reference)
11> at Mono.Linker.Steps.MarkStep.MarkMethod(MethodReference reference)
11> at Mono.Linker.Steps.MarkStep.MarkInstruction(Instruction instruction)
11> at Mono.Linker.Steps.MarkStep.MarkMethodBody(MethodBody body)
11> at Mono.Linker.Steps.MarkStep.ProcessMethod(MethodDefinition method)
11> at Mono.Linker.Steps.MarkStep.ProcessQueue()
11> --- End of inner exception stack trace ---
11> at Mono.Linker.Steps.MarkStep.ProcessQueue()
11> at Mono.Linker.Steps.MarkStep.ProcessPrimaryQueue()
11> at Mono.Linker.Steps.MarkStep.Process()
11> at Mono.Linker.Steps.MarkStep.Process(LinkContext context)
11> at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step)
11> at Mono.Linker.Pipeline.Process(LinkContext context)
11> at Mono.Linker.Driver.Run(ILogger customLogger)
11> at Mono.Linker.Driver.Execute(String[] args, ILogger customLogger)
11> at Mono.Linker.Driver.Main(String[] args)
I'm going to be building a client side blazor app with some SignalR features. I'm curious why I even need this package vs the normal SignalR packages?
I already have Razor components using the C# SignalR package that I'm using with a server side app. Will these components not work on a client side app?
Essentially: Why can't I just use the normal Microsoft SignalR packages when doing client side Blazor? I think this should be added to the readme to make it more clear why this package exists.
Since Blazor 3.2 preview 1, SignalR is available in blazor wasm:
https://devblogs.microsoft.com/aspnet/blazor-webassembly-3-2-0-preview-1-release-now-available/
When creating a connection I'm getting a
TypeError: Cannot read property 'LogLevel' of undefined at http://localhost:1234/_content/Blazor.Extensions.SignalR.JS:30:10392
Code:
connection = new HubConnectionBuilder()
.WithUrl($"{baseUrl}/blazorhub", opt =>
{
opt.AccessTokenProvider = () => Task.FromResult(Jwt);
opt.SkipNegotiation = true;
opt.Transport = HttpTransportType.WebSockets;
})
.AddMessagePackProtocol()
.Build();
Startup from Server:
[code]
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Serialization;
using System.Linq;
namespace BlazorAndSignalR.Server
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddNewtonsoftJson();
services.AddResponseCompression(opts =>
{
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "application/octet-stream" });
});
services.AddCors(options => options.AddPolicy("CorsPolicy", builder =>
{
builder.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.WithOrigins("http://localhost:51742");
}));
services.AddSignalR();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseResponseCompression();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBlazorDebugging();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
app.UseCors("CorsPolicy");
app.UseSignalR(routes => routes.MapHub<ChatHub>("/chathub"));
app.UseHttpsRedirection();
app.UseBlazor<Client.Startup>();
}
}
}
[/code]
Hub:
[code]
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
namespace BlazorAndSignalR.Server
{
public class ChatHub : Hub
{
public override Task OnConnectedAsync()
{
if(string.IsNullOrEmpty(Context.ConnectionId))
{
throw new System.Exception(nameof(Context.ConnectionId)); //This code is never hit
}
Clients.All.SendAsync("broadcastMessage", "system", $"{Context.ConnectionId} joined the conversation");
return base.OnConnectedAsync();
}
public void Send(string name, string message)
{
Clients.All.SendAsync("broadcastMessage", name, message);
}
public override Task OnDisconnectedAsync(System.Exception exception)
{
Clients.All.SendAsync("broadcastMessage", "system", $"{Context.ConnectionId} left the conversation");
return base.OnDisconnectedAsync(exception);
}
}
}
[/code]
Page:
[code]
@page "/chathub"
HubConnection connection;
string Message = "";
IList<string> messages = new List<string>();
protected override async Task OnInitAsync()
{
connection = new HubConnectionBuilder(jsRuntime).WithUrl("https://localhost:51742/chathub").Build();
connection.On<string, string>("broadcastMessage", this.OnBroadcastMessage);
await connection.StartAsync();
}
Task OnBroadcastMessage(string name, string message)
{
messages.Add(name + " : " + message);
StateHasChanged();
return Task.CompletedTask;
}
async Task SendMessage()
{
await connection.InvokeAsync("Send", "Blazor Client", Message);
Message = "";
}
}
[/code]
Unhandled exception. Mono.Linker.MarkException: Error processing method: 'System.Threading.Tasks.Task Blazor.Extensions.HubConnection/<>c__DisplayClass30_0`10::b__0(System.String[])' in assembly: 'Blazor.Extensions.SignalR.dll'
Mono.Cecil.ResolutionException: Failed to resolve !!0 System.Text.Json.Serialization.JsonSerializer::Parse(System.String,System.Text.Json.Serialization.JsonSerializerOptions)
at Mono.Linker.Steps.MarkStep.HandleUnresolvedMethod(MethodReference reference)
at Mono.Linker.Steps.MarkStep.MarkMethod(MethodReference reference)
at Mono.Linker.Steps.MarkStep.MarkInstruction(Instruction instruction)
at Mono.Linker.Steps.MarkStep.MarkMethodBody(MethodBody body)
at Mono.Linker.Steps.MarkStep.ProcessMethod(MethodDefinition method)
at Mono.Linker.Steps.MarkStep.ProcessQueue()
Implement SignalR streaming APIs as per https://docs.microsoft.com/en-us/aspnet/core/signalr/streaming?view=aspnetcore-2.1
I am using an ASP.NET Server hosting a Blazor application + SignalR server. My browser app communicates to that server via BlazorExtensions/SignalR using MessagePack (but same problem with JSON). When I try to serialize a simple class consisting of an enum and an uint32 field, I get the following errors:
enum: Input string was not in a correct format.
uint32: Object of type 'System.Int64' cannot be converted to type 'System.UInt32'
I am not sure what exactly causes the issues but I think that it can be easily reproduced (or not) if you extend your tests with enum and uint32 fields.
Thank you
Hi,
I try incorporating this extension to a blazor app but I encounter an error when establishing a connection.
Here's what I've done which is based on the usage in the README
endpoints.MapHub<TodoHub>("/todoHub")
services.AddTransient<HubConnectionBuilder>();
in Startup.cs[Inject]
private HubConnectionBuilder _hubConnectionBuilder { get; set; }
protected override async Task OnInitializedAsync()
{
HubConnection connection = _hubConnectionBuilder.WithUrl("/todoHub",
opt =>
{
opt.LogLevel = SignalRLogLevel.Trace;
opt.Transport = HttpTransportType.WebSockets;
})
.Build();
connection.On<string, string>("ReceiveMessage", this.ProcessMessage);
await connection.StartAsync();
}
With following the steps above what I expect is it will run smoothly but rather it throws NullReferenceException.
The whole stacktrace is https://gist.github.com/jhefreyzz/eb6194d478e7b43564eabada4e454a07
Uses the latest release from ASP.NET core
Hi!
First of all, thanks for the library! It's great to have possibility to use SignalR in Blazor with C#.
I have an issue with deserialization of an object. There's an example code attached.
On client side I changed the Index component to subscribe to a hub and added a button to poke a controller on server side that sends an object through the hub.
Problem is, that all strings are empty in the object received in the client in method registered through .On<>
(OnPostReceived
). The contents of the received message is logged to console:
When I looked at the packets through Wireshark they seemed to contain sensible data.
It's also possible that I'm doing something very wrong.
I'm using strongly-typed hub on the server, but I don't think it should matter.
Nice work! But is there a way to use this extension with serverside blazor?
I tried to follow this guide https://github.com/Suchiman/BlazorDualMode to switch between clientside and serverside however when I try serverside, the page hangs during load without a good error message.
There is a serialization issue. Looks like json serializer configuration. I'm not able to receive deserialized entity as a message. All fields have default values. (case sensitive serialization?)
Workaround: Serialize as string in server side, send the message as string, and deserialize as entity later. But I don't want todo this.
Now I'm using Blazor.Extensions.SignalR 0.4.0 but I noticed this behavior since preview 7.
At several places, the current js-runtime is cast to IJSInProcessRuntime. This seems to be ok for the default case, but is this really safe to do with future cases in mind?
My proposal is to add a helper (extension method) that performs this cast, with a workaround, for the case, that the js-runtime is not an in-processes runtime and substitute all occurances of the cast.
This could look like this:
internal static class JSRuntimeExtensions
{
public static T InvokeSync<T>(
this IJSRuntime jsRuntime,
string identifier,
params object[] args)
{
if (jsRuntime == null)
throw new ArgumentNullException(nameof(jsRuntime));
if(jsRuntime is IJSInProcessRuntime inProcessJsRuntime)
{
return inProcessJsRuntime.Invoke<T>(identifier, args);
}
return jsRuntime.InvokeAsync<T>(identifier, args)
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();
}
}
This solution is not ideal either and should be handled with care.
The Off()
method is implemented in the HubConnectionManager
but not exposed trough HubConnection
like the On<T>()
Method
How do I unregister a function then?
Thanks!
I'm having issues with sending a ValueTuple
to the server as the parameter arrives at the ServerHub with default values apparently. I am not sure if this is a BlazorExtensions or a SignalR issue and I was unable to find any issues related to ValueTuple
on either GitHubs... Perhaps posting here will shed some light on this matter.
On the client I'm using the following method:
public async Task<UserBaseModel?> LoginUserWithOpenIdAsync((string LoginToken, string Code) uriParameters)
{
await this.ConnectToAPITask;
if (this.ConnectToAPITask.IsCompleted)
{
Console.WriteLine("======================");
Console.WriteLine(uriParameters.LoginToken);
Console.WriteLine("======================");
UserBaseModel? user = await this.HubConnection.InvokeAsync<UserBaseModel?>("LoginUserWithOpenIdAsync", uriParameters);
if (user != null) { }
}
return null;
}
The client prints out to console just fine:
WASM: 7aQ2/1cZvsvZlIbPK26m9T0EGcqPAtAfzoOQ85EoE2s=
And on the server I have the following method:
public async Task<UserBaseModel?> LoginUserWithOpenIdAsync((string LoginToken, string Code) uriParameters)
{
Console.WriteLine("======================");
Console.WriteLine(uriParameters.GetType().ToString());
if (uriParameters == default(ValueTuple<string, string>))
{
Console.WriteLine("Default values");
}
Console.WriteLine(uriParameters.LoginToken);
Console.WriteLine(uriParameters.Code);
Console.WriteLine("======================");
...
}
The server appears to be receiving the default values for the ValueTuple
with two empty strings:
====================== System.ValueTuple`2[System.String,System.String]
Default values
======================
If I serialize it to JSON I can bypass the issue, but I'd rather avoid it if possible.
Could this be some sort of limitation on either SignalR or BlazorExtensions? If not, any ideas on what might be wrong?
Sorry for the trouble, thanks in advance!
Blazor.Extensions.SignalR cannot deserialize decimals using Blazor preview 9 (and System.Text.Json).
To reproduce, just add a decimal to the DemoData class in the test project and enable MessagePack:
In ChatComponent.cs add: opt.EnableMessagePack = true;
In (server) Startup.cs uncomment: .AddMessagePackProtocol();
Any ideas on how to fix this problem? I suspect it's because MessagePack and System.Text.Json are currently incompatible. Possibly related System.Text.Json bug.
A possible fix is to use switch to Newtonsoft instead of the new default System.Text.Json. Previous versions of Blazor.Extensions.SignalR and Blazor 0.9.0 worked fine when used with Newtonsoft as Json serializer. Any way we can make the extension method AddNewtonsoftJsonProtocol work again? Used on
.HubConnectionBuilder(JSRuntimeCurrent).WithUrl("/chathub", options).AddNewtonsoftJsonProtocol();
Exception:
blazor.webassembly.js:1 Uncaught (in promise) Error: System.Text.Json.JsonException: The JSON value could not be converted to System.Decimal. Path: $.Dec | LineNumber: 0 | BytePositionInLine: 42. ---> System.InvalidOperationException: Cannot get the value of a token type 'String' as a number.
at System.Text.Json.Utf8JsonReader.TryGetDecimal (System.Decimal& value) <0x25a5d98 + 0x0002c> in <81e9245ca982431695a55cc67ffb3b86>:0
at System.Text.Json.Utf8JsonReader.GetDecimal () <0x25a5cc0 + 0x0000a> in <81e9245ca982431695a55cc67ffb3b86>:0
at System.Text.Json.Serialization.Converters.JsonConverterDecimal.Read (System.Text.Json.Utf8JsonReader& reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) <0x25a5c08 + 0x00004> in <81e9245ca982431695a55cc67ffb3b86>:0
at System.Text.Json.JsonPropertyInfoNotNullable`4[TClass,TDeclaredProperty,TRuntimeProperty,TConverter].OnRead (System.Text.Json.JsonTokenType tokenType, System.Text.Json.ReadStack& state, System.Text.Json.Utf8JsonReader& reader) <0x25a59d0 + 0x00070> in <81e9245ca982431695a55cc67ffb3b86>:0
at System.Text.Json.JsonPropertyInfo.Read (System.Text.Json.JsonTokenType tokenType, System.Text.Json.ReadStack& state, System.Text.Json.Utf8JsonReader& reader) <0x20b7938 + 0x00098> in <81e9245ca982431695a55cc67ffb3b86>:0
at System.Text.Json.JsonSerializer.HandleValue (System.Text.Json.JsonTokenType tokenType, System.Text.Json.JsonSerializerOptions options, System.Text.Json.Utf8JsonReader& reader, System.Text.Json.ReadStack& state) <0x20b70c0 + 0x000d0> in <81e9245ca982431695a55cc67ffb3b86>:0
at System.Text.Json.JsonSerializer.ReadCore (System.Text.Json.JsonSerializerOptions options, System.Text.Json.Utf8JsonReader& reader, System.Text.Json.ReadStack& readStack) <0x20b3ee8 + 0x000a0> in <81e9245ca982431695a55cc67ffb3b86>:0
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ReThrowWithPath (System.Text.Json.ReadStack& readStack, System.Text.Json.Utf8JsonReader& reader, System.Exception ex) <0x25ef9d0 + 0x00028> in <81e9245ca982431695a55cc67ffb3b86>:0
at System.Text.Json.JsonSerializer.ReadCore (System.Text.Json.JsonSerializerOptions options, System.Text.Json.Utf8JsonReader& reader, System.Text.Json.ReadStack& readStack) <0x20b3ee8 + 0x00340> in <81e9245ca982431695a55cc67ffb3b86>:0
at System.Text.Json.JsonSerializer.ReadCore (System.Type returnType, System.Text.Json.JsonSerializerOptions options, System.Text.Json.Utf8JsonReader& reader) <0x20a9df0 + 0x0003e> in <81e9245ca982431695a55cc67ffb3b86>:0
at System.Text.Json.JsonSerializer.ParseCore (System.String json, System.Type returnType, System.Text.Json.JsonSerializerOptions options) <0x20a5b00 + 0x00086> in <81e9245ca982431695a55cc67ffb3b86>:0
at System.Text.Json.JsonSerializer.Deserialize[TValue] (System.String json, System.Text.Json.JsonSerializerOptions options) <0x2591390 + 0x00022> in <81e9245ca982431695a55cc67ffb3b86>:0
at Blazor.Extensions.HubConnection+<>c__DisplayClass30_0`10[TResult1,TResult2,TResult3,TResult4,TResult5,TResult6,TResult7,TResult8,TResult9,TResult10].<On>b__0 (System.String[] payloads) <0x25910d0 + 0x000a8> in <c55a512ad88d4b5691739ffb720e5e8d>:0
at (wrapper delegate-invoke) System.Func`2[System.String[],System.Threading.Tasks.Task].invoke_TResult_T(string[])
at Blazor.Extensions.HubMethodCallback.On (System.String[] payloads) <0x2505058 + 0x00014> in <c55a512ad88d4b5691739ffb720e5e8d>:0
at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) <0x1c128d0 + 0x000d2> in <b455df9113dd49c5bfed215a721aae19>:0
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.InvokeSynchronously (Microsoft.JSInterop.JSRuntime jsRuntime, Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo& callInfo, Microsoft.JSInterop.Infrastructure.IDotNetObjectReference objectReference, System.String argsJson) <0x21d7068 + 0x0018a> in <b57783c7fafa47088562351a82800d2f>:0
at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.BeginInvokeDotNet (Microsoft.JSInterop.JSRuntime jsRuntime, Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo invocationInfo, System.String argsJson) <0x2246838 + 0x000ba> in <b57783c7fafa47088562351a82800d2f>:0
at Object.endInvokeDotNetFromJS (http://localhost:61448/_framework/blazor.webassembly.js:1:7164)
at Object.invokeJSFromDotNet (http://localhost:61448/_framework/blazor.webassembly.js:1:6790)
at _mono_wasm_invoke_js_marshalled (http://localhost:61448/_framework/wasm/mono.js:1:176158)
at wasm-function[6322]:0x129810
at wasm-function[1962]:0x6063e
at wasm-function[565]:0x12891
at wasm-function[565]:0x12eca
at wasm-function[565]:0x12c35
at wasm-function[565]:0x12c35
at wasm-function[565]:0x12eca
I am getting 401 always when using the Authorize attribute. This makes the AspNetCore's default implementation of the JwtBearerHandler to not do its job to work correctly.
Why we just dont have an option like this
opt.Headers.Authorization = async () =>
{
return $"Bearer {CurrentUser.Token}";
};
Nuget Packet is Broken on 3.0.0-preview6.
Sample is broken as well.
2>Fatal error in IL Linker 2> 2>Unhandled Exception: Mono.Linker.MarkException: Error processing method: 'System.Threading.Tasks.Task Blazor.Extensions.HubConnection/<>c__DisplayClass30_0`10::<On>b__0(System.String[])' in assembly: 'Blazor.Extensions.SignalR.dll' ---> Mono.Cecil.ResolutionException: Failed to resolve !!0 Microsoft.JSInterop.Json::Deserialize(System.String) 2> at Mono.Linker.Steps.MarkStep.HandleUnresolvedMethod(MethodReference reference) 2> at Mono.Linker.Steps.MarkStep.MarkMethod(MethodReference reference) 2> at Mono.Linker.Steps.MarkStep.MarkInstruction(Instruction instruction) 2> at Mono.Linker.Steps.MarkStep.MarkMethodBody(MethodBody body) 2> at Mono.Linker.Steps.MarkStep.ProcessMethod(MethodDefinition method) 2> at Mono.Linker.Steps.MarkStep.ProcessQueue() 2> --- End of inner exception stack trace --- 2> at Mono.Linker.Steps.MarkStep.ProcessQueue() 2> at Mono.Linker.Steps.MarkStep.ProcessPrimaryQueue() 2> at Mono.Linker.Steps.MarkStep.Process() 2> at Mono.Linker.Steps.MarkStep.Process(LinkContext context) 2> at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step) 2> at Mono.Linker.Pipeline.Process(LinkContext context) 2> at Mono.Linker.Driver.Run(ILogger customLogger) 2> at Mono.Linker.Driver.Execute(String[] args, ILogger customLogger) 2> at Mono.Linker.Driver.Main(String[] args)
The Javascript ASP.NET Core SignalR client now support automatic reconnects, which would be super useful to have.
Stuff needed to be implemented:
If this sounds too big, just having the State property on HubConnection would be extremely helpful so we can detect if a (re)connection succeeded or not.
Thanks for all the work you're putting in! :)
It would be nice to have it in both Off("name", callback)
and Off("name")
to unregister all call-backs for "name"
I want to use signalr with wpf but there's no examples...
I want to use signalr as a frontend, wpf as a backend...
I'm sening a POCO with a SignalR hub then, it gets sent to my subscribed client, but the data is lost.
The data I'm sending
public class WorkerOrderViewDto
{
public int Id { get; set; }
public string UserName { get; set; } = string.Empty;
public ICollection<SandwichDto> Sandwiches { get; set; } = new List<SandwichDto>();
public OrderState State { get; set; }
}
public enum OrderState
{
OrderPlaced,
InTheOven,
ToBeDelivered,
Delivered,
}
The Hub
public class WorkerViewOrderHub : Hub<IWorkerViewOrderClient>
{
}
public interface IWorkerViewOrderClient
{
Task ReceiveOrderAddedAsync(WorkerOrderViewDto orders);
}
Sending the data
private readonly IHubContext<WorkerViewOrderHub, IWorkerViewOrderClient> _workerViewHub;
public async Task<ActionResult> AddOrderAsync([FromBody] AddOrderDto addOrderDto)
{
var userId = _userManager.GetUserId(HttpContext.User) ?? throw new InvalidCommandException();
addOrderDto.UserId = userId;
addOrderDto.CustomerId = userId;
var result = await _serverOrderService.AddOrderAsync(addOrderDto);
var orderView = (await _serverOrderService.GetPendingOrdersForWorkerAsync()).SingleOrDefault(o => o.Id == result);
await _workerViewHub.Clients.All.ReceiveOrderAddedAsync(orderView);
return new OkResult();
}
SignalR Client
_connection.On<WorkerOrderViewDto>(HubNames.WorkerViewOrderHubNames.ReceiveOrderAddedAsync, OnOrdersModifiedAsync);
Task OnOrdersModifiedAsync(WorkerOrderViewDto order)
{
Orders.Add(order);
OrdersChanged?.Invoke();
return Task.CompletedTask;
}
Chrom debug inspection of the serialized data:
https://imgur.com/gallery/m37ptwF
The client connects, gets the message, OnOrdersMidifiedAsync gets called, but the data is not serialized properly. Any idea what I'm doing wrong?
Running netcore 3.0.100-preview5-011568
:
1>Fatal error in IL Linker
1>
1>Unhandled Exception: Mono.Linker.MarkException: Error processing method: 'System.Void Microsoft.AspNetCore.Blazor.Services.WebAssemblyUriHelper::NotifyLocationChanged(System.String)' in assembly: 'Microsoft.AspNetCore.Blazor.dll' ---> Mono.Cecil.ResolutionException: Failed to resolve System.Void Microsoft.AspNetCore.Components.UriHelperBase::TriggerOnLocationChanged()
1> at Mono.Linker.Steps.MarkStep.HandleUnresolvedMethod(MethodReference reference)
1> at Mono.Linker.Steps.MarkStep.MarkMethod(MethodReference reference)
1> at Mono.Linker.Steps.MarkStep.MarkInstruction(Instruction instruction)
1> at Mono.Linker.Steps.MarkStep.MarkMethodBody(MethodBody body)
1> at Mono.Linker.Steps.MarkStep.ProcessMethod(MethodDefinition method)
1> at Mono.Linker.Steps.MarkStep.ProcessQueue()
1> --- End of inner exception stack trace ---
1> at Mono.Linker.Steps.MarkStep.ProcessQueue()
1> at Mono.Linker.Steps.MarkStep.ProcessPrimaryQueue()
1> at Mono.Linker.Steps.MarkStep.Process()
1> at Mono.Linker.Steps.MarkStep.Process(LinkContext context)
1> at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step)
1> at Mono.Linker.Pipeline.Process(LinkContext context)
1> at Mono.Linker.Driver.Run(ILogger customLogger)
1> at Mono.Linker.Driver.Execute(String[] args, ILogger customLogger)
1> at Mono.Linker.Driver.Main(String[] args)
When using byte arrays as client handler arguments or as return type of hub handlers, the signal-r ts-client outputs these as TypedArray
. When passed back to .Net these have to be deserialized either directly or indirectly, but SimpleJson, seems to have a problem deserializing TypedArray
s to .Net arrays.
Upon starting the project, I get the following error. It appears to be looking for a dist
folder, which is not present when building against .NET Standard 2.1 (but is there for version 2.0):
System.IO.DirectoryNotFoundException: /home/adam/Source/Kartel/Kartel.Web/bin/Debug/netstandard2.1/dist/
at at Microsoft.Extensions.FileProviders.PhysicalFileProvider..ctor(String root, ExclusionFilters filters)
at at Microsoft.Extensions.FileProviders.PhysicalFileProvider..ctor(String root)
at at Microsoft.AspNetCore.Builder.BlazorHostingApplicationBuilderExtensions.UseClientSideBlazorFiles(IApplicationBuilder app, String clientAssemblyFilePath)
at at Microsoft.AspNetCore.Builder.BlazorHostingApplicationBuilderExtensions.UseClientSideBlazorFiles[TClientApp](IApplicationBuilder app)
at Kartel.Api.Startup.Configure(IApplicationBuilder app, IWebHostEnvironment env) in /home/adam/Source/Kartel/Kartel.Api/Startup.cs:74
at at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at at Microsoft.AspNetCore.Hosting.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder)
at at Microsoft.AspNetCore.Hosting.ConfigureBuilder.<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder)
at at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
at at Microsoft.AspNetCore.Mvc.Filters.MiddlewareFilterBuilderStartupFilter.<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder)
at at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app)
at at Microsoft.AspNetCore.Hosting.WebHost.BuildApplication()
at at Microsoft.AspNetCore.Hosting.WebHost.StartAsync(CancellationToken cancellationToken)
at at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token, String startupMessage)
at at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token, String startupMessage)
at at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token)
at at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host)
at Kartel.Api.Program.Main(String[] args) in /home/adam/Source/Kartel/Kartel.Api/Program.cs:11
I get this error using server side: InvalidOperationException: JSRuntime must be set up correctly and must be an instance of JSRuntimeBase to use DotNetObjectRef. I can't seem to figure out how to get around it,
Perhaps related to this?
dotnet/aspnetcore#11159
Right now we only have OnClose, all events would be great:
See the connection lifetime events in the the ASP.NET SignalR Hubs API Guide - .NET Client (C#)
I have created a blazor server app in Visual studio preview 2019 and Blazor.Extensions.SignalR (0.2.0). Getting an error when I am trying to listen the signalR message and reloading the table.Do I missed any namespace or something else?
Here my code is,
ViewLog.razor file
@page "/ViewLog"
@using Telerik.Blazor;
@using Telerik.Blazor.Components.Grid;
@using Microsoft.WindowsAzure.Storage;
@using Microsoft.WindowsAzure.Storage.Table;
@using System.Threading.Tasks;
@using WcomLogViewerBlazor.Models;
@using Microsoft.Azure.Documents;
@using Blazor.Extensions;
@using Microsoft.AspNetCore.SignalR;
@using Microsoft.Extensions.DependencyInjection;
@using System.Net.Http;
@using Microsoft.JSInterop;
@using Newtonsoft.Json;
[Inject] private HubConnectionBuilder _hubConnectionBuilder { get; set; }
private HubConnection connection;
private IJSRuntime _runtime;
// Listen SignalR messages and update table
protected override async Task OnInitAsync()
{
var BaseUrl = "http://localhost:7071/api/SignalRInfo";
var resonse = await client.GetStringAsync(BaseUrl);
var responseInfo = JsonConvert.DeserializeObject<Models.ConnectionInfo>(resonse as string);
var URL = responseInfo.URL;
var token = responseInfo.AccessToken;
this.connection = this._hubConnectionBuilder
.WithUrl(URL,
opt =>
{
opt.LogLevel = SignalRLogLevel.Trace; // Client log level
opt.Transport = HttpTransportType.WebSockets; // Which transport you want to use for this connection
}) .Build();
connection.On<string>("TableUpdated", this.OnBroadcastMessage);
await this.connection.StartAsync();
}
startup.cs
services.AddTelerikBlazor();
services.AddTransient<HubConnectionBuilder>();
services.AddSignalR();
Project.csproj file
Hi, first of all thanks for your efforts. Just wanted to know if you are planning to support preview 2 any time soon?
Hi @galvesribeiro this is for track the update to new interop spec
Any way to call the non-generic On
method like the example in the docs?
Example from docs:
connection.On("Receive", this.Handle);
If not, any reason why the non-generic is not implemented? I'm trying to accomplish this:
private void Configure() { HubConnection.On("notify", this.OnConnectedToAPI); } public void OnConnectedToAPI() { Console.WriteLine("============================"); }
Thanks in advance!
I'm trying to recreate https://youtu.be/Yb-N0TmEq_Y?t=2275 and I have no clue why, but it just hangs exactly here. I set a breakpoint on that line and on line 32, hit continue, and nothing happens, no console output in the browser, and the nav menu (when I want to go to Counter or others) are not responsive.
Debugger stepping into doesn't work, and I'm not a blazor pro and not a web dev pro, so I'm kinda stuck. I'm using VS2019 preview with asp.net 3 and RazorComponents. All of that is preview heh.
dotnet 3.0.100-preview6-012264
BlazorExtensions 0.1.9
im using serverside blazor
Im getting this error on init
var connection = _hubConnectionBuilder .WithUrl("/hubs/ChatHub", opt => { opt.LogLevel = SignalRLogLevel.Trace; opt.Transport = HttpTransportType.WebSockets; }).Build();
System.MissingMethodException: Method not found: 'Void Microsoft.JSInterop.DotNetObjectRef..ctor(System.Object)'. at Blazor.Extensions.HubConnection..ctor(IJSRuntime runtime, HttpConnectionOptions options) at Blazor.Extensions.HubConnectionBuilder.Build()
I would like the option to unsubscribe a handle from the hub, is that possible?
SignalR allow you to pass a function to the connection options that return an access token.
We must enable that in the C# side as well. Today we only allow people to pass in the fixed access token.
Recently I tried to update my blazor wasm project (which uses Blazor.Extensions.SignalR v1.1.0-preview3
) to latest 3.1.0-preview4.19579.2
Blazor version.
After updating, an error began to appear in browser console:
Could not find 'BlazorExtensions' in 'window'. Error: Could not find 'BlazorExtensions' in 'window'.
at http://localhost:7258/_framework/blazor.webassembly.js:1:8937
at Array.forEach (<anonymous>)
at p (http://localhost:7258/_framework/blazor.webassembly.js:1:8898)
at Object.invokeJSFromDotNet (http://localhost:7258/_framework/blazor.webassembly.js:1:9470)
at _mono_wasm_invoke_js_marshalled (http://localhost:7258/_framework/wasm/mono.js:1:165750)
at wasm-function[6221]:0x11936a
at wasm-function[1431]:0x402ee
at wasm-function[636]:0x147cf
at wasm-function[636]:0x19ae2
at wasm-function[4996]:0xeb135
It is probably due to latest changes related to static assets in libraries - as we can see at https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-core-3-1/
Support for static assets in libraries when publishing
Standalone Blazor WebAssembly apps now support static assets from Razor class libraries both during development and when publishing. This applies to both standalone Blazor WebAssembly apps and ASP.NET Core hosted apps. Static assets are consumed from referenced libraries using the path prefix: _content/{LIBRARY NAME}/.
There is also PR @ AspNetCore src repo: https://github.com/aspnet/AspNetCore/pull/17353/files
Problem is also reported in several other projects which uses *.js static assets.
Initially I have also tried to update Blazor.Extensions.SignalR
to 3.1.0-preview4.19579.2
and the same Could not find 'BlazorExtensions' in 'window'
occured when Blazor.Extensions.SignalR.Test.Server
started.
I have discovered some differences between old build output and new build output, eg.:
[old - netstandard2.0]
test\Blazor.Extensions.SignalR.Test.Client\bin\Debug\netstandard2.0\dist\_content\Blazor.Extensions.SignalR.JS
"jsReferences": [ "_content/Blazor.Extensions.SignalR.JS" ]
entry in test\Blazor.Extensions.SignalR.Test.Client\bin\Debug\netstandard2.0\dist\_framework\blazor.boot.json
[new - netstandard2.1]
test\Blazor.Extensions.SignalR.Test.Client\bin\Debug\netstandard2.1\dist\_content\Blazor.Extensions.SignalR.JS
does NOT existstest\Blazor.Extensions.SignalR.Test.Client\bin\Debug\netstandard2.1\dist\_framework\blazor.boot.js
on does NOT contain "jsReferences": [ "_content/Blazor.Extensions.SignalR.JS" ]
entryI have forked Blazor.Extensions.SignalR
repo and I will try to prepare workaround...
It should be possible to configurate the (external) hub url via configuration.
Attempt by method 'Blazor.Extensions.HubConnection..ctor(Blazor.Extensions.HttpConnectionOptions)' to access method 'Microsoft.JSInterop.JSRuntime.get_Current()' failed.
Simple example test fails with the above.
I am using an ASP.NET Server hosting a Blazor application + SignalR server.
My browser app communicates to that server via BlazorExtensions/SignalR
In the simple classes that I pass it works fine for integers, strings and bytearrays, but not for Guid and DateTime.
If I send the DateTime as a long it works, but for a DateTime I get the following error:
Uncaught (in promise) Error: System.FormatException: String was not recognized as a valid DateTime.
at System.DateTimeParse.Parse (System.ReadOnlySpan`1[T] s, System.Globalization.DateTimeFormatInfo dtfi, System.Globalization.DateTimeStyles styles) <0x23ed4a0 + 0x00074> in <6d03508d2e754cd29d153e0b362bc7fa>:0
at System.DateTime.Parse (System.String s, System.IFormatProvider provider, System.Globalization.DateTimeStyles styles) <0x23ed320 + 0x00038> in <6d03508d2e754cd29d153e0b362bc7fa>:0
at SimpleJson.PocoJsonSerializerStrategy.DeserializeObject (System.Object value, System.Type type) <0x1e54210 + 0x001b2> in <8f8c03446dbf45f5bbcb1e109a064f6e>:0
at SimpleJson.PocoJsonSerializerStrategy.DeserializeObject (System.Object value, System.Type type) <0x1e54210 + 0x00862> in <8f8c03446dbf45f5bbcb1e109a064f6e>:0
at SimpleJson.SimpleJson.DeserializeObject (System.String json, System.Type type, SimpleJson.IJsonSerializerStrategy jsonSerializerStrategy) <0x1e51c68 + 0x00068> in <8f8c03446dbf45f5bbcb1e109a064f6e>:0
at SimpleJson.SimpleJson.DeserializeObject[T] (System.String json) <0x24aae90 + 0x0000a> in <8f8c03446dbf45f5bbcb1e109a064f6e>:0
at Microsoft.JSInterop.Json.Deserialize[T] (System.String json) <0x24aae58 + 0x00004> in <8f8c03446dbf45f5bbcb1e109a064f6e>:0
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.