Introduction
Eucalypto is an open source .NET business/server library to help write ASP.NET content management web sites. Eucalypto currently supports these features:
- Users/Membership
- Roles
- Profiles
- Forum
- Categories
- Attachments
- Answer notifications
- Formatted text
- RSS
- Category level permissions
- Content management
- Categories
- Formatted text
- Attachments
- RSS
- Category level permissions
- News
- Categories
- RSS
- Category level permissions
Eucalypto uses NHibernate for all data access, and can work with any database supported by NHibernate (SQLite, SQL Server, MySQL, Firebird, Access, Oracle, ...).
Eucalypto is well integrated with ASP.NET 2.0 using the standard provider model classes (MembershipProvider
, RoleProvider
, ProfileProvider
, ...).
Why Eucalypto?
My goal is to create a light project that can be used with any ASP.NET compatible environment, without requiring a specific database or additional framework. Eucalypto is composed by a set of .NET assemblies that you must only reference from your project.
Unlike many other similar projects, Eucalypto doesn't have a predefined user interface. Eucalypto is simply a library that can be used from your pages.
Eucalypto is not an all-or-nothing solution. You can use only a subset of the features of Eucalypto. For example, you can use the forum from Eucalypto but continue to use an existing solution for the users and roles. Each feature is isolated. For this reason, it is very easy to integrate Eucalypto in an existing ASP.NET web site.
If configured and used in the right way, I think that Eucalypto is suitable for many situations, especially because it is easy to extend, if required. You can always implement a custom provider implementation, or change the default implementation for your special needs.
Eucalypto uses NHibernate for all the data access; for this reason, you can use a wide range of database servers. See the NHibernate documentation for a list of supported databases.
There are a lot of projects that can be used to create a CMS portal, free or commercial, with similar features of Eucalypto; what are the advantages of Eucalypto?
- you can integrate Eucalypto with an existing site or architecture (Web Parts, SharePoint, an existing CMS portal, ...)
- you can support advanced or customized user interfaces (accessibility, globalization, WAP, XAML/WPF, AJAX, ...) or use a different presentation layer but the same business layer
- you can easily extend/change the business layer (thanks to the provider architecture)
- you are not limited by the features of the portal
- you can use a wide range of database types (thanks to NHibernate)
- there is a clean separation between the presentation layer and the business layer
- you can use the full power of ASP.NET and use well know technologies (master pages, themes, user controls, membership, ...)
Appropriate Uses for Eucalypto
Eucalypto uses SQLite as a default database, but thanks to NHibernate, you can configure Eucalypto to use many other databases (SQL Server, MySQL, Oracle, ...). The SQLite database is a perfect solution for a small web site. If you have thousands of users and visits, probably it is better to use another kind of architecture.
Eucalypto must be used by developers, it is not for end users or power users. You must know how to develop an ASP.NET application.
Eucalypto has some important advantages, but also some disadvantages. The most important consideration is that creating a web site with Eucalypto requires some development and configuration. Eucalypto is not a complete web portal, it is a library. You need some time to create a complete and running web site.
If you are looking for a complete portal or a different solution, you can probably try one of these other projects:
Requirements
Currently, Eucalypto is developed using .NET 2.0, Windows, IIS, and SQLite (or SQL Server). Eucalypto is written using 100% managed code, but some references are not compiled as managed library (for example, SQLite).
Probably, using the right database (like MySQL), Eucalypto can be executed also on Linux and Mono, but I have not tested it for now. I don't know if the latest release of NHibernate and Log4net are fully compatible with other platforms, but I hope not to have many problems in the future.
Packages
Eucalypto is composed of two packages:
- Eucalypto1 - Main Eucalypto package. Contains the source and binary files for Eucalypto.
- Eucalypto - The Eucalypto.dll assembly
- Eucalypto.Test - Eucalypto NUnit test assembly
- Eucalypto1.Demo - Demo package
- WebSite - Demonstration of an ASP.NET website
Demonstration web site
You can also install the demo project on your server if you want to look at the code or modify it. Here are the steps to run the Eucalypto demo project on your server:
- download the Eucalypto.Demo package, open it with Visual Studio 2005, and run the WebSite project
- open the Setup.aspx page to configure the database and create an administrator user
- open the administration page at Admin/Default.aspx for the administrative tasks
Now, you can start to use the Eucalypto demo project. See the following sections if you need more information on the available configurations.
Creating your Website
One common method to start using Eucalypto is to download the Eucalypto.Demo package and use it as a starting point. Eucalypto.Demo contains some useful classes and a working configuration. Here is a short description of the Eucalypto.Demo components:
- \web.config - Main configuration file.
- \Site.master - Page used for the master page.
- \Global.asax - Main application class.
- \Controls\*.* - Some common user controls.
- \Admin\*.* - Administration pages.
- \App_Themes\*.* - Themes, skin, CSS, and images.
- \Setup.aspx - Page used to create the database schema (can be removed in the production environment).
- \User\*.* - User management pages (user settings, change password, ...).
- \Forum\*.* - Forum management pages.
- \Wiki\*.* - Wiki/articles management pages.
- \News\*.* - News management pages.
Many of the pages can simply be used as a starting point, and if you are already familiar with ASP.NET, you can see that the code used is quite simple.
For more information about the configuration file, see the Configuration section. For more information about the required references, see the References section.
Providers Overview
All the base features of Eucalypto are created using a Provider Model pattern (a patter similar to the Inversion Of Control). The Provider Model pattern guarantees easy customization and extensions. If you want, you can create your own providers to save data to another data source, or with a different format, or with special business rules.
ASP.NET 2.0 already uses the Provider pattern for the membership, roles, and profiles features.
Currently, Eucalypto implements these providers:
Eucalypto.Membership.EucalyptoMembershipProvider
- An implementation of System.Web.Security.MembershipProvider
.
Eucalypto.Roles.EucalyptoRoleProvider
- An implementation of System.Web.Security.RoleProvider
.
Eucalypto.Notification.EucalyptoSmtpNotificationProvider
- A new provider that can be used to send notifications to users using SMTP and preconfigured e-mail templates. Used by the forum provider to notify users.
Eucalypto.Profile.EucalyptoProfileProvider
- An implementation of System.Web.Profile.ProfileProvider
.
Eucalypto.Forum.EucalyptoForumProvider
- A new provider that can be used to create a complete forum solution.
Eucalypto.Wiki.EucalyptoWikiProvider
- A new provider that can be used to insert, update, and retrieve articles.
Eucalypto.News.EucalyptoNewsProvider
- A new provider that can be used to manage news.
Each provider is isolated from the other. For example, you can use the forum provider with the Eucalypto database and the membership provider using the default SQL Server database.
Depending on what part of Eucalypto you want to use, you need different settings. Usually, the most important setting is the connection string.
You can create a standard connectiostring
element inside the web.config, and set a connection string with this format:
DriverClass=DRIVER;Dialect=DIALECT;CONNECTION_STRING
The connection string is formed by three sections:
DriverClass=DRIVER
- The NHibernate driver to use. See the NHibernate documentation for more details about drivers.
Dialect=DIALECT
- The NHibernate dialect to use. See the NHibernate documentation for more details about dialects.
CONNECTION_STRING
- The other part of the connection string is used directly and can be different for each driver.
The first two properties are used for the NHibernate configuration. You can also use a special variable |DataDirectory|
that will be replaced with the site server application data path.
SQLite
In the following code, you can see an example of a connection to a SQLite database:
<connectionStrings>
<clear/>
-->
<add name="DefaultConnection"
connectionString="DriverClass=NHibernate.Driver.SQLite20Driver;
Dialect=NHibernate.Dialect.SQLiteDialect;
Data Source=|DataDirectory|\data.db3" />
</connectionStrings>
Remember that you must use a directory where the ASP.NET process has read and write permissions. Below is an example on how to configure the write permission to the App_Data folder on Windows 2003:
The SQLite driver automatically creates the database file if it doesn't exist.
SQL Server
In the following code, you can see a connection string for SQL Server 2005:
<connectionStrings>
-->
<add name="DefaultConnection"
connectionString="DriverClass=NHibernate.Driver.SqlClientDriver;
Dialect=NHibernate.Dialect.MsSql2005Dialect;
Data Source=localhost;
Initial Catalog=Eucalypto;Integrated Security=SSPI;"
/>
</connectionStrings>
You must manually create the empty database and then give the ASP.NET process read and write permissions to the database using the "SQL Server Management Studio" or an appropriate SQL script. For more information about security, try to look at the following MSDN article: 'How To: Connect to SQL Server Using Windows Authentication in ASP.NET 2.0'.
To create the database, you can use this script:
CREATE DATABASE Eucalypto
Other databases
Here is a list of connection strings for the most common databases:
- SQLite -
DriverClass=NHibernate.Driver.SQLite20Driver; Dialect=NHibernate.Dialect.SQLiteDialect; Data Source=|DataDirectory|\data.db3
- SQL Server 2005 -
DriverClass=NHibernate.Driver.SqlClientDriver; Dialect=NHibernate.Dialect.MsSql2005Dialect; Data Source=localhost;Initial Catalog=Eucalypto;Integrated Security=SSPI;
- SQL Server Express 2005 -
DriverClass=NHibernate.Driver.SqlClientDriver; Dialect=NHibernate.Dialect.MsSql2005Dialect;data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename =|DataDirectory|data.mdf;User Instance=true
- SQL Server 2000 -
DriverClass=NHibernate.Driver.SqlClientDriver; Dialect=NHibernate.Dialect.MsSql2000Dialect;Data Source=localhost;Initial Catalog=Eucalypto;Integrated Security=SSPI;
- MySQL -
DriverClass=NHibernate.Driver.MySqlDataDriver; Dialect=NHibernate.Dialect.MySQLDialect; Database=Eucalypto;Data Source=SomeServer;User Id=SomeUser;Password=SomePassword
- ...
Create Database Schema
Now, you must create the Eucalypto database schema. I have written a page, Setup.aspx (inside the WebSiteTest project), that can be used to create the required database schema. You can usually copy this page inside your project and open it with your browser (Note: for security reasons, this page can be executed only from the local server machine).
This page uses the Eucalypto.SchemaGenerator.GenericGenerator
class to generate the schema for the selected connection string. You can select the connection string using the drop down at the top of the page (this drop down is loaded with the current connections configured inside the web.config) and then click on the 'Create schema' button to generate the schema.
The Eucalypto.SchemaGenerator.GenericGenerator
class uses the NHibernate.Tool.hbm2ddl.SchemaExport
code to generate the schema. If you have problems, you can always manually create the database tables.
Remember that for now, this tool cannot upgrade an existing table. If the table already exists, its contents will be deleted.
In the Setup.aspx page, there is also a feature to create the administrative user and role; you must simply choose a new password and click on the 'Create admin user' button.
Administrator Features
I have created a set of pages for the most important administrative tasks. You can copy the Admin folder of the WebSiteTest project inside your website. In this folder, you can find some pages to configure many features of Eucalypto.
Open the Admin/Default.aspx page for an overview of the available configurations. This page requires you to login as an administrator (administrators role), so you must first have correctly configured the user and roles and have created an admin user.
After you have configured the main features, you can start using Eucalypto. See the sections below for the configuration for each feature.
Membership and Roles
The Membership provider is an ASP.NET provider. ASP.NET membership gives you a built-in way to validate and store user credentials, it can be integrated with ASP.NET role management to provide authorization services for your site.
Database diagram
Configuration
To use the membership and role features, you must configure ASP.NET to use the Eucalypto providers, adding this section inside the web.config file:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.web>
-->
<authentication mode="Forms">
<forms loginUrl="Login.aspx" defaultUrl="Default.aspx">
</forms>
</authentication>
-->
<authorization>
-->
<allow users="?"/>
</authorization>
-->
<membership defaultProvider="EucalyptoMembershipProvider">
<providers>
<clear/>
<add name="EucalyptoMembershipProvider"
type="Eucalypto.Membership.EucalyptoMembershipProvider, Eucalypto"
connectionStringName="DefaultConnection"
applicationName="Default"
minRequiredNonAlphanumericCharacters="0"
minRequiredPasswordLength="4"
/>
</providers>
</membership>
-->
<roleManager enabled="true" defaultProvider="EucalyptoRoleProvider">
<providers>
<clear />
<add name="EucalyptoRoleProvider"
connectionStringName="DefaultConnection"
applicationName="Default"
type="Eucalypto.Roles.EucalyptoRoleProvider, Eucalypto" />
</providers>
</roleManager>
</system.web>
</configuration>
You can configure the users and roles using the standard ASP.NET Configuration website:
Usage
There are many good articles about the Membership and Role features of ASP.NET; here are some links:
Please not that for now, the EucalyptoMembershipProvider
supports only hashed passwords and do not support the password retrieval feature (EnablePasswordRetrieval
), only supports password reset.
Profile
The Profile provider is an ASP.NET provider. You can provide the users of your website with a custom experience by defining and using profile properties. You can use profile properties to track any custom information your application requires.
Database diagram
Configuration
To use the Profile features, you must configure ASP.NET to use the Eucalypto providers, adding this section inside the web.config file:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.web>
-->
-->
<anonymousIdentification enabled="true" />
<profile defaultProvider="EucalyptoProfileProvider">
<providers>
<clear />
<add name="EucalyptoProfileProvider"
type="Eucalypto.Profile.EucalyptoProfileProvider, Eucalypto"
connectionStringName="DefaultDB" applicationName="Default" />
</providers>
<properties>
-->
<add name="FavoriteColor" type="String"
defaultValue="Blue" allowAnonymous="true" />
</properties>
</profile>
</system.web>
</configuration>
Usage
There are many good articles about the Profile features of ASP.NET; here are some links:
Notification
Configuration
To use the Notification features, you must first configure the notification provider, adding these sections inside the web.config:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<configSections>
-->
<section name="notificationManager"
type="Eucalypto.Notification.NotificationProviderConfiguration, Eucalypto"/>
</configSections>
-->
<system.net>
<mailSettings>
<smtp>
<network host="yourSmtpServer" port="25"
userName="username" password="password" />
</smtp>
</mailSettings>
</system.net>
-->
<notificationManager>
<providers>
<add name="EucalyptoForumSmtp"
type="Eucalypto.Notification.EucalyptoSmtpNotificationProvider, Eucalypto"
template="App_Data\MailTemplate_Forum.xml" />
</providers>
</notificationManager>
</configuration>
Use the enabled
property to enable or disable the provider. The template
property must be configured with a valid XML file that contains the template data used when sending e-mails. Here is an example:
="1.0" ="utf-8"
<template>
<sender>youremail@yourserver.com</sender>
<subject>[Eucalypto - Forum ?forumDescription?] ?title?</subject>
<body html="true">
<![CDATA[]]>
</body>
</template>
You can use some parameters specified by who will use the notification provider (for example, ?title?, ?user?, ...) that will be replaced by the actual data of the notification. In this case, I have used the parameters used by the forum provider.
Usage
The EucalyptoSmtpNotificationProvider
provider can send notification using SMTP (e-mail). You can use the static property Eucalypto.Notification.NotificationManager.Providers
to read a list of the configured providers.
Here is a simple example to send a notification:
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("?title?", message.Title);
parameters.Add("?body?", xhtml);
parameters.Add("?user?", message.Owner);
System.Web.Security.MembershipUser destinationUser =
System.Web.Security.Membership.GetUser(user);
if (destinationUser != null &&
NotificationProvider.UserCanReceiveNotification(destinationUser))
{
NotificationProvider.NotifyUser(destinationUser, parameters);
}
Forum
Database diagram
Configuration
To use the forum features, you must first configure the forum provider, adding these sections inside the web.config:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<configSections>
-->
<section name="forumManager"
type="Eucalypto.Forum.ForumProviderConfiguration, Eucalypto"/>
</configSections>
-->
<forumManager defaultProvider="EucalyptoForumProvider">
<providers>
<clear/>
<add name="EucalyptoForumProvider"
type="Eucalypto.Forum.EucalyptoForumProvider, Eucalypto"
connectionStringName="DefaultConnection"
notificationProvider="EucalyptoSmtp" />
</providers>
</forumManager>
</configuration>
You can configure the forum provider with these properties:
connectionStringName
- The connection used to store forum data.
notificationProvider
- Notification provider to use to notify users if someone responds to a message. See the Notification section for more details. Leave blank to not use a notification provider.
The default provider is the EucalyptoForumProvider
that uses NHibernate to store any forum related data. Consider that, if required, you can always implement your custom forum provider.
Internally, the forum provider uses the Notification provider, so usually, you must also configure it.
Usage
You can find all the forum related classes inside the Eucalypto.Forum
namespace. You must use the Eucalypto.Forum.ForumManager
class to insert, read, or delete forum data. The main entities are:
Category
- A forum category represents a forum. A forum category is composed of a list of topics.
Topic
- A topic represents the subject of discussion, the initial message posted to the discussion. A topic is composed of a list of messages.
Message
- A message is the main entity of a forum. Represents the text posted by the user of the forum.
You can enable or disable attachments, accepted extensions, and maximum file size, or configure the security for each forum. Use the administration section to configure each forum.
The forum messages are saved using XHTML format.
Here is an example of how to create a forum category, insert some messages, and search for it:
Eucalypto.Forum.Category category =
Eucalypto.Forum.ForumManager.CreateCategory("test", "test");
Eucalypto.Forum.Topic topic;
Eucalypto.Forum.Message message;
Eucalypto.Forum.ForumManager.CreateTopic(category, "user1",
"Title 1", "<p>Body text</p>",
null, out topic, out message);
Eucalypto.Forum.Message message1 =
Eucalypto.Forum.ForumManager.CreateMessage(topic, message.Id,
user1", "RE: Title 1", "<p>Response</p>", null);
//Create a second answer (message)
Eucalypto.Forum.Message message2 =
Eucalypto.Forum.ForumManager.CreateMessage(topic, message1.Id,
"user1", "RE: Title 1", "<p>Response</p>", null);
//Create a second topic
Eucalypto.Forum.Topic topic2;
Eucalypto.Forum.Message message3;
Eucalypto.Forum.ForumManager.CreateTopic(category, "user2",
"Title 2", "<p>Body text</p>",
null, out topic2, out message3);
//Find the previous messages (filtering the owner field)
Eucalypto.PagingInfo paging = new Eucalypto.PagingInfo(10, 0);
Eucalypto.Forum.ForumManager.FindMessages(Eucalypto.Filter.MatchOne( category.Name),
null,
Eucalypto.Filter.MatchOne("user1"),
null,
null, null,
paging);
//Find the previous messages (filtering by a field)
Eucalypto.Forum.ForumManager.FindMessages(Eucalypto.Filter.MatchOne(category.Name),
Eucalypto.Filter.ContainsOne("RE:"),
null, null, null, null, paging);
//Delete a topic
Eucalypto.Forum.ForumManager.DeleteTopic(topic);
//Create another topic
Eucalypto.Forum.Topic topic3;
Eucalypto.Forum.Message message4;
Eucalypto.Forum.ForumManager.CreateTopic(category, "test", "Title 3",
"<p>Body text</p>", null, out topic3, out message4);
//Delete the category
Eucalypto.Forum.ForumManager.DeleteCategory(category);
Content Management (Wiki articles provider)
Database diagram
Configuration
To use the content management features, you must first configure the wiki provider, adding these sections inside the web.config:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<configSections>
-->
<section name="wikiManager"
type="Eucalypto.Wiki.WikiProviderConfiguration, Eucalypto"/>
</configSections>
-->
<wikiManager defaultProvider="EucalyptoWikiProvider">
<providers>
<clear/>
<add name="EucalyptoWikiProvider"
type="Eucalypto.Wiki.EucalyptoWikiProvider, Eucalypto"
connectionStringName="DefaultDB" />
</providers>
</wikiManager>
</configuration>
You can configure the wiki provider with these properties:
connectionStringName
- The connection used to store the article data.
The default provider is the EucalyptoWikiProvider
that uses NHibernate to store any article related data. Consider that, if required, you can always implement your custom provider.
Usage
You can find all the wiki related classes inside the Eucalypto.Wiki
namespace. You must use the Eucalypto.Wiki.WikiManager
class to insert, read, or delete article data. The main entities are:
Category
- A wiki category. A category is composed of a list of articles.
Article
- An article represents the content. An article can contain a list of FileAttachment
s and a list of VersionedArticle
s.
FileAttachment
- A message is the main entity of a forum. Represents the text posted by the user of the forum.
VersionedArticle
- Each time the user updates an Article
, the previous version is saved in a new VersionedArticle instance.
You can enable or disable attachments, accepted extensions, and maximum file size, or configure the security for each category. Use the administration section to configure each category..
The article contents are saved using XHTML format.
Here is an example to insert some articles:
Eucalypto.Wiki.Category category =
Eucalypto.Wiki.WikiManager.CreateCategory("test", "test");
Eucalypto.Wiki.Article article =
Eucalypto.Wiki.WikiManager.CreateArticle(category, "owner1",
"article1", "Title 1", "Description",
"<p>body 1</p>");
Eucalypto.Wiki.Article article2 =
Eucalypto.Wiki.WikiManager.CreateArticle(category, "owner2",
"article2", "Title 2", "Description",
"<p>bla bla bla search1 bla bla bla</p>");
article.Body = "<p>body 1 v2</p>";
string myTag = Guid.NewGuid().ToString();
article.Tag = myTag;
Eucalypto.Wiki.WikiManager.UpdateArticle(article, true);
Eucalypto.Wiki.ArticleBase articleV1 =
Eucalypto.Wiki.WikiManager.GetArticleByVersion(article, 1);
Eucalypto.PagingInfo paging = new Eucalypto.PagingInfo(10, 0);
IList<Eucalypto.Wiki.Article> articles =
Eucalypto.Wiki.WikiManager.FindArticles(Eucalypto.Filter.MatchOne(category.Name),
Eucalypto.Filter.ContainsAll("search1"),
null, null, null, null, null,
Eucalypto.Wiki.ArticleStatus.All,
paging);
articles = Eucalypto.Wiki.WikiManager.FindArticles(null, null, null, null,
Eucalypto.Filter.MatchOne(myTag), null, null,
Eucalypto.Wiki.ArticleStatus.All, paging);
Eucalypto.Wiki.WikiManager.DeleteArticle( article );
Eucalypto.Wiki.WikiManager.DeleteCategory( category );
News
Database diagram
Configuration
To use the news features, you must first configure the news provider, adding these sections inside the web.config:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<configSections>
-->
<section name="newsManager"
type="Eucalypto.News.NewsProviderConfiguration, Eucalypto"/>
</configSections>
-->
<newsManager defaultProvider="EucalyptoNewsProvider">
<providers>
<clear/>
<add name="EucalyptoNewsProvider"
type="Eucalypto.News.EucalyptoNewsProvider, Eucalypto"
connectionStringName="DefaultDB" />
</providers>
</newsManager>
</configuration>
You can configure the news provider with these properties:
connectionStringName
- The connection used to store news data.
The default provider is the EucalyptoNewsProvider
that uses NHibernate to store any news related data. Consider that, if required, you can always implement your custom news provider.
Usage
You can find all the news related classes inside the Eucalypto.News
namespace. You must use the Eucalypto.News.NewsManager
class to insert, read, or delete news data. The main entities are:
Category
- A news category is composed of a list of items.
Item
- An item represents a news row. An item is composed of Title, URL, Description, ...
Use the administration section to configure each news category.
Here is an example of how to create a news category and insert some items:
Eucalypto.News.Category category =
Eucalypto.News.NewsManager.CreateCategory("test", "test");
Eucalypto.News.Item item = Eucalypto.News.NewsManager.CreateItem(category,
"owner1", "Title 1",
"Description 1",
"http://www.google.com/",
"DevAge home page", new DateTime(2006, 1, 3));
Eucalypto.News.Item item2 = Eucalypto.News.NewsManager.CreateItem(category,
"owner1", "Title 2",
"Description 2",
"http://www.google.com/", "DevAge home page",
new DateTime(2006, 10, 3));
item.Description = "Description modified";
Eucalypto.News.NewsManager.UpdateItem(item);
Eucalypto.PagingInfo paging = new Eucalypto.PagingInfo(10, 0);
Eucalypto.News.NewsManager.FindItems(Eucalypto.Filter.MatchOne(category.Name),
null, null, null,
paging);
Eucalypto.News.NewsManager.DeleteItem(item2);
Eucalypto.News.NewsManager.DeleteCategory(category);
Custom Entities
You can extend Eucalypto using custom entities to store additional information for your specific application. Eucalypto exposes a series of classes to simplify the creation and integration of custom entities. In the following sections, you will see how to create a custom Dog
entity, complete with the data access class.
Remember that Eucalypto uses NHibernate for all data access, so I usually suggest to first read and understand the NHibernate architecture and code. Eucalypto simply hides some configurations and code, but some experience of NHibernate is important.
The first step is to configure Eucalypto to identify and use your assembly. You can configure Eucalypto by adding a custom section in the configuration file:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<configSections>
-->
<section name="eucalypto"
type="Eucalypto.Configuration.EucalyptoSection, Eucalypto" />
</configSections>
-->
<eucalypto>
-->
<mappings>
<add assembly="MyAssembly" />
</mappings>
</eucalypto>
</configuration>
The assembly MyAssembly
in the above configuration is the custom assembly that will contain your entities.
Now, you can create the actual entity class.
namespace Eucalypto.Test.CustomEntity
{
public class Dog
{
protected Dog(){ }
public Dog(string name, string displayName)
{
Name = name;
DisplayName = displayName;
}
private string mId;
public virtual string Id
{
get { return mId; }
protected set { mId = value; }
}
private string mName;
public virtual string Name
{
get { return mName; }
protected set { mName = value; }
}
private string mDisplayName;
public virtual string DisplayName
{
get { return mDisplayName; }
set { mDisplayName = value; }
}
private string mDescription;
public virtual string Description
{
get { return mDescription; }
set { mDescription = value; }
}
}
}
As you can see, this is just a standard .NET class, the only required code is the Id
property used as the primary key for the entity and a default constructor (public
or protected
). Compile this class in your assembly. Now, you can create the file that defines the database mapping using the NHibernate configuration file:
="1.0" ="utf-8"
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Eucalypto.Test.CustomEntity.Dog, MyAssembly" table="Dog">
<id name="Id" column="Id" type="String" length="32" >
<generator class="uuid.hex">
<param name="format">N</param>
</generator>
</id>
<property name="Name" type="String">
<column name="Name" unique-key="KeyName" not-null="true" length="100"/>
</property>
<property name="DisplayName" column="DisplayName"
type="String" length="100" not-null="true" />
<property name="Description" column="Description" type="String" length="300" />
</class>
</hibernate-mapping>
You must save this XML in an embedded resource of your assembly with the extension .hbm.xml (for example, Dog.hbm.xml; the .hbm.xml is required by NHibernate). You can usually use any feature of NHibernate (nested classes, collections, inheritance, ...); refer to the NHibernate documentation for more details.
The next step is to create the data access class. Note that you can also use a custom data access class, but using the Eucalypto code can save you some time:
namespace Eucalypto.Test.CustomEntity
{
public class DogDataStore : EntityDataStoreBase<Dog, string>
{
public DogDataStore(TransactionScope transactionScope)
: base(transactionScope)
{
}
public Dog FindByName(string name)
{
ICriteria criteria = CreateCriteria();
criteria.Add(Expression.Eq("Name", name));
return FindUnique(criteria);
}
public IList<Dog> FinAll()
{
ICriteria criteria = CreateCriteria();
criteria.AddOrder(Order.Asc("DisplayName"));
return base.Find(criteria);
}
}
}
The EntityDataStoreBase
is a generic abstract class that can be used for the basic data access features (Insert, Delete, Update, ...). You just need to implement your specific features, usually custom selection and filter.
That's all. Now, you are ready to use your entity. Here is an example of how you can use the custom entity:
ConnectionParameters parameters = ConnectionParameters.Create("DefaultDB");
using (TransactionScope transaction = new TransactionScope(parameters))
{
CustomEntity.DogDataStore dataStore =
new Eucalypto.Test.CustomEntity.DogDataStore(transaction);
dataStore.Insert(new Eucalypto.Test.CustomEntity.Dog("black", "Black"));
dataStore.Insert(new Eucalypto.Test.CustomEntity.Dog("white", "White"));
dataStore.Insert(new Eucalypto.Test.CustomEntity.Dog("red", "Red"));
CustomEntity.Dog redDog = dataStore.FindByName("red");
dataStore.Delete(redDog.Id);
CustomEntity.Dog blackDog = dataStore.FindByName("black");
blackDog.DisplayName = "Black dog";
transaction.Commit();
}
Consider that you need a valid connection string (in the example called DefaultDB
) and a valid database. See the previous configuration section for more information. If you want, you can also generate the schema of your custom entities using the automatic schema generator; in this case, you need another step to configure the schema generator in this way:
[assembly: Eucalypto.SchemaGenerator.SetupMapping("Custom",
"Eucalypto.Test.CustomEntity.Dog, MyAssembly")]
Then, you can automatically generate the schema of the database with this code:
Eucalypto.ConnectionParameters config =
ConnectionParameters.Create(Settings.CONNECTIONSTRING);
Eucalypto.SchemaGenerator.GenericGenerator generator =
new Eucalypto.SchemaGenerator.GenericGenerator(config);
foreach (string cat in generator.GetSchemaCategories())
{
generator.CreateSchemaTable(cat);
}
The above code creates the schema for all the available categories (also the system Eucalypto categories). Each category is defined in the first parameter of the SetupMappingAttribute
.
Implementation Details
NHibernate
"NHibernate is a port of Hibernate Core for Java to the .NET Framework. It handles persisting plain .NET objects to and from an underlying relational database."
You can configure NHibernate to use many kinds of databases: SQL Server, Oracle, MySQL, ... The default database for Eucalypto is SQLite.
SQLite
"SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine."
To query or update a SQLite database, I really suggest using SQLite Spy, a very powerful and useful tool. Thanks to Ralf Junker. You can download it from here.
Usually, you can find the SQLite database inside the App_Data directory.
Important notes: SQLite is currently written with C++ as an unmanaged library. For this reason, you must remember that SQLite must be executed with full trust permissions. If you want to use a shared hosting (run your website on a hosting company), you must consider that they are usually configured as medium trust. Medium trust security blocks any P/Invoke code and SQLite cannot run. In this case, you can ask your hosting company to run your app with full trust, or ask to install SQLite library inside GAC. Remember anyway that Eucalypto can be used with many other databases. For example, many hosting companies offer MySQL, Access, or SQL Server.
Log4Net
"log4net is a tool to help the programmer output log statements to a variety of output targets. log4net is a port of the excellent log4j framework to the .NET runtime."
Eucalypto internally uses log4net for logging exceptions and warnings. The entire log4net configuration can be changed in the web.config file. In the global.asax file, I configure Eucalypto with this code: log4net.Config.XmlConfigurator.Configure()
. Usually, you can find the log4net log file inside the App_Data directory.
CSS
I hate CSS .... Every time I must work on a page layout, I fight with CSS. For this reason, I always look for some simple and clear examples.
I want to thank Alessandro Fulciniti, for his great work on CSS. For me, these are the most clean and simply to use CSS layouts.
For this site, I have used a modified version of a CSS layout that I have found on the above page.
Provider Model
For more information about the ASP.NET provider model, I suggest you read these MSDN articles:
RSS
Eucalypto has an integrated RSS library, written by Brian Kuhn. Thanks for his work.
More info at "RSS 2.0 Class Library and Syndication Provider".
For information about the RSS format and specifications, you can check out this website.
XHTML
All the content written by the users are saved as XHTML. For example, all the wiki content and forum messages are written using XHTML. I have chosen this format for many reasons:
- It is the native format for the web pages, and is supported by many platforms/browsers
- It is a standard and well known format
- Can be easily parsed and modified by humans and from code (using any XML parser)
- Can be easily converted to other formats
- Can be easily used inside email
NUnit
"NUnit is a unit-testing framework for all .NET languages."
I have created a test project for Eucalypto (Eucalypto.Test) with some test cases. See Eucalytpo.nunit
for the NUnit configuration.
HttpModuleCheckValidUser
I have created a custom HttpModule Eucalypto.Membership.HttpModuleCheckValidUser
to add an additional security check. Basically, this HTTP module is used to check if a user already authenticated is approved and not locked. This is useful, for example, when a user is automatically authenticated using the "Remember me" cookie.
To use this module, you must add this configuration inside the system.web
configuration element:
<!---->
<httpModules>
<add type="Eucalypto.Membership.HttpModuleCheckValidUser, Eucalypto"
name="CheckValidUser" />
</httpModules>
Here are the required assemblies that you need to reference:
- Eucalypto.dll - Main Eucalypto assembly
- NHibernate.dll - NHibernate main assembly
- Castle.DynamicProxy.dll - Dynamic proxy generator used by NHibernate
- Iesi.Collections.dll - Advanced collections used by NHibernate
- NHibernate.Tool.hbm2net.dll - Schema generator for NHibernate
- log4net.dll - Used for logging
- [System.Data.SQLite.DLL] - Optional, required only if you use SQLite
- [nunit.framework.dll] - Optional, required only for the Eucalypto.Test NUnit project
Future works
- Extend unit tests
- Stress/performance improvements
- Create a set of web server controls (or skinned controls) for the Eucalypto providers for easy reuse
- Improved search support
- HTML text editor for forum and articles (FCKeditor?)
- Issue tracking system
- Photo album
- Blog
History
7 June 2009 - Version 1.3
- Updated links at the top of this article
2 May 2007 - Version 1.2
- Fixed a bug in the
Filter
class when using MatchMode.End
or MatchMode.Start
.
- Fixed documentation English errors.
20 Apr 2007 - Version 1.1
- Improved the configuration classes for better extendibility.
- Improved the schema generator that now can be extended with custom classes and assemblies.
- Renamed the class
Eucalypto.Configuration
to Eucalypto.ConnectionParameters
.
- Added the ability to add custom mapping assembly using the Eucalypto configuration section of the config file, and created a generic setup configuration that can be used by custom entities.
- Added a custom entity example and test.
- New documentation section that shows how to create and use custom entities.
- Fixed the TOC generator to not consider white space characters inside the heading tags.
- Improved the security code (
SecurityHelper
) used to check for permissions for a specific operation on an entity. Now, supports denies permissions for a role using the prefix '!'.
04 Apr 2007 - Version 1.0
- Updated references of NHibernate 1.2.0.3001 and SQLite 1.0.40.0.
- Added the Eucalypto/Membership/HttpModuleCheckValidUser.cs HttpModule to check if a user is still valid if authenticated with the cookie.
- Fixed a bug in the Filter implementation (caused by a different behaviour of the new NHibernate).
- Updated the
HttpModuleCheckValidUser
to consider the user online and update the activity date.
24 Mar 2007 - Version 0.9
Note: This version has some changes on the database schema. You can upgrade an old database using the SQL scripts inside the SQLScript folder (SQLScript\UpgradeY.YtoX.X).
- Fixed a bug in the
TransactionScope
to correctly execute the rollback when the object is Disposed (I think that this bug occurs only on MySQL).
- Fixed a bug to correctly show the update date of the archived articles. Removed the
OriginalDate
column from the WikiVersionedArticle table and changed the code that creates a VersioneArticle
instance to copy the UpdateDate
and InsertDate
column from the source Article table.
- Better exception if an article name is already used.
- Improved demo website (see ChangeLog.txt).
14 Feb 2007 - Version 0.8.6.0
- Fixed an error that prevents inserting a null or empty description when generating the RSS item.
- Now, the Membership and Role providers implementation use a case insensitive search for user name and e-mail (like the MS provider).
28 Jan 2007 - Version 0.8.5.0
Eucalypto LICENSE (MIT style)
Copyright (c) 2007 Davide Icardi.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.