Detailed introduction to ZKEACMS for. Net Core

Source: Internet
Author: User
Tags open source cms
Zkeacms. Core is an open-source CMS based on. NET Core MVC, this article is mainly for the deep analysis of zkeacms for. NET core, with a certain reference value, interested in small partners can refer to

ZKEACMS Introduction
Zkeacms. Core is an open source CMS developed based on. Net Core MVC. ZKEACMS allows users to freely plan page layouts, use visual editing to design "WYSIWYG" and drag and drop content directly on the page.

ZKEACMS uses plug-in design, module separation, and scale-out to enrich the functionality of the CMS.

Responsive design

The ZKEACMS uses the BOOTSTRAP3 grid system for responsive design, enabling normal access on different devices. At the same time standing on the shoulders of the bootstrap giants, there are a wealth of theme resources to use.

Simple Demo

Next look at the program design and principles

Project structure

    • Easyframework Bottom Frame

    • Zkeacms CMS Core

    • Zkeacms. Article article Plugin

    • Zkeacms. Product Plug-in

    • Zkeacms. Sectionwidget template Component Plug-in

    • Zkeacms. Webhost

Principle-Access Request flow

routing plays a key role in Zkeacms, which determines the flow of access through the priority of the route, and if a matching route is found, it takes precedence over the Controller-to-Action View for that route, if there are no matching routes , the walk is handled by the lowest-priority "catch-all" route to the user's request, and finally the response is returned.

The lowest-priority "catch-all" route is used to process pages that the user creates themselves. When the request comes in, go to the database first to find out if the page exists, and return 404 if it does not exist. After finding the page, find out all the components and contents of the page, then call the "display" method of each component to get the corresponding "ViewModel" and "View", and then display it according to the layout of the page.

ZKEACMS Request Flowchart

Drive Page Components:

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

Page Rendering:

foreach (Var widgetpart in Model.zonewidgets[zoneid]. (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>}

Plug-in "most critical" class Pluginbase

Each plugin/module will need a class to inherit pluginbase, as the plug-in initialization of the portal, when the program starts, it will load these classes and do some key initialization work.

Public abstract class Pluginbase:resourcemanager, Irouteregister, ipluginstartup{public  abstract ienumerable< Routedescriptor> Registroute (); The route required to register the plug-in can return empty public  abstract ienumerable<adminmenu> adminmenu ();//plug-in menu provided on backend can return empty public  Abstract ienumerable<permissiondescriptor> registpermission (); Permissions to register plug-ins public  abstract ienumerable<type> widgetservicetypes ();//Returns the type of all components provided in the plug-in public  abstract void Configureservices (Iservicecollection servicecollection); IOC registers the corresponding interface with the implementation public  virtual void initplug ();//Initialize the plug-in to invoke the method at program startup}

Specific implementation can refer to the "article" Plugin ArticlePlug.cs or "product" plug-in ProductPlug.cs

Load Plugin Startup.cs

public void Configureservices (iservicecollection services) {  services. Useeasyframework (Configuration). Loadenableplugins (Plugin  = {    var cmsplugin = plugin as pluginbase;    if (cmsplugin! = null)    {      cmsplugin.initplug ();}  }, NULL);      }

Component composition

A page, consisting of a number of components, each of which can contain different content, such as text, pictures, videos, etc., content is determined by the component, and the presentation is determined by the component's template (View).

The relationship and presentation are roughly as follows:

Entity Enity

Each component corresponds to an entity that stores some information related to that component. The entity must inherit from the Basicwidget class.

For example, an entity class for an HTML component:

[Viewconfigure (typeof (Htmlwidgetmetadata)), Table ("Htmlwidget")]public class htmlwidget:basicwidget{public  String HTML {get; set;}} Class htmlwidgetmetadata:widgetmetadata

The entity class uses metadata configuration [Viewconfigure (typeof (Htmlwidgetmetadata))] to control the display of form pages and list pages with simple settings. If set to text or drop-down box, required, length, etc. verification.

The way to do this is to add a new modelmetadatadetailsproviderprovider to MVC, a provider that captures the configuration information of the metadata and submits it to MVC.

Services. ADDMVC (option =  {    option. Modelmetadatadetailsproviders.add (New Dataannotationsmetadataprovider ());  })

Services Service

Widgetservice is a bridge between data and templates that fetches data through a service and sends it to a page template. Service must inherit from Widgetservice<widgetbase, cmsdbcontext>. If the business is complex, the corresponding method of overriding the (override) base class is implemented.

For example, the service for HTML components:

public class Htmlwidgetservice:widgetservice

View Entity ViewModel

ViewModel is not required, you can create a new ViewModel and pass this ViewModel over if the entity (entities) is not uploaded to the view as ViewModel to meet the requirements, which will require overriding the Display method

public override Widgetviewmodelpart Display (Widgetbase widget, Actioncontext actioncontext) {  //do some thing  return widget. Towidgetviewmodelpart (New ViewModel ());}

View/Template widget.cshtml

Template is used to display content. The service collects the "Model" required by the template, and the final template displays them.

Dynamic compilation of distributed templates

The plugins ' resources are under their respective folders, and the default view engine (Viewengine) does not find these views and compile them. The MVC4 version of ZKEACMS is implemented by rewriting the viewengine. NET core MVC makes it easier to implement your own configureoptions<razorviewengineoptions>, Then pass the dependency injection on the line.

public class pluginrazorviewengineoptionssetup:configureoptions<razorviewengineoptions>{Public Pluginrazorviewengineoptionssetup (ihostingenvironment hostingenvironment, Ipluginloader loader): base (options = Configurerazor (options, hostingenvironment, loader)) {} private static void Configurerazor (Razorviewengineoptions opt      Ions, 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); }}

Look at the code above and you may wonder why you should divide the development environment. This is due to the different structure of the folder directory when the Zkeacms is published and developed. Special handling of the development environment was added to facilitate development. The next step is to inject this configuration:

Services. Tryaddenumerable (SERVICEDESCRIPTOR.TRANSIENT<ICONFIGUREOPTIONS<RAZORVIEWENGINEOPTIONS>, Pluginrazorviewengineoptionssetup> ());

EntityFramework

Zkeacms for. NET core uses EntityFramework as a database access. Database-related configuration entityframeworkconfigure

public class entityframeworkconfigure:ionconfiguring{public  void Onconfiguring (Dbcontextoptionsbuilder Optionsbuilder)  {    optionsbuilder.usesqlserver (Easy.Builder.Configuration.GetSection ("ConnectionStrings ") [" defaultconnection "]);}  }

The configuration of the entity can still be written directly on the corresponding class or attribute. If you want to use the Entity Framework Fluent API, create a class and inherit from Ionmodelcreating

Class entityframeworkmodelcreating:ionmodelcreating{public  void onmodelcreating (ModelBuilder ModelBuilder)  {    modelbuilder.entity<layouthtml> (). Ignore (M = m.description). Ignore (M = m.status). Ignore (M = m.title);}  }

Theme

Zkeacms uses the BOOTSTRAP3 as the basis, using less, to negotiate a number of variables, such as margin, color, background, etc., can be "compiled" by simply modifying the variable can be a theme.

Or you can use the theme of an already existing Bootstrap3 as a basis and quickly create a theme.

At last

There are a lot more about ZKEACMS, if you are interested, please join us.

Zkeacms for. NET core is about making websites easier and faster. The revision and revision of the page has also become easier and more convenient.

"Recommended"

1.. Net Core Graphics Verification Code

2.. NET core configuration file loading with di injection configuration data

3.. NET Core CLI Tool documentation Dotnet-publish

4. Sharing. NET MVC using forms to validate instance code

5. How do I make HTTP requests under. NET Core?

6. Example tutorials for running zkeacms on CentOS

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.