c1-cms

c1 cms - ¿Cómo funciona la arquitectura del Compuesto C1?



c1-cms (1)

¿Alguien puede dar una descripción de alto nivel de lo que está pasando en el núcleo del Compuesto C1? En particular, me interesa saber cómo funciona la arquitectura del complemento y cuáles son los componentes principales del sistema, es decir, cuando llega una solicitud de lo que está sucediendo en la arquitectura. La descripción no tiene que ser demasiado detallada solo una lista de pasos y las clases involucradas.

Esperemos que uno de los miembros del equipo de desarrollo central me ilumine ... y quizás publique un poco más de API (por favor, sugiera más documentación de clase, por favor).


De la solicitud a la página renderizada

La ruta concreta que toma una solicitud depende de la versión de C1 que esté usando, ya que se cambió para usar Enrutamiento en la versión 2.1.2. Así que veamos

  • <2.1.2

Composite.Core.WebClient.Renderings.RequestInterceptorHttpModule interceptará todas las solicitudes entrantes y averiguará si la ruta solicitada corresponde a una página C1 válida. Si lo hace, la URL se volverá a escribir en el controlador de la página C1 ~/Rendererings/Page.aspx

  • 2.1.1

Composite.Core.Routing.Routes.Register() agrega una ruta de página C1 ( Composite.Core.Routing.Pages.C1PageRoute ) a la colección Routes que mira la ruta entrante, se da cuenta si es una página C1 válida. Si es así, devuelve una instancia de ~/Rendererings/Page.aspx listo para ejecutarse.

Bien, ahora tenemos una instancia de un IHttpHandler listo para inventar la página que se devolverá al cliente. El código real para el IHttpHandler es fácil de ver ya que está ubicado en ~/Renderers/Page.aspx.cs

  • OnPreInit

Aquí estamos pensando qué ID de página y qué idioma se solicitó y verificando si estamos en el modo de vista previa o no, qué enlace de datos, etc.

  • OnInit

Ahora estamos recuperando el contenido de cada Marcador de contenido de nuestra página, y destacando sus funciones que puede contener. Se hace llamando a Composite.Core.WebClient.Renderings.Page.PageRenderer.Render pasando la página actual y nuestros marcadores de posición. Internamente, llamará al método ExecuteFunctions que ejecutará el contenido y resolverá recursivamente los elementos de la función C1 ( <f:function /> ), los ejecutará y reemplazará el elemento con la salida de funciones. Esto se hará hasta que no haya más elementos de función en el contenido, en caso de que las mismas funciones generen otras funciones.

Ahora, todo el contenido se envuelve en un control de Asp.Net WebForms y se inserta en nuestra página de WebForms. Dado que las funciones C1 pueden devolver controles WebForms como UserControl , etc., esto es necesario para que funcionen correctamente y desencadenen el Ciclo de Vida de Eventos de WebForms.

Y eso es básicamente eso. La renderización de una página solicitada es muy simple y muy extensible. Por ejemplo, hay una extensión que permite el uso de MasterPages que simplemente se enlaza con este flujo de renderizado de manera muy elegante. Y como estamos usando Routing para mapear qué controlador usar, también es posible olvidarse de ~/Rendering/Page.aspx y devolver un MvcHandler si eres un fanático de Mvc.

API

Ahora, cuando se trata de las API más básicas, hay muchas, dependiendo de lo que quieras hacer. Pero puede estar bastante seguro, sin importar cuáles sean los necesarios para hacer el trabajo.

En el extremo profundo tenemos la capa de datos en la que se centran la mayoría de las otras API y fachadas. Esto significa que puede hacer la mayoría de las cosas trabajando con los datos en bruto, en lugar de atravesar fachadas todo el tiempo. Esto es posible ya que la mayoría de la configuración de C1 se realiza mediante el uso de su propia capa de datos para almacenar la configuración.

El grupo central Compuesto C1 aún debe validar / refactorizar y documentar todas las API en el sistema y, por lo tanto, operar con el concepto de ''una API pública'' y lo que puede convertirse en una API cuando existe la demanda. Este último es un API bastante estable, pero sin garantías.

La documentación pública de la API está en línea en http://api.composite.net/

Funciones

Las funciones son una parte fundamental de C1 y son una técnica para abstraer la lógica de la ejecución. Básicamente, todo lo que realice una acción o devuelva algunos datos / cadena / valores puede ser candidato para funciones. En el nivel más bajo, una función es una clase .NET que implementa la interfaz IFunction , pero afortunadamente hay muchas formas más fáciles de trabajar con ella. Fuera de la caja, C1 admite funciones definidas como plantillas XSLT, métodos C # o Sql. También hay soporte comunitario para escribir funciones usando Razor o tener controles de usuario de ASP.Net (archivos .ascx) para que sean funciones.

Dado que todas las funciones se registran en C1 durante el inicio del sistema, usamos Composite.Functions.FunctionFacade para ejecutar cualquier función de la que sepamos el nombre. Use GetFunction para obtener una referencia a una función y luego Execute para ejecutarla y obtener un valor de retorno. Las funciones pueden tomar parámetros que se pasan como objetos .Net reales al ejecutar una función. También hay soporte completo para llamar a funciones con marcado Xml usando el elemento <f:function /> , lo que significa que los editores, diseñadores, creadores de plantillas, etc. pueden acceder fácilmente a una gran cantidad de funciones sin tener que saber cómo escribir código .Net.

Lea más sobre las funciones aquí http://users.composite.net/C1/Functions.aspx y cómo usar Razor para hacer funciones aquí http://docs.composite.net/C1/ASP-NET/Razor-Functions.aspx

Globalización y localización

C1 tiene soporte completo en varios idiomas en el núcleo. Composite.Core.Localization.LocalizationFacade se utiliza para administrar las configuraciones regionales instaladas en el sistema; consultar, agregar y eliminar. Las ubicaciones pueden ser cualquier objeto CultureInfo conocido por su sistema.

Composite.Core.ResourceSystem.StringResourceSystemFacade se usa para obtener cadenas en tiempo de ejecución que coincidan con la información de cultura en la que se está ejecutando su solicitud. Use esto, en lugar de cadenas de codificación en sus páginas o en sus plantillas.

Lea más sobre la localización aquí http://docs.composite.net/C1/HTML/C1-Localization.aspx

Eventos globales

Composite.C1Console.Events.GlobalEventSystemFacade es importante saber si necesita seguir la pista cuando el sistema se está apagando para poder realizar cambios de última hora. Dado que C1 es altamente multihilo, es fácil escribir extensiones y módulos para C1 que también lo son, aprovechando los sistemas de núcleo múltiple y la paralelización y, por lo tanto, también es crucial cerrar los subprocesos de manera adecuada. El GlobalEventSystemFacade ayuda a hacer eso.

Eventos de inicio Si escribe complementos, estos pueden tener una fábrica personalizada. Otro código puede usar el atributo ApplicationStartupAttribute para que el núcleo compuesto de C1 lo llame cuando se inicie la aplicación web.

Eventos de datos Puede suscribirse a los eventos de agregar, editar y eliminar datos (anteriores y posteriores) utilizando los métodos estáticos en Composite.Data.DataEvents<T> . Para adjuntar a estos eventos cuando se inicie el sistema, use el atributo ApplicationStartupAttribute .

Datos

Composite.Core.Threading.ThreadDataManager es importante si accede a la capa de datos fuera de una solicitud de página C1 correspondiente. Este podría ser un controlador personalizado que solo tiene que alimentar todas las noticias más recientes como un feed Rss, o quizás esté escribiendo una aplicación de consola. En estos casos, recuerde siempre envolver su código que accede a los datos como este

using(Composite.Core.Threading.ThreadDataManager.EnsureInitialize()) { // Code that works with C1 data layer goes here }

Para acceder y manipular datos, se recomienda NO utilizar la clase DataFacade, pero envolver todo el código que obtiene o actualiza o elimina o agrega datos como este.

using(var data = new DataConnection()) { // Do things with data }

IO

Cuando se trabaja con archivos y directorios, es importante utilizar las clases equivalentes de C1 Composite.Core.IO.C1File y Composite.Core.IO.C1Directory al archivo y directorio de .Net. Esto se debe a la naturaleza en la que C1 se puede alojar en Azure , donde es posible que no tenga acceso al sistema de archivos de la misma manera que en un servidor Windows normal. Al utilizar las envolturas de archivos y directorios de C1, puede estar seguro de que el código que escriba también podrá ejecutarse en Azure.

Consola C1

La consola es un tema completo en sí misma y tiene muchas API.

Puede crear sus propios árboles utilizando Composite.C1Console.Trees.TreeFacade o Composite.C1Console.Elements.ElementFacade e implementando un Composite.C1Console.Elements.Plugins.ElementProvider.IElementProvider .

Puede usar Composite.C1Console.Events.ConsoleMessageQueueFacade para enviar mensajes del servidor al cliente para que haga cosas como abrir un cuadro de mensaje, actualizar un árbol, establecer el foco en un elemento específico, abrir una nueva pestaña, etc.

Composite.C1Console.Workflow.WorkflowFacade se usa para obtener instancias de flujos de trabajo específicos e interactuar con ellos. Workflows son una parte muy fundamental de C1 y es la forma en que se definen y ejecutan las operaciones de varios pasos. Esto hace posible guardar el estado de operación, es decir. un asistente de 10 pasos se mantiene incluso si el servidor se reinicia o si ocurre algo inesperado. Workflows se crean utilizando Windows Workflow Foundation , por lo que está familiarizado con esto, debería sentirse como en casa.

También hay una gran cantidad de fachadas y métodos de javascript que puede conectar al escribir extensiones en la Consola. Mucho más de lo que podría cubrir aquí, así que me abstendré incluso de comenzar con ese tema aquí.

compuesto.config

Una parte fundamental de C1 son los proveedores, casi todo está formado por proveedores, incluso gran parte de la funcionalidad central. Todo en la consola de Perspectivas a árboles y elementos y acciones se incorporan a C1 con los proveedores. Todas las funciones estándar, la ficha de datos y todos los widgets para usar con el editor de llamadas de función se incorporan a C1 con los proveedores. Todas las cadenas de localización para usar con los Recursos, usuarios y permisos, formateadores de URL, etc. son todos proveedores.

  • Composite.Data.Plugins.DataProviderConfiguration

Aquí se registran todos los proveedores que pueden responder a los métodos en DataFacade, Get, Update, Delete, Add, etc. Cada proveedor informa al sistema con qué interfaces puede interactuar y C1 se asegura de enrutar todas las solicitudes de interfaces específicas a sus respectivos proveedores de datos.

  • Composite.C1Console.Elements.Plugins.ElementProviderConfiguration

Aquí estamos definiendo las perspectivas y los árboles dentro de la consola. Todas las perspectivas estándar que ves cuando inicias la Consola por primera vez se configuran aquí, sin magia ni caja negra involucrada.

  • Composite.C1Console.Elements.Plugins.ElementActionProviderConfiguration

Los proveedores de acciones pueden agregar nuevos artículos a todos los elementos del sistema, según su EntityToken. Esto es muy poderoso cuando se desea agregar una nueva funcionalidad al contenido existente como el control de versiones, la seguridad de la extranet, el corte / pegado personalizado y la lista continúa.

  • Composite.C1Console.Security.Plugins.LoginProviderConfiguration

Un LoginProvider es lo que la consola C1 utilizará para autenticar a un usuario y le permitirá iniciar sesión o no. Desafortunadamente, esto no es muy abierto pero con un poco de reflexión debes estar listo.

  • Composite.Functions.Plugins.FunctionProviderConfiguration

Compuesto C1 utilizará todos los proveedores de función registrados para completar su lista interna de funciones en el inicio del sistema.

  • Composite.Functions.Plugins.WidgetFunctionProviderConfiguration

Los WidgetProviders se utilizan en cosas como el editor de llamadas de función o en el marcado de formularios para representar la IU personalizada para seleccionar datos.

  • Composite.Functions.Plugins.XslExtensionsProviderConfiguration

Las extensiones personalizadas para usar en plantillas XSLT se registran aquí

Y luego tenemos algunas secciones para la configuración pura, como el almacenamiento en caché o qué paralelizar, pero no es tan interesante como los proveedores.

Definir y utilizar secciones.

Las secciones en composite.config, y otros archivos .config relacionados son completamente estándar en la configuración .Net y obedecen las reglas de los mismos. Eso significa que para poder usar un elemento personalizado, como por ejemplo. Composite.Functions.Plugins.WidgetFunctionProviderConfiguration debe definirse como una sección. Una sección tiene un nombre y hace referencia a un tipo que heredaría de System.Configuration.ConfigurationSection . Composite usa las bibliotecas empresariales de Microsoft para manejar la mayoría de estas cosas comunes, como la configuración, el registro y la validación, y por lo tanto, todas las secciones de Composites heredan de Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SerializableConfigurationSection . Ahora, este tipo solo tiene que tener propiedades para todos los elementos que deseamos poder definir en el archivo .config, y .Net se asegurará automáticamente de que todo se conecte para nosotros.

Si desea acceder a la configuración de una sección en particular, debe llamar a Composite.Core.Configuration.ConfigurationServices.ConfigurationSource.GetSection(".. section name") y asignarlo a su tipo específico y listo.

Agregando propiedades extra a secciones ya definidas

Normalmente .Net se quejaría si escribe elementos o atributos en los archivos .config que no son reconocidos por el tipo responsable de la sección o del elemento. Esto hace que sea difícil escribir un sistema de módulos verdaderamente flexible donde los autores externos puedan agregar opciones de configuración específicas a sus proveedores, y para eso tenemos la noción de un ensamblador. Es una clase de ConfigurationElement con un atributo Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder.AssemblerAttribute que, a su vez, toma un Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder.IAssembler Atributos y valores personalizados del elemento en el archivo .config y emiten desde él un objeto utilizable. De esta manera .Net no se quejará de un archivo .config no válido, ya que inyectamos un objeto ConfigurationElement que tiene propiedades para todos nuestros atributos personalizados, y podemos obtenerlos al leer la configuración a través del IAssembler

Diapositivas

Algunas diapositivas de resumen se pueden encontrar en estas líneas

Inspiración y ejemplos.

El proyecto C1Contrib en GitHub es una muy buena introducción sobre cómo interactuar con las diferentes partes de C1. Es una colección de paquetes pequeños, que se pueden usar como están o como inspiración. Hay paquetes que se manipulan con tipos dinámicos para habilitar la herencia de la interfaz. Otros paquetes utilizan la api de javascript en la consola, mientras que otros muestran cómo hacer que los proveedores de funciones, los árboles y los comandos de enlace a los elementos existentes. Incluso hay ejemplos de cómo manipular la comunicación del servicio web de Soap entre el cliente y el servidor para que pueda hacer las cosas de la manera que desee. Y la lista continúa.