I understand what the asp-fallback-*
tag helpers do. What I don't understand is how.
For example:
<link rel="stylesheet" href="//ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/css/bootstrap.min.css" asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css" asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
This loads bootstrap from the CDN, and loads the local copy if the CDN is down.
But how does it decide to do that? I assume it checks asp-fallback-test-class
, asp-fallback-test-property
, and asp-fallback-test-value
. But what do those attributes mean?
If I want to hook up some other library off a CDN, I'll need to supply something for those, but I'm not sure what to put there.
There are lots of examples of this in action, but I can't find explanations about how this works.
UPDATE
I'm not really trying to understand how the tag helpers work - how they render, and so on. I'm trying to understand how to choose values for those attributes. For example, the jQuery fallback script usually has asp-fallback-test="window.jQuery"
which makes sense - it's a test to see if jQuery has loaded. But the ones I've shown above are quite different. How does one choose them? If I want to use some other CDN delivered library, I'll need to specify values for those attributes... what would I use? Why were those ones chosen for bootstrap?
UPDATE 2
To understand how the fallback process itself works, and how those tags are written, see @KirkLarkin's answer. To understand why those test values were used, see my answer.
asp-fallback-srcThe URL of a Script tag to fallback to in the case the primary one fails.
asp-fallback-test - the JavaScript code to run that should evaluate to a "truthy" value if the script was loaded correctly. asp-fallback-src - The URL of the file to load if the test fails.
The Anchor Tag Helper enhances the standard HTML anchor ( <a ... > </a> ) tag by adding new attributes. By convention, the attribute names are prefixed with asp- . The rendered anchor element's href attribute value is determined by the values of the asp- attributes.
A Tag Helper Component is a Tag Helper that allows you to conditionally modify or add HTML elements from server-side code. This feature is available in ASP.NET Core 2.0 or later. ASP.NET Core includes two built-in Tag Helper Components: head and body . They're located in the Microsoft. AspNetCore.
TL;DR:
<meta>
tag is added to the DOM that has a CSS class of sr-only
.<meta>
element.position
that is set to absolute
.<link>
element is written to the DOM with a href
of ~/lib/bootstrap/dist/css/bootstrap.min.css
.The LinkTagHelper
class that runs against your <link>
elements inserts a <meta>
element in the output HTML that is given a CSS class of sr-only
. The element ends up looking like this:
<meta name="x-stylesheet-fallback-test" content="" class="sr-only" />
The code that generates the element looks like this (source):
builder .AppendHtml("<meta name=\"x-stylesheet-fallback-test\" content=\"\" class=\"") .Append(FallbackTestClass) .AppendHtml("\" />");
Unsurprisingly, the value for FallbackTestClass
is obtained from the <link>
's asp-fallback-test-class
attribute.
Right after this element is inserted, a corresponding <script>
block is also inserted (source). The code for that starts off like this:
// Build the <script /> tag that checks the effective style of <meta /> tag above and renders the extra // <link /> tag to load the fallback stylesheet if the test CSS property value is found to be false, // indicating that the primary stylesheet failed to load. // GetEmbeddedJavaScript returns JavaScript to which we add '"{0}","{1}",{2});' builder .AppendHtml("<script>") .AppendHtml(JavaScriptResources.GetEmbeddedJavaScript(FallbackJavaScriptResourceName)) .AppendHtml("\"") .AppendHtml(JavaScriptEncoder.Encode(FallbackTestProperty)) .AppendHtml("\",\"") .AppendHtml(JavaScriptEncoder.Encode(FallbackTestValue)) .AppendHtml("\",");
There are a few things of interest here:
{0}
, {1}
and {2}
.FallbackJavaScriptResourceName
, which represents a JavaScript resource that is output into the HTML.FallbackTestProperty
and FallbackTestValue
, which are obtained from the attributes asp-fallback-test-property
and asp-fallback-test-value
respectively.So, let's have a look at that JavaScript resource (source), which boils down to a function with the following signature:
function loadFallbackStylesheet(cssTestPropertyName, cssTestPropertyValue, fallbackHrefs, extraAttributes)
Combining this with the last line of the comment I called out earlier and the values of asp-fallback-test-property
and asp-fallback-test-value
, we can reason that this is invoked like so:
loadFallbackStylesheet('position', 'absolute', ...)
I won't dig into the fallbackHrefs
and extraAttributes
parameters as that should be somewhat obvious and easy to explore on your own.
The implementation of loadFallbackStylesheet
does not do a great deal - I encourage you to explore the full implementation on your own. Here's the actual check from the source:
if (metaStyle && metaStyle[cssTestPropertyName] !== cssTestPropertyValue) { for (i = 0; i < fallbackHrefs.length; i++) { doc.write('<link href="' + fallbackHrefs[i] + '" ' + extraAttributes + '/>'); } }
The script obtains the relevant <meta>
element (it's assumed to be directly above the <script>
itself) and simply checks that it has a property of position
that is set to absolute
. If it does not, additional <link>
elements are written to the output for each fallback URL.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With