ASP.NET Core MVC 修改视图的默认路径及其实现原理解析

本章将和大家分享如何在ASP.NET Core MVC中修改视图的默认路径,以及它的实现原理。

导语:在日常工作过程中你可能会遇到这样的一种需求,就是在访问同一个页面时PC端和移动端显示的内容和风格是不一样(类似两个不一样的主题),但是它们的后端代码又是差不多的,此时我们就希望能够使用同一套后端代码,然后由系统自动去判断到底是PC端访问还是移动端访问,如果是移动端访问就优先匹配移动端的视图,在没有匹配到的情况下才去匹配PC端的视图。

下面我们就来看下这个功能要如何实现,Demo的目录结构如下所示:

龙方网络

本Demo的Web项目为ASP.NET Core Web 应用程序(目标框架为.NET Core 3.1) MVC项目。

首先需要去扩展视图的默认路径,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Razor;

namespace NETCoreViewLocationExpander.ViewLocationExtend
{
    /// <summary>
    /// 视图默认路径扩展
    /// </summary>
    public class TemplateViewLocationExpander : IViewLocationExpander
    {
        /// <summary>
        /// 扩展视图默认路径(PS:并非每次请求都会执行该方法)
        /// </summary>
        /// <param name="context"></param>
        /// <param name="viewLocations"></param>
        /// <returns></returns>
        public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
        {
            var template = context.Values["template"] ?? TemplateEnum.Default.ToString();
            if (template == TemplateEnum.WeChatArea.ToString())
            {
                string[] weChatAreaViewLocationFormats = {
                    "/Areas/{2}/WeChatViews/{1}/{0}.cshtml",
                    "/Areas/{2}/WeChatViews/Shared/{0}.cshtml",
                    "/WeChatViews/Shared/{0}.cshtml"
                };
                //weChatAreaViewLocationFormats值在前--优先查找weChatAreaViewLocationFormats(即优先查找移动端目录)
                return weChatAreaViewLocationFormats.Union(viewLocations);
            }
            else if (template == TemplateEnum.WeChat.ToString())
            {
                string[] weChatViewLocationFormats = {
                    "/WeChatViews/{1}/{0}.cshtml",
                    "/WeChatViews/Shared/{0}.cshtml"
                };
                //weChatViewLocationFormats值在前--优先查找weChatViewLocationFormats(即优先查找移动端目录)
                return weChatViewLocationFormats.Union(viewLocations);
            }

            return viewLocations;
        }

        /// <summary>
        /// 往ViewLocationExpanderContext.Values里面添加键值对(PS:每次请求都会执行该方法)
        /// </summary>
        /// <param name="context"></param>
        public void PopulateValues(ViewLocationExpanderContext context)
        {
            var userAgent = context.ActionContext.HttpContext.Request.Headers["User-Agent"].ToString();
            var isMobile = IsMobile(userAgent);
            var template = TemplateEnum.Default.ToString();
            if (isMobile)
            {
                var areaName = //区域名称
                    context.ActionContext.RouteData.Values.ContainsKey("area")
                    ? context.ActionContext.RouteData.Values["area"].ToString()
                    : "";
                var controllerName = //控制器名称
                    context.ActionContext.RouteData.Values.ContainsKey("controller")
                    ? context.ActionContext.RouteData.Values["controller"].ToString()
                    : "";
                if (!string.IsNullOrEmpty(areaName) &&
                    !string.IsNullOrEmpty(controllerName)) //访问的是区域
                {
                    template = TemplateEnum.WeChatArea.ToString();
                }
                else
                {
                    template = TemplateEnum.WeChat.ToString();
                }
            }

            context.Values["template"] = template; //context.Values会参与ViewLookupCache缓存Key(cacheKey)的生成
        }

        /// <summary>
        /// 判断是否是移动端
        /// </summary>
        /// <param name="userAgent"></param>
        /// <returns></returns>
        protected bool IsMobile(string userAgent)
        {
            userAgent = userAgent.ToLower();
            if (userAgent == "" ||
                userAgent.IndexOf("mobile") > -1 ||
                userAgent.IndexOf("mobi") > -1 ||
                userAgent.IndexOf("nokia") > -1 ||
                userAgent.IndexOf("samsung") > -1 ||
                userAgent.IndexOf("sonyericsson") > -1 ||
                userAgent.IndexOf("mot") > -1 ||
                userAgent.IndexOf("blackberry") > -1 ||
                userAgent.IndexOf("lg") > -1 ||
                userAgent.IndexOf("htc") > -1 ||
                userAgent.IndexOf("j2me") > -1 ||
                userAgent.IndexOf("ucweb") > -1 ||
                userAgent.IndexOf("opera mini") > -1 ||
                userAgent.IndexOf("android") > -1 ||
                userAgent.IndexOf("transcoder") > -1)
            {
                return true;
            }

            return false;
        }
    }

    /// <summary>
    /// 模板枚举
    /// </summary>
    public enum TemplateEnum
    {
        Default = 1,
        WeChat = 2,
        WeChatArea = 3
    }
}

郑重声明:本文版权包含图片归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们(delete@yzlfxy.com)修改或删除,多谢。

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

留言与评论(共有 0 条评论)
昵称:
匿名发表
   
验证码: