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

[WIP] Server-side blazor support #12

wants to merge 19 commits into from

Conversation

CatoLeanTruetschel
Copy link
Contributor

@CatoLeanTruetschel CatoLeanTruetschel commented Mar 15, 2019

This is a prototype to make available the library server-side, running with Razor Components. The biggest issues are solved but it is not running server-side yet.

To support this, the IUriHelper needs to be injected as server, as it was needed with the js runtime on the blazor 0.9.0 update. This will incur breaking changes.

There are some code parts, that need to know whether it is running on blazor, this is currently done by checking for loaded assemblies (in particual if the Microsoft.AspNetCore.Mvc assembly is loaded). This is a temporary workaround only and need to be replaced. Maybe there is a way of checking whether we are running on Mono WASM or we let the user configure this in the options.

Fixes #23

@csnewman csnewman changed the title [Do not merge] Razor Components (server-side) support [WIP] Razor Components (server-side) support Mar 15, 2019
Copy link
Owner

@csnewman csnewman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good start. Obviously currently WIP, so asides from the formatting comments, the main point is about trying to remove the use of reflection, maybe via the jsruntime check?

src/BlazorSignalR/Internal/BlazorHttpConnectionFactory.cs Outdated Show resolved Hide resolved
test/BlazorSignalR.Test.Client/Pages/ChatComponent.cs Outdated Show resolved Hide resolved
test/BlazorSignalR.Test.RazorComponents/Hubs/ChatHub.cs Outdated Show resolved Hide resolved
test/BlazorSignalR.Test.Server/wwwroot/css/site.css Outdated Show resolved Hide resolved
@csnewman
Copy link
Owner

@AndreasTruetschel Any progress?

@CatoLeanTruetschel
Copy link
Contributor Author

I'm currently working on this.
Work that I want to complete before merge:

  • Replace the usage of the WebAssemblyHttpMessageHandler to send everything to the client
  • Merge the test projects
  • Review the breaking changes (and allow the usage with the old api, disabling the server-side support in this case)

@csnewman
Copy link
Owner

Thanks.

I assume you're just creating a "BrowserHttpMessageHandler"/"BlazorHttpMessageHandler" or something of the sorts that will be used regardless of whether it's server side of client side blazor?

@csnewman
Copy link
Owner

Would it also be possible for the RazorComponents naming to be replaced with ServerSideBlazor as they have switched back to the old naming?

@csnewman csnewman changed the title [WIP] Razor Components (server-side) support [WIP] Server-side blazor support May 18, 2019
@CatoLeanTruetschel
Copy link
Contributor Author

CatoLeanTruetschel commented May 18, 2019

Would it also be possible for the RazorComponents naming to be replaced with ServerSideBlazor as they have switched back to the old naming?

Sure. I wanted to do this anyway.

@CatoLeanTruetschel
Copy link
Contributor Author

I assume you're just creating a "BrowserHttpMessageHandler"/"BlazorHttpMessageHandler" or something of the sorts that will be used regardless of whether it's server side of client side blazor?

This would be a solution but needs the complete replacement and therefore reimplementation (or fork) of the WebAssemblyHttpMessageHandler. I have the hope that we can make the WebAssemblyHttpMessageHandler work with server-side blazor but I need to have a look into the repo whether this is possible.

@csnewman Do you have a better idea for this?

@csnewman
Copy link
Owner

I assume you're just creating a "BrowserHttpMessageHandler"/"BlazorHttpMessageHandler" or something of the sorts that will be used regardless of whether it's server side of client side blazor?

This would be a solution but needs the complete replacement and therefore reimplementation (or fork) of the WebAssemblyHttpMessageHandler. I have the hope that we can make the WebAssemblyHttpMessageHandler work with server-side blazor but I need to have a look into the repo whether this is possible.

@csnewman Do you have a better idea for this?

Afaik the webassembly one uses WebAssemblyJsRuntime explicitly. I also assume the JS probably isn't included as the server side blazor uses a different js file in the browser.

I therefore get the impression that a custom message handler will have to be made (well copied).

@CatoLeanTruetschel
Copy link
Contributor Author

I looked into this. The typescript code of the original implementation has to be changed massively, as they do not use ordinary interop but rely on the fact that this thing runs on web assembly. If this is forked and adapted in order to be used both, client and server-side it will incure a massive hit in performance IMO as this will need to work with json serialization then.
For example the result is directly written into a .net array that is pre-allocated without marshaling the array. See also: dotnet/aspnetcore#5619 (comment)

I don't think this will be possible in general, when we do not know that we are running client-side within wasm.

@csnewman
Copy link
Owner

Maybe a slight change of course is a better option.

Currently HttpClient etc is only needed for the inbuilt c# transports, i.e. ServerSentEventsTransport, whereas the JS proxied versions like BlazorServerSentEventsTransport have no need for it.

Maybe instead we can detect if running on server side blazor and disable any non-js transports in CreateTransport. This should require a lot less effort, and then the performance overhead will be lowered as much as possible (only the actual data being sent will be serialised as json instead of all HTTP overhead).

@CatoLeanTruetschel
Copy link
Contributor Author

CatoLeanTruetschel commented May 19, 2019

Thats seems to be a reasonable approach. However we need a HttpClient instance anyway (for the negotiation). I will continue with forking WebAssemblyHttpMessageHandler and make it work server-side. When creating a transport I will then create a HttpClient via WebAssemblyHttpMessageHandler when running client-side and via the fork when running server-side.

@CatoLeanTruetschel
Copy link
Contributor Author

CatoLeanTruetschel commented May 19, 2019

This is working now for both server and client-side projects. I tried to re-use and/or link most of the stuff in the server projects as it is not possible for now to combine these without copying a lot of source code from the blazor repo. It seems they are currently working on this so maybe we can do this soon.

Still open issues:

  • Server-side blazor cannot import static content as of the current version. I copied the js-files for this project and the BlazorExtensions.Logging project to the wwwroot folder. I also tried to use this but couldn't make it work yet.
  • The browser console is playing tango in the client-side and server-side case. I have to take a deeper look on this.

@csnewman Can you please review the latest changes?

@csnewman
Copy link
Owner

csnewman commented May 19, 2019

It feels like a lot of baggage having a custom HttpMessageHandler if it is only used for the negotiation. Instead having just a JS implemented negotiater might simply things.

src/BlazorSignalR.JS/src/WebSocketsTransport.ts Outdated Show resolved Hide resolved
src/BlazorSignalR.JS/src/ServerSentEventsTransport.ts Outdated Show resolved Hide resolved
src/BlazorSignalR/BlazorSignalRExtensions.cs Outdated Show resolved Hide resolved
/// <summary>
/// A browser-compatible implementation of <see cref="HttpMessageHandler"/>
/// </summary>
internal class BlazorHttpMessageHandler : HttpMessageHandler
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned already, I see little purpose for having this this heavy weight custom HttpMessageHandler just for a one-off negotiation request.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The BlazorServerSentEventsTransport internally also uses an http-client. Replacing the current solution needs us to rewrite the negotiation in js together with the parts the BlazorServerSentEventsTransport does with it. I don't think this will be less costly for at least the development and maintenance costs. For runtime statistics we had to test this as I cannot estimate the performance characteristics of the two solutions. The current solution also gives as the benefit if we ever wanted to support some kind of managed (well C# implemented) transport to have a solution for HTTP-transmission out of the box.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I'm quite torn about this.

One side of me thinks when on server side blazor, we should never use c# implemented transports because this risks the request being sent from server (API might change etc) is too high, and we can tune the performance more of the custom JS implementations, therefore removing the need for this large setup. The negotiation code should be quite short (we can look at the typescript client code), and I imagine the usage of it in the server sent event transport is quite minimal/easy to convert.

Though I also think that this could be useful in the future, for when we need to bodge some more functionality, or maybe someone wants to add a custom transport.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to retain the current solution. When we ever need to, due to perfromance problems or other issues, we can investigate with replacing the current solution (partially) with a js-implemented one. This also does not bloat this PR with too many changes that are not actually necessary to implement the desired set of features.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Via that argument, I would argue BlazorHttpMessageHandler is more bloat and unneeded for the actual features we need. It is going to become a large burden to maintain, as we will have to track the Blazor repo to see if any bugs etc are detected with the more or less copied implementation?

You can either remove it, or I can if you prefer.

@CatoLeanTruetschel
Copy link
Contributor Author

CatoLeanTruetschel commented May 23, 2019

The browser console is playing tango in the client-side and server-side case. I have to take a deeper look on this.

I don't think this is a problem in our code but a bug in the BrowserConsoleLogger. I will file a bug there eventually.

Edit: This is the issue: BlazorExtensions/Logging#28

@csnewman csnewman added the enhancement New feature or request label May 24, 2019
@csnewman
Copy link
Owner

The browser console is playing tango in the client-side and server-side case. I have to take a deeper look on this.

I don't think this is a problem in our code but a bug in the BrowserConsoleLogger. I will file a bug there eventually.

Edit: This is the issue: BlazorExtensions/Logging#28

Ah. I see the people over BlazorExtensions/Logging#28 have been rather unhelpful.


factory.Services.AddLogging(builder => builder
//.AddBrowserConsole() // Add Blazor.Extensions.Logging.BrowserConsoleLogger // This is not yet available for Blazor 0.8.0 https://github.com/BlazorExtensions/Logging/pull/22
.AddBrowserConsole()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did this work for you? I received runtime errors when adding in this manner

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Re-enable logging in the test project
3 participants