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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…