Skip to content
This repository has been archived by the owner on Feb 5, 2020. It is now read-only.

[WIP] Server-side blazor support #12

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
1fff4b1
Moved wwwroot to server project
CatoLeanTruetschel Mar 13, 2019
a694437
Prepared project for running server-side
CatoLeanTruetschel Mar 15, 2019
7d1876d
Added razor components prototype
CatoLeanTruetschel Mar 15, 2019
6db616f
Replaced obsolete IHostingEnvironment with IWebHostEnvironment
CatoLeanTruetschel Mar 15, 2019
363995c
Cleanup and code style
CatoLeanTruetschel Mar 16, 2019
e39849e
Fixed typo
CatoLeanTruetschel Mar 16, 2019
0836843
Merge remote-tracking branch 'upstream/master' into master
CatoLeanTruetschel May 18, 2019
5bd330a
Reenable pre-rendering
CatoLeanTruetschel May 18, 2019
7f1a495
Re-enable client-side logging
CatoLeanTruetschel May 18, 2019
4f94347
Add missing JSRuntime service to HubConnectionBuilder services
CatoLeanTruetschel May 18, 2019
31aa5dc
Implement client-side HttpMessageHandler that is usable server-side
CatoLeanTruetschel May 19, 2019
e4bbeea
Replace server-side http dispatch with new client-side HttpMessageHan…
CatoLeanTruetschel May 19, 2019
726d626
Replace synchronous JS->.Net invokation with async alternative
CatoLeanTruetschel May 19, 2019
be4dba0
Add new server-side test project
CatoLeanTruetschel May 19, 2019
20b72ca
Ensure backwards compatibility
CatoLeanTruetschel May 19, 2019
f7c9680
Revert temporary changes
CatoLeanTruetschel May 19, 2019
e2b4d9e
Await the JS->.Net invokations in event handlers
CatoLeanTruetschel May 23, 2019
1d33089
Revert "Ensure backwards compatibility"
CatoLeanTruetschel May 23, 2019
e1d6ccf
Add comment to explain pre-rendering short-circuit
CatoLeanTruetschel May 23, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions BlazorSignalR.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
# Visual Studio Version 16
VisualStudioVersion = 16.0.28711.60
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B286BCBD-DAD8-4DE7-9334-3DE18DF233AF}"
EndProject
Expand All @@ -20,6 +20,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorSignalR.Test.Client",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorSignalR.Test.Server", "test\BlazorSignalR.Test.Server\BlazorSignalR.Test.Server.csproj", "{8952910D-6251-48A0-8A00-369553370547}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorSignalR.Test.RazorComponents", "test\BlazorSignalR.Test.RazorComponents\BlazorSignalR.Test.RazorComponents.csproj", "{38EF5314-698C-41A1-BC4E-E6595ABA33A6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -78,6 +80,18 @@ Global
{8952910D-6251-48A0-8A00-369553370547}.Release|x64.Build.0 = Release|Any CPU
{8952910D-6251-48A0-8A00-369553370547}.Release|x86.ActiveCfg = Release|Any CPU
{8952910D-6251-48A0-8A00-369553370547}.Release|x86.Build.0 = Release|Any CPU
{38EF5314-698C-41A1-BC4E-E6595ABA33A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{38EF5314-698C-41A1-BC4E-E6595ABA33A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{38EF5314-698C-41A1-BC4E-E6595ABA33A6}.Debug|x64.ActiveCfg = Debug|Any CPU
{38EF5314-698C-41A1-BC4E-E6595ABA33A6}.Debug|x64.Build.0 = Debug|Any CPU
{38EF5314-698C-41A1-BC4E-E6595ABA33A6}.Debug|x86.ActiveCfg = Debug|Any CPU
{38EF5314-698C-41A1-BC4E-E6595ABA33A6}.Debug|x86.Build.0 = Debug|Any CPU
{38EF5314-698C-41A1-BC4E-E6595ABA33A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{38EF5314-698C-41A1-BC4E-E6595ABA33A6}.Release|Any CPU.Build.0 = Release|Any CPU
{38EF5314-698C-41A1-BC4E-E6595ABA33A6}.Release|x64.ActiveCfg = Release|Any CPU
{38EF5314-698C-41A1-BC4E-E6595ABA33A6}.Release|x64.Build.0 = Release|Any CPU
{38EF5314-698C-41A1-BC4E-E6595ABA33A6}.Release|x86.ActiveCfg = Release|Any CPU
{38EF5314-698C-41A1-BC4E-E6595ABA33A6}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -87,6 +101,7 @@ Global
{1C49147F-7C73-4962-A71C-6A193970D058} = {B286BCBD-DAD8-4DE7-9334-3DE18DF233AF}
{752EC32C-EC70-4E7E-B2C3-610B0893249F} = {20DAA632-F8AD-4C5F-9E5F-FC82B7CB56A7}
{8952910D-6251-48A0-8A00-369553370547} = {20DAA632-F8AD-4C5F-9E5F-FC82B7CB56A7}
{38EF5314-698C-41A1-BC4E-E6595ABA33A6} = {20DAA632-F8AD-4C5F-9E5F-FC82B7CB56A7}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A97C0A4B-E309-4485-BB76-898B37BFBFFF}
Expand Down
29 changes: 21 additions & 8 deletions src/BlazorSignalR/BlazorSignalRExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using BlazorSignalR.Internal;
using Microsoft.AspNetCore.Components.Services;
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -9,14 +10,24 @@ namespace BlazorSignalR
{
public static class BlazorSignalRExtensions
{
public static IHubConnectionBuilder WithUrlBlazor(this IHubConnectionBuilder hubConnectionBuilder, string url, IJSRuntime jsRuntime,
HttpTransportType? transports = null, Action<BlazorHttpConnectionOptions> options = null)
public static IHubConnectionBuilder WithUrlBlazor(
this IHubConnectionBuilder hubConnectionBuilder,
string url,
IJSRuntime jsRuntime,
IUriHelper uriHelper,
HttpTransportType? transports = null,
Action<BlazorHttpConnectionOptions> options = null)
{
return WithUrlBlazor(hubConnectionBuilder, new Uri(url), jsRuntime, transports, options);
return WithUrlBlazor(hubConnectionBuilder, new Uri(url, UriKind.Relative), jsRuntime, uriHelper, transports, options);
}

public static IHubConnectionBuilder WithUrlBlazor(this IHubConnectionBuilder hubConnectionBuilder, Uri url, IJSRuntime jsRuntime,
HttpTransportType? transports = null, Action<BlazorHttpConnectionOptions> options = null)
public static IHubConnectionBuilder WithUrlBlazor(
this IHubConnectionBuilder hubConnectionBuilder,
Uri url,
IJSRuntime jsRuntime,
IUriHelper uriHelper,
HttpTransportType? transports = null,
Action<BlazorHttpConnectionOptions> options = null)
{
if (hubConnectionBuilder == null)
throw new ArgumentNullException(nameof(hubConnectionBuilder));
Expand All @@ -33,15 +44,17 @@ public static IHubConnectionBuilder WithUrlBlazor(this IHubConnectionBuilder hub
});
if (options != null)
hubConnectionBuilder.Services.Configure(options);
hubConnectionBuilder.Services.AddSingleton(provider => BuildBlazorHttpConnectionFactory(provider, jsRuntime));
hubConnectionBuilder.Services.AddSingleton(provider => BuildBlazorHttpConnectionFactory(provider, jsRuntime, uriHelper));
return hubConnectionBuilder;
}

private static IConnectionFactory BuildBlazorHttpConnectionFactory(IServiceProvider provider, IJSRuntime jsRuntime)
private static IConnectionFactory BuildBlazorHttpConnectionFactory(
IServiceProvider provider, IJSRuntime jsRuntime, IUriHelper uriHelper)
{
return ActivatorUtilities.CreateInstance<BlazorHttpConnectionFactory>(
provider,
jsRuntime);
jsRuntime,
uriHelper);
}
}
}
32 changes: 27 additions & 5 deletions src/BlazorSignalR/Internal/BlazorHttpConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Blazor.Http;
using Microsoft.AspNetCore.Blazor.Services;
using Microsoft.AspNetCore.Components.Services;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Http.Connections;
Expand All @@ -23,6 +24,7 @@ internal class BlazorHttpConnection : ConnectionContext, IConnectionInherentKeep
{
private static readonly int _maxRedirects = 100;
private static readonly Task<string> NoAccessToken = Task.FromResult<string>((string)null);
private readonly bool _isServerSide;

public override string ConnectionId
{
Expand Down Expand Up @@ -51,6 +53,7 @@ public override IDuplexPipe Transport

private readonly BlazorHttpConnectionOptions _options;
private readonly IJSRuntime _jsRuntime;
private readonly IUriHelper _uriHelper;
private readonly ILoggerFactory _loggerFactory;
private readonly ILogger<BlazorHttpConnection> _logger;
private readonly HttpClient _httpClient;
Expand All @@ -64,20 +67,29 @@ public override IDuplexPipe Transport
private bool _hasInherentKeepAlive;
private Func<Task<string>> _accessTokenProvider;

public BlazorHttpConnection(BlazorHttpConnectionOptions options, IJSRuntime jsRuntime, ILoggerFactory loggerFactory)
public BlazorHttpConnection(
BlazorHttpConnectionOptions options,
IJSRuntime jsRuntime,
IUriHelper uriHelper,
bool isServerSide,
ILoggerFactory loggerFactory)
{
if (jsRuntime == null)
throw new ArgumentNullException(nameof(jsRuntime));

if (uriHelper == null)
throw new ArgumentNullException(nameof(uriHelper));

_options = options;
_jsRuntime = jsRuntime;
_uriHelper = uriHelper;
_isServerSide = isServerSide;
_loggerFactory = loggerFactory ?? NullLoggerFactory.Instance;
_logger = _loggerFactory.CreateLogger<BlazorHttpConnection>();
_httpClient = CreateHttpClient();
Features.Set<IConnectionInherentKeepAliveFeature>(this);
}


public async Task StartAsync(TransferFormat transferFormat)
{
CheckDisposed();
Expand Down Expand Up @@ -117,7 +129,7 @@ private async Task SelectAndStartTransport(TransferFormat transferFormat)
// Fix relative url paths
if (!uri.IsAbsoluteUri || uri.Scheme == Uri.UriSchemeFile && uri.OriginalString.StartsWith("/", StringComparison.Ordinal))
{
Uri baseUrl = new Uri(WebAssemblyUriHelper.Instance.GetBaseUri());
Uri baseUrl = new Uri(_uriHelper.GetBaseUri());
uri = new Uri(baseUrl, uri);
}

Expand Down Expand Up @@ -320,7 +332,17 @@ private static Uri CreateConnectUrl(Uri url, string connectionId)

private HttpClient CreateHttpClient()
{
HttpMessageHandler handler = new WebAssemblyHttpMessageHandler();
HttpMessageHandler handler;

if (_isServerSide)
{
handler = new HttpClientHandler();
csnewman marked this conversation as resolved.
Show resolved Hide resolved
}
else
{
handler = new WebAssemblyHttpMessageHandler();
}

if (_options.HttpMessageHandlerFactory != null)
{
handler = _options.HttpMessageHandlerFactory(handler);
Expand All @@ -333,7 +355,7 @@ private HttpClient CreateHttpClient()
HttpClient httpClient =
new HttpClient(new LoggingHttpMessageHandler(handler, _loggerFactory))
{
BaseAddress = new Uri(WebAssemblyUriHelper.Instance.GetBaseUri()),
BaseAddress = new Uri(_uriHelper.GetBaseUri()),
Timeout = HttpClientTimeout
};
// httpClient.DefaultRequestHeaders.UserAgent.Add(Constants.UserAgentHeader);
Expand Down
19 changes: 17 additions & 2 deletions src/BlazorSignalR/Internal/BlazorHttpConnectionFactory.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Services;
using Microsoft.AspNetCore.Connections;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.Logging;
Expand All @@ -13,22 +15,35 @@ internal class BlazorHttpConnectionFactory : IConnectionFactory
{
private readonly BlazorHttpConnectionOptions _options;
private readonly IJSRuntime _jsRuntime;
private readonly IUriHelper _uriHelper;
private readonly bool _isServerSide;
private readonly ILoggerFactory _loggerFactory;

public BlazorHttpConnectionFactory(IOptions<BlazorHttpConnectionOptions> options, IJSRuntime jsRuntime, ILoggerFactory loggerFactory)
public BlazorHttpConnectionFactory(
IOptions<BlazorHttpConnectionOptions> options,
IJSRuntime jsRuntime,
IUriHelper uriHelper,
ILoggerFactory loggerFactory)
{
if (jsRuntime == null)
throw new ArgumentNullException(nameof(jsRuntime));

if (uriHelper == null)
throw new ArgumentNullException(nameof(uriHelper));

_options = options.Value;
_jsRuntime = jsRuntime;
_uriHelper = uriHelper;
_loggerFactory = loggerFactory;

// TODO: Is there a better/cleaner way?
_isServerSide = AppDomain.CurrentDomain.GetAssemblies().Any(p => p.GetName().Name == "Microsoft.AspNetCore.Mvc");
CatoLeanTruetschel marked this conversation as resolved.
Show resolved Hide resolved
}

public async Task<ConnectionContext> ConnectAsync(TransferFormat transferFormat,
CancellationToken cancellationToken = new CancellationToken())
{
BlazorHttpConnection connection = new BlazorHttpConnection(_options, _jsRuntime, _loggerFactory);
BlazorHttpConnection connection = new BlazorHttpConnection(_options, _jsRuntime, _uriHelper, _isServerSide, _loggerFactory);

try
{
Expand Down
14 changes: 7 additions & 7 deletions test/BlazorSignalR.Test.Client/Pages/Chat.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<h4>To Everybody</h4>
<form class="form-inline">
<div class="input-append">
<input type="text" id="message-text" placeholder="Type a message" bind=@_toEverybody />
<input type="text" id="message-text" placeholder="Type a message" bind=@ToEverybody />
<input type="button" id="broadcast" class="btn" value="Broadcast" onclick=@Broadcast />
<input type="button" id="broadcast-exceptme" class="btn" value="Broadcast (Others)" onclick=@SendToOthers />
</div>
Expand All @@ -22,25 +22,25 @@
<h4>To Connection</h4>
<form class="form-inline">
<div class="input-prepend input-append">
<input type="text" name="connection-message" id="connection-message-text" placeholder="Type a message" bind=@_toConnection />
<input type="text" name="connection-id" id="connection-id" placeholder="Type a connection id" bind=@_connectionId />
<input type="text" name="connection-message" id="connection-message-text" placeholder="Type a message" bind=@ToConnection />
<input type="text" name="connection-id" id="connection-id" placeholder="Type a connection id" bind=@ConnectionId />
<input type="button" id="connection-send" class="btn" value="Send to Connection" onclick=@SendToConnection />
</div>
</form>

<h4>To Me</h4>
<form class="form-inline">
<div class="input-append">
<input type="text" id="me-message-text" placeholder="Type a message" bind=@_toMe />
<input type="text" id="me-message-text" placeholder="Type a message" bind=@ToMe />
<input type="button" id="send" class="btn" value="Send to Me" onclick=@SendToMe />
</div>
</form>

<h4>Group Actions</h4>
<form class="form-inline">
<div class="input-prepend input-append">
<input type="text" name="group-message" id="group-message-text" placeholder="Type a message" bind=@_toGroup />
<input type="text" name="group-name" id="group-name" placeholder="Type a group name" bind=@_groupName />
<input type="text" name="group-message" id="group-message-text" placeholder="Type a message" bind=@ToGroup />
<input type="text" name="group-name" id="group-name" placeholder="Type a group name" bind=@GroupName />
<input type="button" id="groupmsg" class="btn" value="Send to Group" onclick=@SendToGroup />
<input type="button" id="others-groupmsg" class="btn" value="Send to Others in Group" onclick=@SendToOthersInGroup />
<input type="button" id="join-group" class="btn" value="Join Group" onclick=@JoinGroup />
Expand All @@ -50,7 +50,7 @@
</form>

<ul id="message-list">
@foreach (var msg in _messages)
@foreach (var msg in Messages)
{
<li>@msg</li>
}
Expand Down
Loading