Автоматическое переключение представлений для AMP в ASP.NET MVC

Я хочу создать AMP-версию своего веб-сайта в ASP.NET MVC с использованием .NET Core 2.0. Раньше я работал с экземплярами DisplayModeProvider в прошлом на платформе .Net, но, похоже, это не вариант в .NET Core.

Что я хочу сделать, так это изменить имена представлений на index.amp.cshtml, а не index.cshtml, когда мой URL-адрес начинается с /amp. Как лучше всего добиться этого в .NET Core?


person kieszen    schedule 06.03.2018    source источник


Ответы (2)


Вы можете сделать что-то подобное, используя IViewLocationExpander. Так случилось, что я играл с этим несколько дней назад, поэтому у меня есть несколько примеров кода. Если вы создадите что-то вроде этого:

public class AmpViewLocationExpander : IViewLocationExpander
{
    public void PopulateValues(ViewLocationExpanderContext context)
    {
        var contains = context.ActionContext.HttpContext.Request.Query.ContainsKey("amp");
        context.Values.Add("AmpKey", contains.ToString());

        var containsStem = context.ActionContext.HttpContext.Request.Path.StartsWithSegments("/amp");
        context.Values.Add("AmpStem", containsStem.ToString());
    }

    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        if (!(context.ActionContext.ActionDescriptor is ControllerActionDescriptor descriptor)) { return viewLocations; }

        if (context.ActionContext.HttpContext.Request.Query.ContainsKey("amp")
            || context.ActionContext.HttpContext.Request.Path.StartsWithSegments("/amp")
        )
        {
            return viewLocations.Select(x => x.Replace("{0}", "{0}.amp"));
        }

        return viewLocations;
    }
}

iViewLocationExpander можно найти в Microsoft.AspNetCore.Mvc.Razor

Затем в методе Configure Services в Startup.cs добавьте следующее:

  services.Configure<RazorViewEngineOptions>(options =>
        {
            options.ViewLocationExpanders.Add(new AmpViewLocationExtender());
        });

Что это будет делать, так это обновлять местоположения просмотра для каждого запроса, чтобы вставить .amp перед .cshtml в любое время, когда URL-адрес либо начинается с /amp, либо есть ключ строки запроса amp. Если ваших представлений AMP не существует, он может немного взорваться, я не тестировал его полностью, но он должен помочь вам начать работу.

person mnield    schedule 06.03.2018
comment
Спасибо @mnield! Есть ли способ ограничить это, чтобы исключить страницы макета и частичные просмотры? Не специально для AMP, но я думаю, что это хороший способ предоставить альтернативные представления. - person kieszen; 13.03.2018
comment
Привет @kieszen, да, конечно. вы можете добавить if (!context.IsMainPage) return viewLocations; в начало ExpandViewLocations. Это исключит страницы макета и их части. Я не совсем уверен, что вы можете сделать это более детально. - person mnield; 13.03.2018
comment
@mnield Я подумал, что было бы полезно перенаправить весь мобильный трафик на версию сайта с усилителем, вы согласны? - person prospector; 21.05.2018
comment
@prospector, в некотором смысле, это так. В реализации, с которой я экспериментировал, представления, используемые для навигации и т. д., относились к AMP-версии сайта. Таким образом, как только amp находится в URL-адресе, вы всегда получаете эти ссылки. Чего бы я не хотел, так это заставить его всегда быть AMP. Я не нахожу ничего более разочаровывающего, чем, например, вынужденный просмотр сайта в мобильной версии, когда он менее функционален, чем десктопный. - person mnield; 22.05.2018
comment
@mnield Я понимаю твою точку зрения. Большинство моих веб-сайтов, которые я разрабатываю, предназначены для привлечения потенциальных клиентов, а время загрузки — это деньги, поэтому для своей работы я недавно несколько часов назад принудительно перенаправлял на AMP, но для более информационных сайтов я согласен, я бы просто использовал адаптивный дизайн. - person prospector; 22.05.2018

Вы можете определить это Middleware :

public class AmpMiddleware
{
    private RequestDelegate _next;

    public AmpMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    public Task Invoke(HttpContext context)
    {
        const string ampTag = "/amp";

        var path = context.Request.Path;
        if (path.HasValue)
        {
            var ampPos = path.Value.IndexOf(ampTag);
            if (ampPos >= 0)
            {
                context.Request.Path = new PathString(path.Value.Remove(ampPos, ampTag.Length));
                context.Items.Add("amp", "true");
            }
        }
        return _next(context);
    }
}

public static class BuilderExtensions
{
    public static IApplicationBuilder UseAmpMiddleware(this IApplicationBuilder app)
    {
        return app.UseMiddleware<AmpMiddleware>();
    }
}

И назовите это в Startup:

app.UseAmpMiddleware();

Затем можно зайти на страницу и просто установить другой макет или ограничить некоторый код, в этом случае нет необходимости создавать отдельную страницу для версии усилителя:

@if (HttpContext.Items.ContainsKey("amp"))
{
    <b>Request AMP Version</b>
}
person MohsenB    schedule 17.12.2020