Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
297 views
in Technique[技术] by (71.8m points)

c# - How do ASP.NET Core's "asp-fallback-*" CDN tag helpers work?

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

TL;DR:

  • A <meta> tag is added to the DOM that has a CSS class of sr-only.
  • Additional JavaScript is written to the DOM, which:
    1. Locates said <meta> element.
    2. Checks whether said element has a CSS property position that is set to absolute.
    3. If no such property value is set, an additional <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:

  • The last line of the comment, which refers to placeholders {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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...