Maison  >  Article  >  développement back-end  >  Introduction détaillée à ZKEACMS pour .Net Core

Introduction détaillée à ZKEACMS pour .Net Core

零下一度
零下一度original
2017-05-26 13:34:482995parcourir

ZKEACMS.Core est un CMS open source développé sur la base de .Net Core MVC Cet article fournit principalement une analyse approfondie de ZKEACMS pour .Net Core. Il a une certaine valeur de référence pour ceux qui le sont. Vous pouvez vous référer à

Introduction à ZKEACMS
ZKEACMS.Core est un CMS open source développé sur la base de .Net Core MVC. ZKEACMS permet aux utilisateurs de planifier librement la mise en page, d'utiliser l'édition visuelle pour concevoir « ce que vous voyez est ce que vous obtenez » et de glisser-déposer le contenu directement sur la page.

ZKEACMS utilise la conception de plug-ins, la séparation des modules et enrichit les fonctions du CMS grâce à une expansion horizontale.

Conception réactive

ZKEACMS utilise le système de grille de Bootstrap3 pour mettre en œuvre une conception réactive, afin qu'il puisse être utilisé sur différents les appareils sont accessibles normalement. Dans le même temps, sur les épaules des géants Bootstrap, de riches ressources thématiques sont disponibles.

Démonstration simple

Jetons un coup d'œil à la conception et aux principes du programme

Structure du projet

  • EasyFrameWork Cadre sous-jacent

  • ZKEACMS CMS Core

  • ZKEACMS. Article Article Plug-in

  • ZKEACMS.Product Plug-in du produit

  • ZKEACMS.SectionWidget Plug-in de composant de modèle

  • ZKEACMS. WebHost

Principe - Processus de demande d'accès

Routage démarre dans ZKEACMS Jouant un rôle clé, la priorité de l'itinéraire détermine la direction du processus d'accès. Si un itinéraire correspondant est trouvé, la vue Contrôleur -> S'il n'y a pas de route correspondante, la route sera empruntée par La route "fourre-tout" la plus basse priorité gère la demande de l'utilisateur et renvoie finalement la réponse.

La route "capturer tout" avec la priorité la plus basse est utilisée pour traiter les pages créées par les utilisateurs. Lorsqu'une requête arrive, elle recherche d'abord dans la base de données pour voir si la page existe. Si elle n'existe pas, un 404 est renvoyé. Après avoir trouvé la page, recherchez tous les composants et le contenu de la page, puis appelez uniformément la méthode "Display" de chaque composant pour obtenir le "ViewModel" correspondant et la vue "View", et enfin affichez-les selon la disposition du page.

Organigramme des requêtes ZKEACMS

Composant de page Drive :

widgetService.GetAllByPage(filterContext.HttpContext.RequestServices, page).Each(widget =>
{
  if (widget != null)
  {
    IWidgetPartDriver partDriver = widget.CreateServiceInstance(filterContext.HttpContext.RequestServices);
    WidgetViewModelPart part = partDriver.Display(widget, filterContext);
    lock (layout.ZoneWidgets)
    {
      if (layout.ZoneWidgets.ContainsKey(part.Widget.ZoneID))
      {
        layout.ZoneWidgets[part.Widget.ZoneID].TryAdd(part);
      }
      else
      {
        layout.ZoneWidgets.Add(part.Widget.ZoneID, new WidgetCollection { part });
      }
    }
    partDriver.Dispose();
  }
});

Rendu de page :

foreach (var widgetPart in Model.ZoneWidgets[zoneId].OrderBy(m => m.Widget.Position).ThenBy(m => m.Widget.WidgetName))
{
  <p style="@widgetPart.Widget.CustomStyle">
    <p class="widget @widgetPart.Widget.CustomClass">
      @if (widgetPart.Widget.Title.IsNotNullAndWhiteSpace())
      {
        <p class="panel panel-default">
          <p class="panel-heading">
            @widgetPart.Widget.Title
          </p>
          <p class="panel-body">
            @Html.DisPlayWidget(widgetPart)
          </p>
        </p>
      }
      else
      {
        @Html.DisPlayWidget(widgetPart)
      }
    </p>
  </p>
}

La classe "la plus critique" du plug-in, PluginBase

Chaque plug-in/module doit avoir une classe Inherit PluginBase, qui sert de le point d'entrée pour l'initialisation du plug-in. Le programme est Au démarrage, ces classes seront chargées et certains travaux d'initialisation des clés seront effectués.

public abstract class PluginBase : ResourceManager, IRouteRegister, IPluginStartup
{
  public abstract IEnumerable<RouteDescriptor> RegistRoute(); //注册该插件所需要的路由 可返回空
  public abstract IEnumerable<AdminMenu> AdminMenu(); //插件在后端提供的菜单 可返回空
  public abstract IEnumerable<PermissionDescriptor> RegistPermission(); //注册插件的权限
  public abstract IEnumerable<Type> WidgetServiceTypes(); //返回该插件中提供的所有组件的类型
  public abstract void ConfigureServices(IServiceCollection serviceCollection); //IOC 注册对应的接口与实现
  public virtual void InitPlug(); //初始化插件,在程序启动时调用该方法
}

Pour une implémentation spécifique, veuillez vous référer au plug-in "Article" ArticlePlug.cs ou au plug-in "Produit" ProductPlug.cs

Chargez le plug-in Startup. cs

public void ConfigureServices(IServiceCollection services)
{
  services.UseEasyFrameWork(Configuration).LoadEnablePlugins(plugin =>
  {
    var cmsPlugin = plugin as PluginBase;
    if (cmsPlugin != null)
    {
      cmsPlugin.InitPlug();
    }
  }, null);      
}

Composition des composants

Une page est composée de nombreux composants. Chaque composant peut contenir un contenu différent (Contenu), tel que du texte, des images. , vidéos, etc. Le contenu est déterminé par le composant. La méthode de présentation est déterminée par le modèle (View) du composant.

La relation et la présentation sont à peu près telles qu'indiquées dans la figure ci-dessous :

Enity

Chaque composant sera correspondre Une entité utilisée pour stocker certaines informations liées à ce composant. Les entités doivent hériter de la classe BasicWidget.

Par exemple, la classe d'entité des composants HTML :

[ViewConfigure(typeof(HtmlWidgetMetaData)), Table("HtmlWidget")]
public class HtmlWidget : BasicWidget
{
  public string HTML { get; set; }
}
class HtmlWidgetMetaData : WidgetMetaData<HtmlWidget>
{
  protected override void ViewConfigure()
  {
    base.ViewConfigure();
    ViewConfig(m => m.HTML).AsTextArea().AddClass("html").Order(NextOrder());
  }
}

La configuration des métadonnées [ViewConfigure(typeof(HtmlWidgetMetaData))] est utilisée dans la classe d'entité pour contrôler les pages et les listes de formulaires via réglages simples L'affichage de la page. Si défini sur texte ou zone déroulante requis, vérification de la longueur, etc.

La méthode d'implémentation ici consiste à ajouter un nouveau ModelMetadataDetailsProviderProvider à MVC. La fonction de ce fournisseur est de capturer les informations de configuration de ces métadonnées et de les soumettre à MVC.

services.AddMvc(option =>
  {
    option.ModelMetadataDetailsProviders.Add(new DataAnnotationsMetadataProvider());
  })

Service Service

WidgetService est le pont entre les données et les modèles. Il récupère les données via le service et les envoie au modèle de page. Le service doit hériter de WidgetService30387bb9109ecea281cb4c0ff151ccd8. Si l'entreprise est complexe, remplacez la méthode correspondante de la classe de base pour l'implémenter.

Par exemple, le Service de composants HTML :

public class HtmlWidgetService : WidgetService<HtmlWidget, CMSDbContext>
{
  public HtmlWidgetService(IWidgetBasePartService widgetService, IApplicationContext applicationContext)
    : base(widgetService, applicationContext)
  {
  }
 
  public override DbSet<HtmlWidget> CurrentDbSet
  {
    get
    {
      return DbContext.HtmlWidget;
    }
  }
}

Voir l'entité ViewModel

ViewModel n'est pas nécessaire lorsque l'entité (Entity) est passé en tant que ViewModel Lorsque la vue n'est pas suffisante pour répondre aux exigences, vous pouvez créer un nouveau ViewModel et transmettre ce ViewModel, ce qui nécessitera de remplacer la méthode Display

public override WidgetViewModelPart Display(WidgetBase widget, ActionContext actionContext)
{
  //do some thing
  return widget.ToWidgetViewModelPart(new ViewModel());
}

View/Template Widget.cshtml

Le modèle est utilisé pour afficher le contenu. Le « Modèle » requis par le modèle est collecté via le Service, et enfin le modèle les affiche.

动态编译分散的模板

插件的资源都在各自的文件夹下面,默认的视图引擎(ViewEngine)并不能找到这些视图并进行编译。MVC4版本的ZKEACMS是通过重写了ViewEngine来得以实现。.net core mvc 可以更方便实现了,实现自己的 ConfigureOptionsb81c8758155c398bce8db7dc265f7449 ,然后通过依赖注入就行。

public class PluginRazorViewEngineOptionsSetup : ConfigureOptions<RazorViewEngineOptions>
{
  public PluginRazorViewEngineOptionsSetup(IHostingEnvironment hostingEnvironment, IPluginLoader loader) :
    base(options => ConfigureRazor(options, hostingEnvironment, loader))
  {
 
  }
  private static void ConfigureRazor(RazorViewEngineOptions options, IHostingEnvironment hostingEnvironment, IPluginLoader loader)
  {
    if (hostingEnvironment.IsDevelopment())
    {
      options.FileProviders.Add(new DeveloperViewFileProvider());
    }
    loader.GetPluginAssemblies().Each(assembly =>
    {
      var reference = MetadataReference.CreateFromFile(assembly.Location);
      options.AdditionalCompilationReferences.Add(reference);        
    });
    loader.GetPlugins().Where(m => m.Enable && m.ID.IsNotNullAndWhiteSpace()).Each(m =>
    {
      var directory = new DirectoryInfo(m.RelativePath);
      if (hostingEnvironment.IsDevelopment())
      {
        options.ViewLocationFormats.Add($"/Porject.RootPath/{directory.Name}" + "/Views/{1}/{0}" + RazorViewEngine.ViewExtension);
        options.ViewLocationFormats.Add($"/Porject.RootPath/{directory.Name}" + "/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
        options.ViewLocationFormats.Add($"/Porject.RootPath/{directory.Name}" + "/Views/{0}" + RazorViewEngine.ViewExtension);
      }
      else
      {
        options.ViewLocationFormats.Add($"/{Loader.PluginFolder}/{directory.Name}" + "/Views/{1}/{0}" + RazorViewEngine.ViewExtension);
        options.ViewLocationFormats.Add($"/{Loader.PluginFolder}/{directory.Name}" + "/Views/Shared/{0}" + RazorViewEngine.ViewExtension);
        options.ViewLocationFormats.Add($"/{Loader.PluginFolder}/{directory.Name}" + "/Views/{0}" + RazorViewEngine.ViewExtension);
      }
    });
    options.ViewLocationFormats.Add("/Views/{0}" + RazorViewEngine.ViewExtension);
  }
}

看上面代码您可能会产生疑惑,为什么要分开发环境。这是因为ZKEACMS发布和开发的时候的文件夹目录结构不同造成的。为了方便开发,所以加入了开发环境的特别处理。接下来就是注入这个配置:

services.TryAddEnumerable(ServiceDescriptor.Transient14b327c75dcb4d47b8bf35db01acaec9, PluginRazorViewEngineOptionsSetup>());            

EntityFrameWork

ZKEACMS for .net core 使用EntityFrameWork作为数据库访问。数据库相关配置 EntityFrameWorkConfigure

public class EntityFrameWorkConfigure : IOnConfiguring
{
  public void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  {
    optionsBuilder.UseSqlServer(Easy.Builder.Configuration.GetSection("ConnectionStrings")["DefaultConnection"]);
  }
}

对Entity的配置依然可以直接写在对应的类或属性上。如果想使用 Entity Framework Fluent API,那么请创建一个类,并继承自 IOnModelCreating

class EntityFrameWorkModelCreating : IOnModelCreating
{
  public void OnModelCreating(ModelBuilder modelBuilder)
  {
    modelBuilder.Entity<LayoutHtml>().Ignore(m => m.Description).Ignore(m => m.Status).Ignore(m => m.Title);
  }
}

主题

ZKEACMS 使用Bootstrap3作为基础,使用LESS,定议了许多的变量,像边距,颜色,背景等等,可以通过简单的修改变量就能“编译”出一个自己的主题。

或者也可以直接使用已经有的Bootstrap3的主题作为基础,然后快速创建主题。

最后

关于ZKEACMS还有很多,如果您也感兴趣,欢迎加入我们。

ZKEACMS for .net core 就是要让建网站变得更简单,快速。页面的修改与改版也变得更轻松,便捷。

【相关推荐】

1. .Net Core 之 图形验证码

2. .NET Core配置文件加载与DI注入配置数据

3. .NET Core CLI工具文档dotnet-publish

4. 分享.net MVC中使用forms验证实例代码

5. 在.net core 下如何进行http请求?

6. CentOS上运行ZKEACMS的实例教程

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