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
361 views
in Technique[技术] by (71.8m points)

c# - Apply Google AMP (Accelerated Mobile Pages) to ASP.NET Core site

I'm trying to create an AMP page with ASPNET Core MVC. I haven't been able to find many documents if any. For ASPNET, it was suggested to use DisplayModes to create a Google AMP Display. However, ASPNet Core doesn't support DisplayModes and I'm trying to figure a way to work around it. Any suggestions would be greatly appreciated!

@model Models.Article
@{
    Layout = null;
}

<!doctype html>
<html amp>
    <head>
        <meta charset="utf-8">
        <link rel="canonical" href="/article.cshtml">
        <link rel="amphtml" href="/article.amp.cshtml">
        <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
        <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style>
        <noscript>
        <style amp-boilerplate>
          body {
          -webkit-animation: none;
          -moz-animation: none;
          -ms-animation: none;
          animation: none
          }
    </style></noscript>
    <script async src="https://cdn.ampproject.org/v0.js"></script>
    </head>
    <body>
        <article>
            <h2>@Html.DisplayFor(model => model.Title)</h2>
            <div>@Convert.ToDateTime(Model.PublishedDate).ToString("dddd, MMMM d, yyyy")</div>
        </article>    
    </body>
</html>
See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

There are a few ways to achieve something like this. One possibility would be to dynamically change your layout depending on the route, i.e. use template X for AMP or Y otherwise.

A more powerful solution would be the view location expander. This is also generally considered as a successor to the display modes. The view location expander is basically a mechanism that allows you to post-process the physical locations where the Razor engine will look for views. So you can use this to conditionally modify or expand the paths where your views are located.

In your case, you might want to change the behavior so that when accessing your site through AMP, Razor should first look for a <view>.amp.cshtml before falling back to <view>.cshtml.

In order to do that, you would have to implement IViewLocationExpander. In PopulateViews you would have to detect whether you are within AMP mode or not; and in ExpandViewLocations you could then modify the view locations.

That could look somewhat like this (untested, as an idea on how to approach this):

public class AmpViewLocationExpander : IViewLocationExpander
{
    private const string ValueKey = "ampmode";

    public void PopulateValues(ViewLocationExpanderContext context)
    {
        // magic utility method that determines whether this is within an AMP context
        var isAmp = context.ActionContext.HttpContext.IsAmp();

        // persist the value on the context to allow the cache to consider this
        context.Values[ValueKey] = isAmp.ToString();
    }

    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context,
        IEnumerable<string> viewLocations)
    {
        // when in AMP mode
        if (context.Values.TryGetValue(ValueKey, out var isAmpValue) && isAmpValue == "True")
        {
            return ExpandAmpViewLocations(viewLocations);
        }

        // otherwise fall back to default locations
        return viewLocations;
    }

    private IEnumerable<string> ExpandAmpViewLocations(IEnumerable<string> viewLocations)
    {
        foreach (var location in viewLocations)
        {
            // yield the AMP version first
            yield return location.Replace("{0}", "{0}.amp");

            // then yield the normal version as a fallback
            yield return location;
        }
    }
}

Once you have that, you only have to register the expander after the AddMvc call within your ConfigureServices:

services.AddMvc()
    .AddRazorOptions(options =>
    {
        options.ViewLocationExpanders.Add(new AmpViewLocationExpander());
    });

And then you only need to create your alternate views for AMP.


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

...