Themelia Pro allows you to install many different types of things in a web domain. Many times a lot of what you will add in a web domain is something that's potentially reusable and packagable. For example, say you build a forum system on Themelia Pro that install eight different endpoints, two init processors, an override processor, a catch all process, and an error processor into a web domain. Themelia Pro allows you to componentize all of this into a reusable and distributable entity which any one can install into a web domain in one shot.
To begin the discussion on web components, let's examine the example of the Minima Blog Engine 3.x. This is a Themelia Pro application that is installed into a web domain via a web component. This component installs six endpoints and two processors.
You install components via the "components" collection in a web domain, setting any required parameters in the parameters collection of the component.
<themelia.web>
<webDomains>
<add defaultPage="/Page_/Blog/Root.aspx" catchAllMode="DefaultPage">
<components>
<add key="Minima" type="Minima.Web.Routing.Component.MinimaComponent, Minima.Web">
<parameters>
<add name="blogGuid" value="19277C41-7E4D-4AE0-A196-25F45AC48762" />
</parameters>
</add>
</components>
</add>
</webDomains>
</themelia.web>
That example is all that's required to install the seven endpoints and two processors. The user of the component doens't need to know anything about the HTTP handlers or anything about the mechanics (or existence!) of the two processors.
A Themelia Pro web component is developed by creating a class that inherits from Themelia.Web.Processing.ComponentBase. This is an abstract class that requires you to implement just one method:
void Register ();
Inside of the Register method, you then add the various Themelia Pro parts by adding...
- ...FactoryData object via the AddFactory method,
- ProcessorData object via the AddProcessor method, and
- EndpointData object via the AddEndpoint method.
You create these Data objects via the Create static method on the class itself. Here's a complete example of a web component:
using System;
//+
using Themelia.Web.Processing.Data;
//+
namespace Minima.Web.Processing
{
public class MinimaComponent : Themelia.Web.Processing.ComponentBase
{
//- @Register -//
public override void Register()
{
String blogGuid = ParameterMap.PeekSafely("blogGuid");
if (String.IsNullOrEmpty(blogGuid))
{
throw new System.Configuration.ConfigurationErrorsException(String.Format("Missing parameter: {0}.", "blogGuid"));
}
//+
AddFactory(FactoryData.Create("Minima.Web.Processing.HandlerFactory, Minima.Web"));
AddFactory(FactoryData.Create("Minima.Web.Processing.ProcessorFactory, Minima.Web"));
//+
AddProcessor(ProcessorData.Create<ProcessorData>("__$Minima$PreProcessor", new Object[] { blogGuid }));
AddProcessor(ProcessorData.Create<ProcessorData>("__$Minima$OverrideProcessor"));
//+
AddEndpoint(EndpointData.Create("__$Minima$UrlProcessing", "contains", "/"));
AddEndpoint(EndpointData.Create("__$Minima$BlogDiscovery", "endswith", "/rsd.xml"));
AddEndpoint(EndpointData.Create("__$Minima$WindowsLiveWriterManifest", "endswith", "/wlwmanifest.xml"));
AddEndpoint(EndpointData.Create("__$Minima$SiteMap", "endswith", "/blogmap.xml"));
AddEndpoint(EndpointData.Create("__$Minima$MetaWeblogApi", "contains", "/xml-rpc"));
AddEndpoint(EndpointData.Create("__$Minima$MetaWeblogApi", "contains", "/xml-rpc/"));
AddEndpoint(EndpointData.Create("__$Minima$Image", "contains", "/imagestore/"));
}
}
}
Note that if you want to add an error processor, you add it using ErrorProcessData as the generic parameter:
AddProcessor(ProcessorData.Create<ErrorProcessorData>("CellPhonePager"));
Parameters
As can be seen in the previously shown configuration example, you can use parameters with your components. All components can allow any number of components, you just need to use them in your component. All parameters are available in the ParameterMap propery of your component. All you need to do is pull the parameter from the map and, optionall, validate it. For example,
String blogGuid = ParameterMap.PeekSafely("blogGuid");
if (String.IsNullOrEmpty(blogGuid))
{
throw new System.Configuration.ConfigurationErrorsException(String.Format("Missing parameter: {0}.", "blogGuid"));
}
You can then pass the parameters off to the parts of the component that will use the parameter. You set the parameters when you createData object. For example,
AddProcessor(ProcessorData.Create<ProcessorData>("__$Minima$PreProcessor", new Object[] { blogGuid }));
Component in Web Domain Inheritance
When working with web domain inheritance, components are also copies along side processors, factories, and other elements. Because of this, you do not need to declare the component type in more than one location.
The parameters of a component are also copied; however, you are able to override individual parameters to change the value. In the following example, there are two web domains. The second copies all of the contents of the first, including parameters, but it changes the value of one of them.
<themelia.web>
<webDomains>
<add defaultPage="/Page_/Blog/Root.aspx" catchAllMode="DefaultPage">
<components>
<add key="Minima" type="Minima.Web.Routing.Component.MinimaComponent, Minima.Web">
<parameters>
<add name="blogGuid" value="19277C41-7E4D-4AE0-A196-25F45AC48762" />
</parameters>
</add>
</components>
</add>
<add basedOn="root">
<components>
<add key="Minima">
<parameters>
<add name="blogGuid" value="19277C41-7E4D-4AE0-A196-25F45AC48762" />
</parameters>
</add>
</components>
</add>
</webDomains>
</themelia.web>
In more complex scenarios, you may have web domain which use the same component with a different number of parameters. Thus, when using web domain inheritance, you have the option to reset all parameters in a component. Using this option, you can tell the new web domain not to copy the parameters of a specific component. All you need to do is set the reset attribute on the parameters element to true. Here's an example:
<themelia.web>
<webDomains>
<add>
<components>
<add key="Sample" type="Sample.Component, Minima.Web">
<parameters>
<add name="personId" value="2" />
</parameters>
</add>
</components>
</add>
<add name="second" path="second" basedOn="root">
<components>
<add key="Sample">
<parameters reset="true">
<add name="firstName" value="john" />
<add name="lastName" value="doe" />
</parameters>
</add>
</components>
</add>
</webDomains>
</themelia.web>