首页 > 解决方案 > 如何将 IViewLocationExtender 与 Razor 页面一起使用来呈现设备特定页面

问题描述

目前我们正在构建一个 web 应用程序,首先是桌面,它需要特定页面的设备特定 Razor 页面。这些页面与它们的桌面版本确实不同,在这里使用响应性是没有意义的。

我们已经尝试实现我们自己的 IViewLocationExpander 并且还尝试使用 MvcDeviceDetector 库(基本上是这样做的)。设备类型的检测没有问题,但由于某种原因,设备特定页面没有被拾取,并且不断回退到默认的 Index.cshtml。(编辑:我们正在考虑基于 IPageConvention、IPageApplicationModelProvider 或其他东西实现一些东西...... ;-)

索引.mobile.cshtml 索引.cshtml

我们使用 MvcDeviceDetector 的示例添加了以下代码:

public static IMvcBuilder AddDeviceDetection(this IMvcBuilder builder)
{
    builder.Services.AddDeviceSwitcher<UrlSwitcher>(
    o => { },
    d => {
            d.Format = DeviceLocationExpanderFormat.Suffix;
            d.MobileCode = "mobile";
        d.TabletCode = "tablet";
    }
    );

    return builder;
}

并正在添加一些路线映射

routes.MapDeviceSwitcher();

我们希望在 Chrome 中选择 Phone Emulation 时看到 Index.mobile.cshtml 被拾取,但这并没有发生。

编辑注:

编辑 2 我认为解决方案与您实施特定于文化的 Razor Pages 的方式相同(我们也不知道 ;-))。基本 MVC 支持 Index.en-US.cshtml

下面的最终解决方案

标签: asp.net-corerazor-pagesdevice-detection

解决方案


如果这是一个 Razor Pages 应用程序(相对于 MVC 应用程序),我认为该IViewLocationExpander界面对您没有多大用处。据我所知,它只适用于部分页面,而不适用于可路由页面(即带有@page指令的页面)。

您可以做的是使用中间件来确定请求是否来自移动设备,然后将要执行的文件更改为以.mobile. 这是一个非常粗略且现成的实现:

public class MobileDetectionMiddleware
{
    private readonly RequestDelegate _next;

    public async Task Invoke(HttpContext context)
    {
        if(context.Request.IsFromAMobileDevice())
        {
            context.Request.Path = $"{context.Request.Path}.mobile";
        }
        await _next.Invoke(context);
    }
}

由您决定如何实现该IsFromAMobileDevice方法来确定用户代理的性质。没有什么可以阻止您使用可以为您可靠地进行检查的第三方库。此外,您可能只想在某些条件下更改路径 - 例如存在请求页面的设备特定版本的地方。

Configure尽早在您的方法中注册:

app.UseMiddleware<MobileDetectionMiddleware>();

推荐阅读