Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of ZKEACMS for .net Core

2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article shares with you the content of the sample analysis of ZKEACMS for .net Core. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

Introduction to ZKEACMS

ZKEACMS.Core is an open source CMS based on .net Core MVC. ZKEACMS allows users to freely plan the layout of the page, use visual editing to design WYSIWYG, and drag and drop to add content directly on the page.

ZKEACMS uses plug-in design, module separation, and horizontal expansion to enrich the functions of CMS.

Responsive design

ZKEACMS uses Bootstrap3's grid system to implement a responsive design so that it can be accessed properly on different devices. At the same time, standing on the shoulders of Bootstrap giants, there are rich theme resources to use.

Simple demonstration

Next, let's take a look at the programming and the principle.

Project structure

EasyFrameWork underlying framework

ZKEACMS CMS core

ZKEACMS.Article article plug-in

ZKEACMS.Product product plug-in

ZKEACMS.SectionWidget template component plug-in

ZKEACMS.WebHost

Principle-access request process

Routing plays a key role in ZKEACMS. The access process is determined by the priority of the route. If a matching route is found, the corresponding Controller-> Action-> View of the route is preferred. If there is no matching route, the user's request is processed by the "full capture" route with the lowest priority, and the response is returned at last.

The lowest priority "full capture" route is used to process user-created pages. When the request comes in, first go to the database to see 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 "View", and finally 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.ZoneWidget.ZoneID] .TryAdd (part) } else {layout.ZoneWidgets.Add (part.Widget.ZoneID, new WidgetCollection {part});} partDriver.Dispose ();}})

Page rendering:

Foreach (var widgetPart in Model. ZoneWidges [zoneId] .OrderBy (m = > m.Widget.Position) .ThenBy (m = > m.Widget.WidgetName)) {@ if (widgetPart.Widget.Title.IsNotNullAndWhiteSpace ()) {@ widgetPart.Widget.Title @ Html.DisPlayWidget (widgetPart)} else {@ Html.DisPlayWidget (widgetPart)}}

PluginBase, the "most critical" class of the plug-in

Every plug-in / module must have a class that inherits PluginBase as the entry for the initialization of the plug-in. 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 RegistRoute (); / / the route required to register the plug-in can return empty public abstract IEnumerable AdminMenu (); / / the menu provided by the plug-in in the backend can return empty public abstract IEnumerable RegistPermission (); / / the permission to register the plug-in public abstract IEnumerable WidgetServiceTypes (); / / return the type of all components provided in the plug-in public abstract void ConfigureServices (IServiceCollection serviceCollection) / / IOC registers the corresponding interface and implementation public virtual void InitPlug (); / / initializes the plug-in and calls this method when the program starts}

For specific implementation, please refer to the "article" plug-in ArticlePlug.cs or "product" plug-in ProductPlug.cs.

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

Component composition

A page, made up of many components, each component can contain different content (Content), such as text, pictures, videos, etc., the content is determined by the component, and the presentation is determined by the component template (View).

The relationship and presentation are roughly shown in the following figure:

Entity Enity

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

For example, the entity class of the HTML component:

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

Metadata configuration [ViewConfigure (typeof (HtmlWidgetMetaData))] is used in entity classes to control the display of form pages and list pages through simple settings. If set to text or drop-down box; required, length, etc.

The implementation here is to add a new ModelMetadataDetailsProviderProvider to the MVC. The purpose of this Provider is to grab the configuration information of the metadata and submit it to the MVC.

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

Service Service

WidgetService is a bridge between data and template, grabbing data through Service and sending it to the page template. Service must inherit from WidgetService. If the business is complex, override the corresponding method of the base class to implement it.

For example, Service of the HTML component:

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

View entity ViewModel

ViewModel is not required. When the Entity is passed to the view as a ViewModel, you can create a new ViewModel and pass the ViewModel, which will require the Display method to be overridden.

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

View / template Widget.cshtml

Templates (Template) are used to display content. The "Model" required by the template is collected through Service, and finally the template displays them.

Dynamically compile distributed templates

The plug-in's resources are under their respective folders, and the default view engine (ViewEngine) cannot find these views and compile them. The MVC4 version of ZKEACMS is implemented by rewriting ViewEngine. Net core mvc can be implemented more easily, implementing your own ConfigureOptions, and then through dependency injection.

Public class PluginRazorViewEngineOptionsSetup: ConfigureOptions {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);}}

Looking at the code above, you may wonder why you should divide the development environment. This is due to the different folder directory structure when ZKEACMS was released and developed. In order to facilitate the development, the special treatment of the development environment is added. The following is to inject this configuration:

Services.TryAddEnumerable (ServiceDescriptor.Transient ())

EntityFrameWork

ZKEACMS for. Net core uses EntityFrameWork as 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 Entity can still be written directly on the corresponding class or property. If you want to use Entity Framework Fluent API, create a class and inherit it from IOnModelCreating

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

Theme

ZKEACMS uses Bootstrap3 as the basis, uses LESS, and negotiates many variables, such as margins, colors, backgrounds, and so on. You can "compile" your own theme by simply modifying the variables.

Alternatively, you can directly use the existing Bootstrap3 theme as the basis, and then quickly create the theme.

Thank you for reading! This is the end of the article on "sample Analysis of ZKEACMS for .net Core". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, you can share it for more people to see!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report