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

醉酒当歌 提交于 2019-11-30 09:08:44

问题


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>

回答1:


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.



来源:https://stackoverflow.com/questions/53732980/apply-google-amp-accelerated-mobile-pages-to-asp-net-core-site

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!