Aspnetcore: IE11 support for server-side Blazor

Created on 16 Apr 2019  Â·  55Comments  Â·  Source: dotnet/aspnetcore

Creating a default "Razor Component" Project and trying to access it from IE 11 doesn't seem to work.

Steps to reproduce the behavior:

  1. Create a new "Razor Component" project
  2. Run
  3. Access it from IE11

Expected behavior / Error
The counter page shows up but the button action does not do anything .

IE11 Console shows the following error during the load of the page

  • Promise is undefined

I tried to do random stuff that got me nowhere.

I added

then I got "fetch is undefined"
So I added

and now I get-
undefined is not encodable in msgpack!

area-blazor bug help wanted

Most helpful comment

Update:
I got it working in a different way. For me this seems easier because no modification is needed for blazor.server.js

  1. use Daddoon's Polyfill library
  2. set signalR client side log level in _Host.cshtml
<script src="~/_framework/blazor.server.js"></script>
<script>
    Blazor.start({
        configureSignalR: function (builder) {
            builder.configureLogging(2); // LogLevel.Information
        }
    });
</script>

I don't know why the call to Blazor.start suddenly brings the application up running on IE11 but it seems to be a valid workaround.

Update:
Setting the signalR log level is not really necessary, just call Blazor.start (see below).

Regards
Sven

All 55 comments

Some doc/wiki page once mentioned you'll need polyfills. I tried some in the past without success.

  1. get https://github.com/Daddoon/Blazor.Polyfill
  2. include it before blazor script tag
  3. profit

I already tried that one. While it works for simple setups like the counter page, my stress test page (which I made for #6385) just never changes from "loading..." to final values: https://github.com/springy76/RazorComponentsProblems/blob/problem/ConnectionDiesWhenUsingAsyncOperations/WebApp/Components/Pages/Index.razor (and so does the real real world app which we're migrating to Razor components).

That's an interesting edge case, I'll try to have a look and try to catch the errors there.
Does the console show any error?

The console only shows timeout after 30s. But I have to revaluate because on my home machine the sample even crashes on Firefox earlier than expected. Maybe I hit the "MessagePack's ReadStringSlow looks broken" problem SteveSandersonMS has mentioned.

yeah, that sounds more like a bug in the message queue than in the browser.

Answering the original question (ie11 polyfills), the mentioned library seems to work well on normal use cases

@javiercn can you please have a look at this and see what prevents us from supporting IE11? Thanks!

Hello! The https://github.com/Daddoon/Blazor.Polyfill solution doesn't work around here (IE11).
Do you know another alternative to try?
I've made an App using Blazor Server Side for the company I work for and found out it doesn't work in IE11. I hope they won't find out it doesn't work or I'll have to redo it again using Webforms (Yes, they still use Webforms for 95% of their apps).

We need something to start working on, can you provide the console errors or some demo repository so we can debug it? Thanks

We need something to start working on, can you provide the console errors or some demo repository so we can debug it? Thanks

The console doesn't show any error, if you want to replicate this, just create a new Server Side Blazor with the latest SDK (Preview 4) and run it.... the reactivity won't work. At least that's how I reproduce it.

@danroth27 Can you update the issue based on our discussion?

OK, I've investigated, and got it to work. But it involved making some changes inside blazor.server.js in addition to the polyfills.

I did:

  • Add core-js polyfills (covers most ES6 stuff): <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.6.5/core.min.js"></script>
  • Add "fetch" polyfill (not part of core-js): <script src="https://polyfill.io/v3/polyfill.min.js?features=fetch"></script>
  • Fix document.baseURI [1]
  • Fix usage of Symbol [2]
  • Fix parseMarkup [3]

[1] Fix document.baseURI

document.baseURI just isn't set on IE11.

Workaround: In UriHelper.ts, change the getBaseURI logic so that instead of just returning document.baseURI, it includes some polyfill logic similar to this, but make sure you actually resolve it to an absolute URI like document.baseURI does.

[2] Fix usage of Symbol

In LogicalElement.ts, we call createSymbolOrFallback to instantiate a Symbol that's then used as a key into elements, e.g., someElement[theSymbol]. For whatever reason, this fails on IE11 with "stack out of range". It might even be a problem in one of the polyfill libraries I was using.

Workaround: change the createSymbolOrFallback logic so that, on IE11, it always uses the "fallback" code path (i.e., just returns a string).

[3] Fix parseMarkup

In BrowserRenderer.ts, we call parseMarkup to transform an HTML markup string into a DocumentFragment. This fails on IE11 because <template> elements lack a content property.

Workaround: replace return sharedTemplateElemForParsing.content; with:

    if (sharedTemplateElemForParsing.content) {
      return sharedTemplateElemForParsing.content;
    } else {
      const result = document.createDocumentFragment();
      while (sharedTemplateElemForParsing.firstChild) {
        result.appendChild(sharedTemplateElemForParsing.firstChild);
      }
      return result;
    }

Proposal

We should implement the three workarounds in our TypeScript code. Then it will be sufficient for people to add polyfills to make the whole thing work.

cc @danroth27

Are you now saying that IE 11 support will only be included in ASP.NET Core 3.1.0? That's very unfortunate.

@Swellenator We know this is a painful cut. Unfortunately we have a deep backlog right now and limited resources to get through it all, so we're scoping back to just the items that absolutely have to get done in order to ship .NET Core 3.0. We'd welcome a PR on this one though.

@danroth27 I figured as much, .NET Core 3.0 is very ambitious in scope.

I think that a PR would be beyond my skills, but hey contributing to .NET would be a great achievement so you never know.

@SteveSandersonMS
Thank you for supporting the required fixes to get it working.
We're currently developing some Intranet applications and we must support IE11. Most of the client PCs are still running Win7 with IE11.
I will try the workaround you mentioned.

Regards
Sven

Update:
I got it working in a different way. For me this seems easier because no modification is needed for blazor.server.js

  1. use Daddoon's Polyfill library
  2. set signalR client side log level in _Host.cshtml
<script src="~/_framework/blazor.server.js"></script>
<script>
    Blazor.start({
        configureSignalR: function (builder) {
            builder.configureLogging(2); // LogLevel.Information
        }
    });
</script>

I don't know why the call to Blazor.start suddenly brings the application up running on IE11 but it seems to be a valid workaround.

Update:
Setting the signalR log level is not really necessary, just call Blazor.start (see below).

Regards
Sven

awesome @sven5 ! It works for me without the explicit configureSignalR

It works around here too... just adding the polyfill and calling

<script>
        Blazor.start();
</script>

The configureSignalR function is not neccesary

since we are calling Blazor.Start() manually, I strongly recommend setting autostart to false:

<script autostart="false" src="~/_framework/blazor.server.js"></script>

Check this link for more info

@isc30 Thanks for clarification. I had some errors without setting autostart to false.

And not forget restart debug ;)

I have made a new release of Blazor.Polyfill , thanks to your code and fix suggestions here.
IE11 should now loaded automatically just by adding the Polyfill.

I don't have managed anything about the autostart attribute on my side, but Blazor.start(); should only be called if IE11 is detected, so you should not have any error conflict on modern browsers even if the autostart attribute is not set.

See the release page of Blazor.Polyfill

@Daddoon I've found an issue with your Polyfill and the latest 3.0.0 Release, that makes Blazor fail when using URLs with parameters.

I attach the demo project as requested by @mkArtakMSFT

RouterIssue.zip

It's basically a default Blazor ServerSide template with the Counter component modified so it takes 1 parameter.
The issue appears when you use URLs with parameters, like this example:

image

This works fine in Chrome & Edge, but in IE11 the URLs that use a parameter don't work, showing this router error, like the URL doesn't exist.

If you browse the app first using a URL without parameters like https://localhost:44340/fetchdata, and then you click in the counter component link it seems to work because the connection is established. The problem appears when you browser directly the counter component, seems that blazor fails to establish a connection to the server.

Regards!

Well, in my opinion it's surely a "bad" idea of my side.

I have done a fix on IE11 that take account what is the base start when a Blazor is not hosted on a simple base root.

However i have missed this type of scenario you are talking about, as i must reference the base path about the page path and not the app subpath.

In the meantime, before i take any action do it properly IF possible, if you take the original source code, you can revert to the previous implementation assuming launching Blazor from a simple base path. So this line:

document.baseURI = window.location.protocol + "//" + window.location.hostname + port + path;

Must be replaced with:

document.baseURI = window.location.protocol + "//" + window.location.hostname + port + "/";

Then it should work with the sample when calling your page with parameters.

I don't know if it is possible to get the real base path of the application URI from IE11 and Websocket if the given starting page is not the base application path. I have to do some test!

We should implement the three workarounds in our TypeScript code. Then it will be sufficient for people to add polyfills to make the whole thing work.

@SteveSandersonMS @Daddoon Are these fixes still needed at this point? If yes, how is BlazorPolyfill working without these fixes?

Hi @danroth27,

EDIT: Concerning your question, BlazorPolyfill is sufficient for running Blazor on IE11. I don't have made test about other old browsers like the one shipped with old Android versions.

TL;DR BlazorPolyfill should be sufficient

Concerning the tests, starting with the last stable Visual Studio 2019 release (16.3.29318.209):

Flat test, without Blazor.polyfill.js:

  • The page "Show" on IE11 but does not work. Actually, i think this is the server-side pre-rendering showing.
  • Clicking on other menu elements does still redirect to the correct page, but it seem to reload the page when doing it.
  • "Fetch data" sample view work
  • Clicking on "Click me" in "Counter page" does not work. No error thrown in the browser.

With Blazor.polyfill.js test:

  • The page does not reload when changing page => Normal Blazor behavior
  • Clicking on "Click me" in "Counter page" does work.

Without Blazor.polyfill.js but forcing window.Blazor.start():

  • Something new happen compared to the flat test, we have "Promise is undefined"
  • Adding Promise and other packaged Polyfills (sorry can't test individually rapidly) without document.baseURI defined return this error: "Unhandled promise rejection Error: undefined is not encodable in msgpack!" just after Blazor websocket connect.
  • Adding document.baseURI property defined is not enough. We have:

    • [2019-09-25T12:11:58.680Z] Error: There was an error applying batch 2.
    • Unhandled promise rejection Error: There is no browser renderer with ID 0.
    • [2019-09-25T12:11:58.754Z] Error: There was an unhandled exception on the current circuit, so this circuit will be terminated. For more details turn on detailed exceptions in 'CircuitOptions.DetailedErrors'.
    • [2019-09-25T12:11:58.756Z] Information: Connection disconnected.
  • Calling "Symbol.useSimple();" from core-js polyfill does fix the previous error. Also i tested that if i use it, but don't set document.baseURI, it still not working, the two fix are required.

Conclusion:

In actual release IE11 need:

  • Promise polyfill
  • core-js "Symbol.useSimple()"
  • document.baseURI defined
  • window.Blazor.start(); must be call explicitly

Maybe some other polyfills are required, i mean, i have tested individually a long time ago, but it was with the asmjs support, so there is maybe less requirement today.

But the 4 mentionned here seem still mandatory.

BlazorPolyfill does include theses requirements.

@chrdlx I fixed the issue you mentionned. It should work right with root and not root path now on IE11.

See the release here.

@Daddoon Beautiful !! Thank you very much!!

We will need to make sure this is covered too: https://github.com/aspnet/AspNetCore/issues/14784 as part of this work.

@mkArtakMSFT According to what i see in the closed issue you mentionned, does this mean that Blazor will transpile Javascript code automatically at build time in the future, as a standard build subset ?

@Daddoon No, there is nothing about transpilation here.

@SteveSandersonMS Sorry! So IMO, the referenced issue here (#14784) is just an usage of an ECMAScript version unsupported by IE11, by the original issuer. I think there is nothing to do. But i mean, that's why i thought we were maybe talking about transpilation.

Sorry again!

Oh I see! Yes you’re right. In the linked issue, the person was using the wrong syntax for IE11, so I agree there’s nothing for us to do with that.

Yeah sorry about raising that issue. It was a mistake on my side. I appreciate the help in resolving that though

I could use some help here. I created a Blazor serverside project (using the code as generated).

In _Host.cshtml I added:

    <script src="_framework/blazor.server.js"></script>
    <![if !IE]>
        <script src="blazor.polyfill.js" type="text/javascript">
            window.Blazor.Start();
        </script>
    <![endif]>

However, the [@onclick="IncrementCount"] still does not work. What am I missing? I downloaded the blazor.polyfill.js from https://github.com/Daddoon/Blazor.Polyfill/releases/tag/3.0.0

Followup:
The counter now works in IE11, but I get this error on exit:

Unhandled exception at line 8, column 102493 in https://localhost:44350/_framework/blazor.server.js
0x800a01b6 - JavaScript runtime error: Object doesn't support property or method 'sendBeacon' occurred

My _Host.cshtml has this now:

    <script type="text/javascript" src="blazor.polyfill.js"></script>
    <script src="_framework/blazor.server.js"></script>
    <script>
        Blazor.start();
    </script>

How can I get rid of the 'sendBeacon' error?

Please note that this polyfill is not something supported officially by Microsoft.

TL;DR I don't know yet how to avoid this error with Blazor.Polyfill

As stated on my repo:

For Blazor in Server-side mode

<script type="text/javascript" src="blazor.polyfill.min.js"></script>
<script src="_framework/blazor.server.js"></script>

And that's all. The polyfill should handle the Blazor.start() by itself.

For that sendBeacon error, i think this is something that my polyfill don't manage, and i have never tried to see on what this is related, and if i can do something on this error.

However, in the current state, the Blazor server-side app on IE11 work even with this error.
But thanks for your post, i will try to take a look, to see if i can integrate a polyfill for sendBeacon on my library.

EDIT: Opened an issue here: https://github.com/Daddoon/Blazor.Polyfill/issues/12
I will come back soon here if i'm able to do a fix on that.

Thanks. If I can ignore the error, that is fine for now.

I think one aspect MS fails to adequately recognize is that a LOT of government agencies and large companies are still standardized on IE 11. The cost to retrain and make Edge or another browser the standard is quite large, and not a high priority as long as line-of-business apps work on IE 11.

That means that internal development teams and consultants/contractors that want to start pushing our Blazor serverside apps, cannot do so if IE 11 is not fully supported on Blazor Serverside. The end result for MS is a delayed or no adoption of Blazor for wasm, and potentially the MS stack gets replaced by other wasm stacks that do support IE 11.

I and most users of IE 11 understand the browser is end-of-lifed and no longer supported for new functionality, like a wasm engine. But adoption of a modern browser is slowed by the cost for governments and large companies.

I think MS was on it but mainly more focused about releasing the RTM of .NET Core 3.0 (Including Blazor server-side). And as polyfills can workaround the missing features, i think this is fine that they don't have priotized this.

Btw, Navigator.sendBeacon seem polyfillable as it's a browser feature and not something related to Blazor and that some polyfills exists like this one on NPM.

I'm taking a look on this right now as i have some time right now. I will release an update shortly if this work correctly on the sample.

I don't know where sendBeacon is used, but i think this may be used to sync some browser states when reconnecting for the current session but this is just an assumption.

@MSBassSinger Done.

See the release here: https://github.com/Daddoon/Blazor.Polyfill/releases/tag/3.0.1

I don't see the error anymore since the polyfill included.

Thanks. I am trying to prove to my employer (a consulting company that builds websites for a major federal agency) that it is safe to start shifting to Blazor serverside. Getting IE11 usable is the one big obstacle.

Good luck with your Employer.

At least, with Blazor WASM, you can prove to your employer that Blazor is future proof, as if IE11 support drop one day, you will still be on the boat with a cutting edge technology in browser !

Most assuredly! And your fix took care of it. As we say down here in the South, "I am cooking with gas!"

@MSBassSinger

<![if !IE]>
      <script src="blazor.polyfill.js" type="text/javascript">
      </script>
  <![endif]>

To me this reads: "If not using InternetExploder then insert polyfill"

Even with @Daddoon's polyfill (a great help, many thanks), we've had a problem with s/s Blazor with IE11 when the root component is hosted on a page which isn't at the root path /. (This is on 3.1 preview 3)

What happens is that SignalR tries to connect to http://localhost/our/path/_blazor, rather than http://localhost/_blazor which is what all the modern browsers do.

I gave up trying to work out why this was (TBH, I'm not 100% why it works on the modern browsers) and just added the following rewrite rule to Startup (before app.UseRouting():

app.UseRewriter(new RewriteOptions().AddRewrite("^.*_blazor(.*)", "/_blazor$1", true));

You might fancy a more sophisticated re-write rule, as this one could be a bit enthusiastic.

This might be useful to someone, if you get to a point where you're seeing 404 errors from the Blazor SignalR connection.

Are you sure you are using a recent version of my polyfill ? I had fixed something about a similar issue some weeks ago.

Do you have a repro project with this bug ? If i can fix something about it, it would be better.

@Daddoon - I'm not sure it's fixable in your polyfill, but if I can build a simple repro then I'll open an issue on your repro for you to look at.

Thanks !

Le mer. 20 nov. 2019 à 23:51, Will Dean notifications@github.com a écrit :

@Daddoon https://github.com/Daddoon - I'm not sure it's fixable in your
polyfill, but if I can build a simple repro then I'll open an issue on your
repro for you to look at.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/aspnet/AspNetCore/issues/9436?email_source=notifications&email_token=AFS5ALW6G43UNFOZXT762QTQUW5NNA5CNFSM4HGOFMDKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEEV2UJQ#issuecomment-556509734,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AFS5ALTPKXRNS23EDU5AJHLQUW5NNANCNFSM4HGOFMDA
.

@Daddoon Thank-you for pushing me to create a repro. This lead to the discovery that the problem was the base element being in the body of the page, not the head - i.e. entirely my fault... Thanks for the help.

@willdean No problems, good to know it was a tag issue on your side. For a next update, maybe i should add a log error in the console mentionning the missing base tag, then if it's omitted it would be at least written in the browser console!

I released a new version of the polyfill:

https://github.com/Daddoon/Blazor.Polyfill

  • Added an error in the console if the base tag is not found on IE
  • Re-added core-js in the library
  • Updated the documentation: You can now safely remove core-js external reference if you added it previously, but otherwise, it's recommended to only add the polyfill on a IE11 browser.

So to install, as stated in the updated doc:

<script type="text/javascript">
    if (/MSIE \d|Trident.*rv:/.test(navigator.userAgent)) {
        document.write('<script src="js/blazor.polyfill.min.js"><\/script>');
    }
</script>
<script src="_framework/blazor.server.js"></script>

...considering you have copied the file in a wwwroot/js folder.

I tried the polyfill and it seems to work absolutely fine, thanks @Daddoon

The questions really is why can't this be adopted as the official way to support IE11 in the upcoming release?

@andy-davies as far as I know, the IE11 support is just a bunch of polyfills.
I don't think AspNetCore team wants to stick to specific polyfills as a official support

@isc30 Yes, the IE11 support is a polyfill but I don't see a problem with that as they are pretty standard in web development. Angular is an example of a major project that uses polyfills to provide support for IE.

Obviously I'd rather MS just dropped IE altogether... but that's a different topic ;-)

We're closing this issue as we don't plan to do anything here. Polyfill support is what we recommend in this case.

Was this page helpful?
0 / 5 - 0 ratings