Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

ASP.NET Content Editor Control for Basic Content Management

4.69/5 (7 votes)
27 Jan 2009CPOL11 min read 59K   2.5K  
A web control that lets you maintain page content using a comprehensive HTML editor, persisting the content to a database.

Image 1

Introduction

This web control provides you with the ability to maintain the content of your website pages without the need for using any client software or heavyweight server side content management system. What motivated me to develop this control was that I had an existing ASP.NET website and I wanted a means to be able to regularly update its content quickly from anywhere by simply using a browser. You can visit www.goodforyourecords.co.uk which demonstrates this control in action. It's straightforward to incorporate into your site, and easy to use. The control allows you to edit, preview, and save your content to a database, and provides comprehensive editing through the use of the FreeTextBox control.

What this control is designed to do:

  • edit and preview HTML content within an ASP.NET page
  • save and retrieve the content using a database (MS Access / SQL Server / SQL Express / SQL Compact Edition)
  • allow the content displayed by the control to change through use of query string parameters
  • allow multiple instances of the control to reside on a single page
  • easy modification of your existing pages to incorporate the content control
  • tested with IE7 and Firefox 3.0.5

What it doesn't do:

  • manage the page structure of your site (it's not a content management system!)
  • allow multi-user editing (there's no locking functionality implemented - yet)

Incorporating this control into one of your pages is simple:

  • within Visual Studio, add the ContentEditor control to your toolbox and drop the control onto your page
  • assign a content ID to the control
  • drop the empty WebSiteContent.mdb database file to your web app's App_Data directory
  • add some configuration items to your web.config
  • authenticate the current user to allow editing to begin ...

That's it - you now have a page whose content can be edited online through your web browser.

Adding the ContentEditor Control to Pages

The demo project provides a simple example of what can be done with the ContentEditor control. The Default.aspx file contains four instances of the control of which three demonstrate the idea of switching content using query string parameters - more on this later. There is also a demo login page which provides a means of authenticating a user to enable him or her to modify the content of these instances. If your site already has a means of authenticating users, then you may not require this. If you don't, you will need to add at least this page to your site - don't worry, it's simple.

Steps to Add ContentEditor to your Website

Adding the Control to Visual Studio

Open your website in Visual Studio, and add the control to the toolbox. Do this through View->Toolbox. Right click in the toolbox panel, and select "Choose Items". On the ".NET Framework Components" tab, click "Browse", and then locate the bin folder of ContentEditor.dll in the source code project. Click "Open" and then "Ok". The control DLL should have been copied to your bin folder and now be available in your toolbox. You should now be able to drag and drop the control onto the design surface of your page.

In the properties grid, set the ContentId of the control to a unique string value. This identifies the content that will be displayed by the control.

Adding Configuration to Web.Config

Add the following configuration to your web.config file:

XML
<appSettings>
    <add key="ContentEditor.ContentDataProviderAssembly" value="ContentEditor"></add>
    <add key="ContentEditor.StyleSheetUrl" value="ContentEditor.css"></add>    
</appSettings>

You'll need to copy the ContentEditor.css style sheet from the demo project to the root directory of your website. If you wish to use another folder, modify the value of ContentEditor.StyleSheetUrl to specify the appropriate path.

Now, you need to decide what sort of database to use to hold the content. By far, the simplest solution is to use an in-process database such as MS Access or SQL Compact Edition. There's no database administration to worry about, just a file to drop into the App_Data folder. It's the best option for a small site. Not all ISPs support SQL Compact, and if yours doesn't, then choose MS Access. If you choose MS Access, then add the following to the <appSettings> element of your web.config:

XML
<add key="ContentEditor.ContentDataProviderType" 
     value="ContentEditing.OleDb.OleDbContentDataProvider"></add>

If you wish to use SQL Compact, SQL Express, or SQL Server, add the following instead:

XML
<add key="ContentEditor.ContentDataProviderType" 
     value="ContentEditing.LinqSql.LinqSqlContentDataProvider"></add>

If using either MS Access or SQL Compact, copy either the .mdb (for MS Access) or the .sdf (for SQL Compact) database file to your website's App_Data folder. For MS Access, add the following to the <connectionStrings> element in your web.config file:

XML
<add name="ContentEditor.WebContentDatabase" 
     connectionString="provider=Microsoft.Jet.OLEDB.4.0;
                       data source=|DataDirectory|WebSiteContent.mdb"/>

For SQL Compact, use:

XML
<add name="ContentEditor.WebContentDatabase" 
     connectionString="data source=|DataDirectory|WebSiteContent.sdf;
                       Persist Security Info=false"/>

For SQL Express or SQL Server, you'll need to setup up the database manually using SQL Server Management Studio. The CreateContentTable.sql SQL script in the ContentEditor project can be used to create the required table. Set the connection string accordingly; for example, for SQL Server:

XML
<add name="ContentEditor.WebContentDatabase" 
     connectionString="Data Source=localhost;Initial Catalog=WebSiteContent;
                       Integrated Security=True"/>

Authenticating Users to Edit Content

Now, you need to enable authenticated users the ability to edit content. As mentioned previously, you can either use an existing authentication mechanism of your site, or if you don't have one, then copy the login page (Login.aspx) from the demo site. The ContentControl class provides two static methods to control editing behaviour:

C#
/// <summary>
/// Enables content editing for the current user session.
/// Once enabled, content can be edited and viewed in preview mode.
/// </summary>
public static void EnableEditingForCurrentSession()

/// <summary>
/// Disables content editing for the current user session.
/// Once disabled, the content is output without 
/// any modification by this control.
/// </summary>
public static void DisableEditingForCurrentSession()

Once your authentication mechanism has deemed the user worthy of editing content, you simply call EnableEditingForCurrentSession. This will allow the user to edit and preview content for the duration of the client's session. Calling DisableEditingForCurrentSession disables any editing for the client's session, and switches the control to View mode, whereby the edited content is rendered directly by the control - in other words, as it will be seen by end users. Call this when the user logs out.

If you choose to use the login page from the demo project, simply copy the page to your website. You'll need to add the user's username and password to your web.config, as follows:

XML
<authentication mode="Forms">
    <forms name="appNameAuth" protection="All" timeout="30">
        <credentials passwordFormat="Clear">
            <user name="user" password="password" />
        </credentials>
    </forms>
</authentication>

By default, successful authentication results in a redirect to Default.aspx. Change this to your required page by setting the DestinationPageUrl property of the ASP.NET login control used by the login page.

There's just one last change required before editing can begin. Because you are allowing HTML to be posted back to your site when you edit content through the control, ASP.NET will validate the request to ensure it does not contain any malicious cross site scripting elements. You will have to disable this feature for your page by setting the validateRequest attribute to false on your page directive as follows:

ASP.NET
<%@Page ValidateRequest="false" %>

Editing Website Content

Once EnableEditingForCurrentSession has been called, it is possible to edit content for the current client session. All instances of the control will be rendered as shown in Figure 2. This is the "Preview" mode.

Figure2.png

Figure 2 - Preview Mode

Here, the content ID, the original creation date, and the last modification date are shown above the content. The content is shown as it will be viewed by the end user. Clicking the "Edit" button switches the control to "Edit" mode, where the FreeTextBox control takes over, allowing you to modify the content in both HTML and Design modes, as shown in Figure 3.

Figure3.png

Figure 3 - Edit Mode

Clicking on "Save" will permanently update the content and revert to "Preview" mode where the new content can be previewed. It is no longer possible to revert back to the original content at this point. Clicking "Cancel" will revert back to "Preview" mode, leaving the original content unmodified. Clicking "Preview" will revert to "Preview" mode, allowing you to view the changes, but in this case, it will be possible to revert back to the original content should what you see not be to your liking. Also, end users do not yet see your changes.

Figure4.png

Figure 4 - Preview Mode with a Pending Change

Figure 4 shows the control in "Preview" mode where the content has not been permanently updated. This is signified by the red border. If you're not happy with the changes, clicking "Cancel" at this point will revert the content back to the original content. If you are happy with what you see, clicking "Save" permanently updates the content. In both cases, you are left in "Preview" mode. Clicking "Edit" allows further modifications to the already modified content. End users do not see your update until you click "Save" to permanently update the change.

When DisableEditingForCurrentSession is called, the control switches to "View" mode. In this case, the control renders exactly what is rendered in the "Preview" mode, except all editing features are removed. The page is rendered as the end user will see it.

Using Query String Parameters to Modify the Content ID

A really useful feature of the control is the ability to modify the content ID of any instance on a page by passing parameters in the query string of the page request. By doing this, it is possible for the same control instance to display different content for different page visits. A single query string can specify multiple remappings if you have more than one instance on a page. By creating hyperlinks in the actual content itself that contain such query strings, it's possible to implement a form of pagination, as demonstrated by the demo project.

Figure5.png

Figure 5 - The "Next" Hyperlink Alters the Content ID for the Control Instance

In figure 5, the "Next" hyperlink is defined with the following URL:

/Default.aspx?ids=ContentEditor1,Content%20A2

The default content ID for "ContentEditor1" is "Content A", as specified in the ASPX markup, so the content for this ID is what will be displayed if a query string is not supplied. By specifying "id=ContentEditor1,Content A2", when the page is loaded, the content ID of "Content A2" is assigned to the instance whose ID is "ContentEditor1", overriding the default value and causing the content for "Content A2" to be loaded. Figure 6 is what the user then sees.

Figure6.png

Figure 6 - The "Prev" Hyperlink Modifies the Content ID of the Control Instance Back to the Original Value

In figure 6, the "Previous" hyperlink is defined with the URL:

/Default.aspx?ids=ContentEditor1,Content%20A

This is setting the content ID, for instance, "ContentEditor1" back to the original value of "Content A". When the user clicks this link, they see what is shown by Figure 5. So, we now have some basic pagination which allows the user to move between "Content A" and "Content A2" within the same control instance.

The PreserveIdRemapping property of the control, when set to true, allows you to specify that the remapping received in the query string of a page request remains in effect for the duration of the user's session. By requesting the same page with no query string override, any previous remapping for a control instance remains in effect - the default content ID specified in the ASPX markup is not used. When set to false, if a page is requested and there is no override in the query string, the default in the markup is used regardless of any previous remapping. The purpose of this feature is to allow the control to display the last content viewed by a user if they return to a page from elsewhere in the site where a content remapping has not been defined in a URL. In particular, it is useful in a case where you have multiple content controls implementing pagination on a single page. By preserving the remapping, clicking on the "Next" hyperlink in one instance does not cause another instance to revert back to the original content when the page is returned.

Customization of the ContentEditor Control

Changing the Appearance

You may need to change the appearance of the control, for example, to change the colour or style of the preview border so it is visible within the website in which it is used. This is achieved by changing the styles in the stylesheet defined by the ContentEditor.StyleSheetUrl property specified in the configuration file.

Creating New Content Providers

The control is designed using the Strategy Pattern which means it is possible for you to plug in a different content provider should you require to store your data in a data source other than a SQL Sever or MS Access database. To do this, you need to create a class that implements the ContentEditor.IContentProvider interface and follow the contract described by the XML comments in the source file. Then, in the configuration file, simply change the ContentEditor.ContentDataProviderAssembly property to specify the name of the assembly containing the new type and the ContentEditor.ContentDataProviderType to specify the name of the new type.

Future Development

Multi User Access

Currently, it is not safe for more than one user to edit content concurrently without the danger of changes being overwritten by another user. So, a future enhancement would be to introduce some form of locking, allowing only one user to change content at a time.

Access Control

Different users could be assigned different roles. So, a user in an "editor" role can update content, but only a user in an "approver" role can approve the update for viewing by end users.

History

  • 1.0 - 19 January 2009 - Initial version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)