Maison  >  Article  >  développement back-end  >  Exemple de tutoriel de réécriture ASP.NET MVC

Exemple de tutoriel de réécriture ASP.NET MVC

零下一度
零下一度original
2017-07-02 10:35:072101parcourir

Cet article présente principalement ASP.NET MVC pour réécrire RazorViewEngine pour réaliser une commutation multithème en détail. Il a une certaine valeur de référence. Les amis intéressés peuvent se référer à

dans ASP.NET MVC. Il existe généralement deux manières. pour changer de thème en Chine, l'une consiste à changer les références css et js du skin, et l'autre à réécrire le moteur d'affichage. Il est plus flexible en réécrivant le moteur d'affichage, car je peux non seulement avoir différentes mises en page et styles sous différents thèmes, mais également rendre les éléments de données affichés sous différents thèmes incohérents, ce qui signifie que je peux ajouter du contenu personnalisé sous certains thèmes.

Dans cet article, je vais faire une démonstration en réécrivant le moteur de vue. Avant de faire cela, je suppose que vous avez déjà quelques bases de MVC. Jetons d'abord un coup d'œil à l'effet :

Système après. lors de la connexion, c'est le thème par défaut. Lorsque l'on clique pour changer de thème, la disposition de la barre de menu à gauche change, le style du contenu à droite change également, mais la barre d'adresse reste inchangée. Metronic est utilisé pour l'interface utilisateur. Bien que le site officiel facture des frais, vous pouvez toujours le trouver gratuitement en Chine. Adresse officielle : http://keenthemes.com/preview/metronic/

Ici, j'ai utilisé sous-région et sous-module (Divisé par des fonctions métier indépendantes), un module est une DLL indépendante. Ici, Secom.Emx.Admin et Secom.Emx.History sont deux modules indépendants, et les zones Admin et History sont créées respectivement.

Vous constaterez que le répertoire Areas sous le modèle Secom.Emx.Admin est exactement le même que le répertoire dans Secom.Emx.WebApp. Au départ, je ne voulais pas l'ajouter au module Ajouter une vue au projet, mais il est ajouté pour faciliter le déploiement indépendant.

Cliquez droit sur le projet Secom.Emx.Admin, sélectionnez "Propriétés" - "Générer un événement" et ajoutez le code suivant :


xcopy /e/r/y $(ProjectDir)Areas\Admin\Views 
$(SolutionDir)Secom.Emx.WebApp\Areas\Admin\Views

Cette commande C'est très simple. En fait, lors de la compilation du projet Secom.Emx.Admin, copiez les vues du projet dans le répertoire spécifié du projet Secom.Emx.WebApp.

ZoneFichier de configuration Je l'ai placé dans Secom.Emx.WebApp. En fait, vous pouvez le placer indépendamment dans un projet de bibliothèque de classes grâce à. zone d'enregistrement Après le routage, le projet recherchera éventuellement tous ceux du répertoire bin qui héritent de la classe AreaRegistration, puis laissera WebApp référencer ce projet de bibliothèque de classes. Le projet Secom.Emx.WebApp ajoute des références à Secom.Emx.Admin et Secom. .Emx.Historique.

Le code AdminAreaRegistration est le suivant :


using System.Web.Mvc;

namespace Secom.Emx.WebApp
{
 public class AdminAreaRegistration : AreaRegistration 
 {
  public override string AreaName 
  {
   get 
   {
    return "Admin";
   }
  }

  public override void RegisterArea(AreaRegistrationContext context) 
  {
   context.MapRoute(
    "Admin_default",
    "Admin/{controller}/{action}/{id}",
    new { action = "Index", id = UrlParameter.Optional },
    namespaces:new string[1] { "Secom.Emx.Admin.Areas.Admin.Controllers" }
   );
  }
 }
}

Notez l'espace de noms et ceux ajoutés plus tard namespaces:new string[1] { "Secom.Emx.Admin.Areas.Admin.Controllers" >, cet espace de noms est indépendant module L'espace de noms où se trouvent les contrôleurs sous Secom.Emx.Admin.

Le code HistoryAreaRegistration est le suivant :


using System.Web.Mvc;

namespace Secom.Emx.WebApp
{
 public class HistoryAreaRegistration : AreaRegistration 
 {
  public override string AreaName 
  {
   get 
   {
    return "History";
   }
  }

  public override void RegisterArea(AreaRegistrationContext context) 
  {
   context.MapRoute(
    "History_default",
    "History/{controller}/{action}/{id}",
    new { action = "Index", id = UrlParameter.Optional },
    namespaces:new string[1] { "Secom.Emx.History.Areas.History.Controllers" }
   );
  }
 }
}

Examinons d'abord le constructeur original de RazorViewEngine comme suit :


public RazorViewEngine(IViewPageActivator viewPageActivator) 
  : base(viewPageActivator) 
 { 
  AreaViewLocationFormats = new[] 
  { 
   "~/Areas/{2}/Views/{1}/{0}.cshtml", 
   "~/Areas/{2}/Views/{1}/{0}.vbhtml", 
   "~/Areas/{2}/Views/Shared/{0}.cshtml", 
   "~/Areas/{2}/Views/Shared/{0}.vbhtml" 
  }; 
  AreaMasterLocationFormats = new[] 
  { 
   "~/Areas/{2}/Views/{1}/{0}.cshtml", 
   "~/Areas/{2}/Views/{1}/{0}.vbhtml", 
   "~/Areas/{2}/Views/Shared/{0}.cshtml", 
   "~/Areas/{2}/Views/Shared/{0}.vbhtml" 
  }; 
  AreaPartialViewLocationFormats = new[] 
  { 
   "~/Areas/{2}/Views/{1}/{0}.cshtml", 
   "~/Areas/{2}/Views/{1}/{0}.vbhtml", 
   "~/Areas/{2}/Views/Shared/{0}.cshtml", 
   "~/Areas/{2}/Views/Shared/{0}.vbhtml" 
  }; 
  
  ViewLocationFormats = new[] 
  { 
   "~/Views/{1}/{0}.cshtml", 
   "~/Views/{1}/{0}.vbhtml", 
   "~/Views/Shared/{0}.cshtml", 
   "~/Views/Shared/{0}.vbhtml" 
  }; 
  MasterLocationFormats = new[] 
  { 
   "~/Views/{1}/{0}.cshtml", 
   "~/Views/{1}/{0}.vbhtml", 
   "~/Views/Shared/{0}.cshtml", 
   "~/Views/Shared/{0}.vbhtml" 
  }; 
  PartialViewLocationFormats = new[] 
  { 
   "~/Views/{1}/{0}.cshtml", 
   "~/Views/{1}/{0}.vbhtml", 
   "~/Views/Shared/{0}.cshtml", 
   "~/Views/Shared/{0}.vbhtml" 
  }; 
  
  FileExtensions = new[] 
  { 
   "cshtml", 
   "vbhtml", 
  }; 
 }

Créez ensuite un nouveau CustomRazorViewEngine qui hérite de RazorViewEngine et réécrit les règles de routage de View. Puisque les règles de routage peuvent être réécrites, cela signifie que vous pouvez définir les règles arbitrairement. puis respectez-les. Il convient de noter qu'il faut prêter attention à l'ordre dans le tableau de routage lors de la recherche de la vue, elle est recherchée dans l'ordre avant et arrière. Lorsque la vue est trouvée, elle sera renvoyée immédiatement et ne correspondra pas à celle-ci. règles de routage ultérieures. Afin d'améliorer l'efficacité de la recherche d'itinéraire, j'ai supprimé ici toutes les règles de routage vbhtml, car j'utilise le langage C# dans l'ensemble du projet.


using System.Web.Mvc;

namespace Secom.Emx.WebApp.Helper
{
 public class CustomRazorViewEngine : RazorViewEngine
 {
  public CustomRazorViewEngine(string theme)
  {
   if (!string.IsNullOrEmpty(theme))
   {
    AreaViewLocationFormats = new[]
    {
      //themes
      "~/themes/"+theme+"/views/Areas/{2}/{1}/{0}.cshtml",
      "~/themes/"+theme+"/Shared/{0}.cshtml"

  "~/Areas/{2}/Views/{1}/{0}.cshtml",
  "~/Areas/{2}/Views/Shared/{0}.cshtml"
 };
    AreaMasterLocationFormats = new[]
    {
        //themes
    "~/themes/"+theme+"/views/Areas/{2}/{1}/{0}.cshtml",
    "~/themes/"+theme+"/views/Areas/{2}/Shared/{0}.cshtml",
    "~/themes/"+theme+"/views/Shared/{0}.cshtml",

  "~/Areas/{2}/Views/{1}/{0}.cshtml",
  "~/Areas/{2}/Views/Shared/{0}.cshtml"
 };
    AreaPartialViewLocationFormats = new[]
    {
       //themes
   "~/themes/"+theme+"/views/Shared/{0}.cshtml",

  "~/Areas/{2}/Views/{1}/{0}.cshtml",
  "~/Areas/{2}/Views/Shared/{0}.cshtml"
 };

    ViewLocationFormats = new[]
    {
       //themes
   "~/themes/"+theme+"/views/{1}/{0}.cshtml",

  "~/Views/{1}/{0}.cshtml",
  "~/Views/Shared/{0}.cshtml"
 };
    MasterLocationFormats = new[]
    {
       //themes
   "~/themes/"+theme+"/views/Shared/{0}.cshtml",

  "~/Views/{1}/{0}.cshtml",
  "~/Views/Shared/{0}.cshtml"
 };
    PartialViewLocationFormats = new[]
    {
       //themes
  "~/themes/"+theme+"/views/Shared/{0}.cshtml",

  "~/Views/{1}/{0}.cshtml",
  "~/Views/Shared/{0}.cshtml"
 };

    FileExtensions = new[]{"cshtml"};
   }

  }
 }
}

Après réécriture, nos règles de routage seront comme ceci : lorsqu'aucun sujet n'est sélectionné, celui d'origine sera utilisé règles de routage, si un sujet est sélectionné, les règles de routage réécrites sont utilisées.

Nouvelle règle de routage : lorsqu'un thème est sélectionné, recherchez d'abord thèmes/nom du thème/vues/zones/nom de la zone/nom du contrôleur/nom de la vue.cshtml. S'il n'est pas trouvé, suivez les règles de routage par défaut pour le trouver. , c'est-à-dire Zones/nom de la zone/Vues/nom du contrôleur/nom de la vue.cshtml

切换主题View代码:


<p class="btn-group">
     <button type="button" class="btn btn-circle btn-outline red dropdown-toggle" data-toggle="dropdown">
      <i class="fa fa-plus"></i> 
      <span class="hidden-sm hidden-xs">切换主题 </span> 
      <i class="fa fa-angle-down"></i>
     </button>
     <ul class="dropdown-menu" role="menu">
      <li>
       <a href="javascript:setTheme(&#39;default&#39;)">
        <i class="icon-docs"></i> 默认主题
       </a>
      </li>
      <li>
       <a href="javascript:setTheme(&#39;Blue&#39;)">
        <i class="icon-tag"></i> 蓝色主题
       </a>
      </li>
     </ul>
    </p>
  <script type="text/javascript">
   function setTheme(themeName)
   {
    window.location.href = "/Home/SetTheme?themeName=" + themeName + "&href=" + window.location.href;
   }
</script>

用户登录成功的时候,从Cookie中读取所选主题信息,当Cookie中没有读取到主题记录时,则从Web.config配置文件中读取配置的主题名称,如果都没有读取到,则说明是默认主题,沿用原有的视图引擎规则。

在后台管理界面,每次选择了主题,我都将主题名称存储到Cookie中,默认保存一年,这样当下次再登录的时候,就能够记住所选的主题信息了。


using System;
using System.Web.Mvc;
using Secom.Emx.WebApp.Helper;
using System.Web;
using Secom.Emx.Common.Controllers;

namespace Secom.Emx.WebApp.Controllers
{
 public class HomeController : BaseController
 {
  string themeCookieName = "Theme";
  public ActionResult Index()
  {
   ViewData["Menu"] = GetMenus();
   return View();
  }
  public ActionResult SetTheme(string themeName,string href)
  {
   if (!string.IsNullOrEmpty(themeName))
   {
    Response.Cookies.Set(new HttpCookie(themeCookieName, themeName) { Expires = DateTime.Now.AddYears(1) });
   }
   else
   {
    themeName = Request.Cookies[themeCookieName].Value ?? "".Trim();
   }
   Utils.ResetRazorViewEngine(themeName);
   return string.IsNullOrEmpty(href)? Redirect("~/Home/Index"):Redirect(href);
  }
  public ActionResult Login()
  {
   string themeName = Request.Cookies[themeCookieName].Value ?? "".Trim();
   if (!string.IsNullOrEmpty(themeName))
   {
    Utils.ResetRazorViewEngine(themeName);
   }
   return View();
  }
 }
}

Utils类:


using System.Configuration;
using System.Web.Mvc;

namespace Secom.Emx.WebApp.Helper
{
 public class Utils
 {
  private static string _themeName;

  public static string ThemeName
  {
   get
   {
    if (!string.IsNullOrEmpty(_themeName))
    {
     return _themeName;
    }
    //模板风格
    _themeName =string.IsNullOrEmpty(ConfigurationManager.AppSettings["Theme"])? "" : ConfigurationManager.AppSettings["Theme"];
    return _themeName;
   }
  }
  public static void ResetRazorViewEngine(string themeName)
  {
   themeName = string.IsNullOrEmpty(themeName) ? Utils.ThemeName : themeName;
   if (!string.IsNullOrEmpty(themeName))
   {
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new CustomRazorViewEngine(themeName));
   }
  }
 }
}

实现方式实在是太简单,简单得我不知道如何表述才好,我还是记下来,方便有需要的人可以查阅,希望可以帮到你们。由于项目引入了庞大的各种相关文件以致文件比较大,网速原因无法上传源码还望见谅!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn