Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Einführung in ZKEACMS für .Net Core

Detaillierte Einführung in ZKEACMS für .Net Core

零下一度
零下一度Original
2017-05-26 13:34:483006Durchsuche

ZKEACMS.Core ist ein Open-Source-CMS, das auf Basis von .Net Core MVC entwickelt wurde. Dieser Artikel bietet hauptsächlich eine ausführliche Analyse von ZKEACMS für .Net Core Bei Interesse können Sie sich auf

ZKEACMS-Einführung
ZKEACMS.Core beziehen, ein Open-Source-CMS, das auf Basis von .Net Core MVC entwickelt wurde. Mit ZKEACMS können Benutzer das Seitenlayout frei planen, mithilfe visueller Bearbeitung „What you see is what you get“ gestalten und Inhalte direkt auf die Seite ziehen und dort ablegen.

ZKEACMS nutzt Plug-in-Design, Modultrennung und erweitert die Funktionen von CMS durch horizontale Erweiterung.

Responsive Design

ZKEACMS nutzt das Rastersystem von Bootstrap3, um Responsive Design zu implementieren, sodass es auf verschiedenen Plattformen eingesetzt werden kann Auf die Geräte kann normal zugegriffen werden. Gleichzeitig stehen auf den Schultern der Bootstrap-Giganten umfangreiche Themenressourcen zur Verfügung.

Einfache Demonstration

Werfen wir einen Blick auf das Programmdesign und die Prinzipien

Projektstruktur

  • EasyFrameWork Underlying Framework

  • ZKEACMS CMS Core

  • ZKEACMS. Artikel Artikel-Plug-in

  • ZKEACMS.Product Produkt-Plug-in

  • ZKEACMS.SectionWidget Vorlagenkomponenten-Plug-in

  • ZKEACMS.

Prinzip - Zugriffsanforderungsprozess

Routing beginnt in ZKEACMS. Die Priorität der Route bestimmt die Richtung des Zugriffsprozesses. Wenn eine passende Route gefunden wird, wird zuerst die der Route entsprechende Controller-Ansicht ausgeführt Wenn es keine passende Route gibt, wird die Route von der „Catch-All“-Route mit der niedrigsten Priorität übernommen, die die Anfrage des Benutzers verarbeitet und schließlich die Antwort zurückgibt.

Die Route „Alle erfassen“ mit der niedrigsten Priorität wird zur Verarbeitung von Seiten verwendet, die von Benutzern selbst erstellt wurden. Wenn eine Anfrage eingeht, wird zunächst die Datenbank durchsucht, um festzustellen, ob die Seite vorhanden ist. Wenn sie nicht vorhanden ist, wird eine 404 zurückgegeben. Nachdem Sie die Seite gefunden haben, suchen Sie alle Komponenten und Inhalte der Seite und rufen Sie dann einheitlich die Methode „Display“ jeder Komponente auf, um das entsprechende „ViewModel“ und die entsprechende Ansicht „View“ abzurufen und sie schließlich entsprechend dem Layout der Seite anzuzeigen Seite.

ZKEACMS-Anfrageflussdiagramm

Drive-Seitenkomponente:

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();
  }
});

Seitenrendering:

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>
}

Die „kritischste“ Klasse des Plug-Ins, PluginBase

Jedes Plug-In/Modul muss eine Klasse Inherit PluginBase haben, die als dient Der Einstiegspunkt für die Plug-In-Initialisierung ist. Beim Start werden diese Klassen geladen und einige wichtige Initialisierungsarbeiten durchgeführt.

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(); //初始化插件,在程序启动时调用该方法
}

Informationen zur spezifischen Implementierung finden Sie im Plug-in „Article“ ArticlePlug.cs oder im Plug-in „Product“ ProductPlug.cs.

Laden Sie das 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);      
}

Komponentenzusammensetzung

Eine Seite besteht aus vielen Komponenten. Jede Komponente kann unterschiedliche Inhalte (Inhalte) enthalten, z. B. Text, Bilder , Videos usw. Der Inhalt wird durch die Komponente bestimmt. Die Präsentationsmethode wird durch die Vorlage (Ansicht) der Komponente bestimmt.

Die Beziehung und Darstellung sind ungefähr wie in der folgenden Abbildung dargestellt:

Enity

Jede Komponente wird korrespondieren Eine Entität, die zum Speichern einiger Informationen zu dieser Komponente verwendet wird. Entitäten müssen von der BasicWidget-Klasse erben.

Zum Beispiel die Entitätsklasse von HTML-Komponenten:

[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());
  }
}

Die Metadatenkonfiguration [ViewConfigure(typeof(HtmlWidgetMetaData))] wird in der Entitätsklasse verwendet, um Formularseiten und Listen durch zu steuern einfache Einstellungen Die Anzeige der Seite. Bei Einstellung auf Text oder Dropdown-Feld erforderlich, Überprüfung der Länge usw.

Die Implementierungsmethode besteht darin, einen neuen ModelMetadataDetailsProvider zu MVC hinzuzufügen. Die Funktion dieses Providers besteht darin, die Konfigurationsinformationen dieser Metadaten zu erfassen und an MVC zu übermitteln.

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

Service Service

WidgetService ist die Brücke zwischen Daten und Vorlagen. Es erfasst Daten über den Service und sendet sie an die Seitenvorlage. Der Dienst muss von WidgetService30387bb9109ecea281cb4c0ff151ccd8 erben. Wenn das Geschäft komplex ist, überschreiben Sie die entsprechende Methode der Basisklasse, um es zu implementieren.

Zum Beispiel ist der Dienst von HTML-Komponenten:

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

View-Entität ViewModel

ViewModel nicht erforderlich, wenn die Entität (Entity) vorhanden ist übergeben als ViewModel Wenn die Ansicht nicht ausreicht, um die Anforderungen zu erfüllen, können Sie ein neues ViewModel erstellen und dieses ViewModel übergeben, was das Überschreiben der Display-Methode

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

View/Template Widget.cshtml erfordert

Vorlage wird zum Anzeigen von Inhalten verwendet. Das für die Vorlage erforderliche „Modell“ wird über den Dienst erfasst und schließlich in der Vorlage angezeigt.

动态编译分散的模板

插件的资源都在各自的文件夹下面,默认的视图引擎(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的实例教程

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in ZKEACMS für .Net Core. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn