Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Real - World ASP .NET—Building a Content Management System - StephenR. G. Fraser

.pdf
Скачиваний:
68
Добавлен:
24.05.2014
Размер:
4.59 Mб
Скачать

Content content = new Content(appEnv.GetConnection());

AccountProperty property = new AccountProperty(appEnv.GetConnection());

DataRow dr = content.GetContentForIDVer(curId, curVer);

if (dr != null)

{

lbHeadline.Text = dr["Headline"].ToString();

lbSource.Text = dr["Source"].ToString();

lbByline.Text = property.GetValue(Convert.ToInt32(dr["Byline"]),

"UserName").Trim();

lbDate.Text = dr["ModifiedDate"].ToString();

lbTeaser.Text = dr["Teaser"].ToString();

lbBody.Text = dr["Body"].ToString();

lbTagline.Text = dr["Tagline"].ToString();

}

else

{

lbHeadline.Text = "No Stories";

lbBy.Visible = false;

lbDashes.Visible = false;

}

}

In a case in which the content is not found in the database, a "No Stories" message is displayed instead. This should actually never happen, but it is possible that an inquisitive user might try to search for stories by entering content IDs and versions manually in the Address edit field of the browser.

Deploying Content

All the code in this chapter is quite useless if you can't load it with the content from the repository. Content that is in the process of being created should not be accessible for viewing on the Web site. Only after it is completed and approved should content be available. It is ultimately the job of the deployment process to make content available to users of the Web site. Deploying content is the last step of CMS.NET's workflow. Because workflow is the topic of the next chapter, I am going to delay covering this until then. For those of you who want to add content and see it displayed, however, a simplified version of the source code for deploying content (see Figure 13-15) is included on the Apress Web site (www.apress.com) in the Downloads section. Using this is easy. Submit the content from the content development area and then deploy it from the site maintenance area. It is also possible to see all the stories deployed to all zones, or to a particular zone, and shift the viewing order of the stories.

Figure 13-15: The Deploy Web page

Summary

This chapter covered the displaying of dynamic content.

It started by covering the basics of what dynamic content is and how it uses a three-level approach to dynamic content. Next, it took a little side trip and covered stopping and starting CMS.NET so that the user never gets the ugly "The page cannot be found" error. It then got back on topic and described the new database tables needed to handle threelevel navigation. Next, it covered User Controls and you created a few. Finally, you implemented the default dynamic Web pages using these User Controls.

The next chapter returns to the content management application (CMA), which you started building in Chapter 11, and adds a simple workflow.

Chapter 14: Using a Workflow to Enter Content

Overview

Workflow is one of the most important features of a content management system (CMS), so much so that Chapter 3 was devoted entirely to covering the theory behind it. In this chapter, on the other hand, you get to have some fun and actually develop the workflow for CMS.NET.

CMS.NET's workflow isn't the most elaborate, but it does have all the pieces needed to

develop a content management application (CMA) that supports the following: • Multiple users

§Internet maintainability

§Multiversion content

§Interstate communication

§State change e-mail events

§Role-based content development

§Role-based security

§Repeatable process

It supports a few other features that I'm sure I missed, but I'd say this isn't too bad for one chapter's worth of work.

CMS.NET Content Workflow

Most of the more expensive CMSs on the market support a fully dynamic workflow generator. These systems enable the Web system developer to generate a workflow however she wants. I suppose that having this capability could merit a little higher price tag than, say, the hard-coded workflow supported by CMS.NET. Not the few hundred thousand dollars difference but maybe a few thousand dollars at least. On the other hand, these systems don't provide full source code so that you can change the workflow to suit your exact needs.

Figure 14-1 shows CMS.NET's content development workflow. It starts with the author creating the content. When the author is happy with the content, he passes it to an editor who edits it. When the editor is happy, it is passed to an approver, who gives the final rubber stamp and passes it on to the deployer for deployment.

Figure 14-1: The content development workflow

Each piece of content can maintain a running commentary or audit using dated notes attached to it. This facility also can be used to handle all communication between the roles when the content moves from state to state. Keeping the notes separate from the content means no cleanup of the document is needed at the end to remove all unwanted commentary.

When a piece of content migrates from one state to another, CMS.NET will automatically send e-mail notification of the content's availability to all persons that fill the next role in the workflow. As soon as a specific person is designated to that role, only she will get the e-mail notifications. This helps people manage their time better because they no longer have to continually monitor the CMS for new content. Instead, they will be alerted by a simple e-mail.

Content is available on a first-come first-served basis for each role. In other words, the first user to start processing the content when it becomes available is given complete control of it until he relinquishes it to the next role in the workflow.

Unlike many content workflows, nothing enforces an author review, but the editor can handle this procedurally by returning the content to the author before she forwards it for

approval. Forcing this review into the workflow would only require a few minor changes to the code, which I will leave to the reader as an exercise.

It is assumed that testing in this workflow is done throughout the process. Adding an additional role to handle testing should not be difficult. As you will see, much of the functionality in each role is repeated. This will also be the case for the tester role.

CMS.NET Roles

CMS.NET only uses four roles to handle content development:

§Author

§Editor

§Approver

§Deployer

Author

The author's role is to create the original content that the Web site will provide. Unlike the more expensive CMSs on the market, authors for CMS.NET have to be HTML knowledgeable so that they can format their content. For example, paragraphs require

the <P> tag, images use the <img> tag, and boldface uses the <B> tag. In fact, all HTML formatting tags are supported.

All text entered into the edit boxes ignores spaces and new lines, so any manual formatting that the author does (that isn't done using HTML) is ignored when it finally displays on the Web site.

It is true that a good CMS enables an author to not worry about HTML when creating content. To keep the program simple, I overlooked this fact, but nothing is stopping you from augmenting the editor. An easier solution (and the one that I use) if you need any elaborate formatting is to use FrontPage or an equivalent tool and just cut and paste the

HTML generated within the <body></body> tags into the edit boxes.

Figure 14-2 shows a little of what is available to an author in the way of HTML formatting. By the way, I created this Web page first using FrontPage to save time.

Figure 14-2: The Elaborate Web page

As you can see in Listing 14-1, which shows the actual HTML used to create the Elaborate Web page, the code contains bullets, a table, two images, and a numbered

list. You might have noted the <BR Clear=" all"> tag at the end. This little nifty tag makes sure that all subsequent HTML is placed after this visually on the Web page. If

you leave it off, sometimes you might find that the tagline is embedded in the middle of your body.

Listing 14-1: The Elaborate Web Page's HTML

<p>This is an elaborate test page with:</p>

<ul>

<li>Bullets</li>

<li>Bullets</li>

</ul>

<table border="1" width="60%" cellpadding="6" >

<tr>

<td width="75%" bgcolor="#CCFFFF">A table with one</td>

<td width="25%" bgcolor="#FFCCFF">two</td>

</tr>

<tr>

<td width="75%" bgcolor="#FFCC99" > three with a picture

<img border="0" align=" right"

src=" http://localhost/CMSNET/Images/steph.gif"

width="180" height="180" >

</td>

<td width="25%" bgcolor="#99FFCC" >four cells</td>

</tr> </table>

<ol>

<li>A numbered</li>

<li>list</li>

<li>of stuff</li>

</ol>

<p>And some more text to end it off</p>

<BR clear=" all">

Editor

The editor does have a more specific role in most content management systems, but in CMS.NET it is simply a second person to look over the piece of content with the authority to update as she sees fit.

Again, to keep things simple, I merged many roles into the editor role. In CMS.NET, the editor fills all the roles normally broken up into editor, copy editor, proofreader, compositor, and so on. Nothing is stopping you from adding these roles, and I'm sure you will find that much of the code is already provided.

If you have authors who are not HTML savvy, the editor's role could be used to add HTML formatting to the author's content.

As you can see, having a dynamic way of creating a workflow can come in handy. Here's a note to managers reading this: It took me only one week to write this entire workflow. If your software developers are saying it will take months to update it, they are yanking your chain, or you need better developers.

Approver

This role has the last say before the content is deployed in the Web site. CMS.NET only needs one person to approve the content, but it will not take much effort to change it to require more than one.

This role does not have the ability to make any changes to the content. He approves it, sends it back to the editor for more revisions, or withdraws it altogether. As I said in Chapter 3, this workflow has a chance of being wasted effort if the approver withdraws the content at this point. Hopefully, the editor and approver have already had some communication about the content before it gets to this point.

Deployer

This role simply takes the content and places it into the Web site repository. At this point, all the deployer does is place the content into its default content zone(s). If you were to add personalization to the Web site, this role would most likely expand.

The deployer also, frequently, takes content off the main Web site and places it into an archive. Since CMS.NET does not support archiving, the archive process just sends the content back to the editor for more revisions. (I did this so that I could test content workflow without having to keep creating new content.)

Interrole Communication

Let's get back to some coding. CMS.NET uses two methods to handle communication between roles in the workflow: notes and e-mails. CMS.NET uses notes as a means to provide a running commentary on the content and its development. E-mails, on the other hand, are used as an instant notifier of content availability.

Content Notes

Notes are simply time-stamped messages attached to a piece of content. They contain almost any kind of information. They are free format and, unlike content formatting that is manually typed in, will remain. HTML tags do not work.

The ContentNotes Database Table

This is the only new database table in this chapter. It is designed to hold content notes for a specific Content ID. The design of the database table, as shown in Table 14-1, is purposely simple in nature. It enables almost any type of textual information to be stored as a comment to the content.

Table 14-1: The ContentNotes Database Table Design

COLUMN NAME

 

DATA

 

LENGTH

 

KEY

 

DESCRIPTION

 

 

TYPE

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

NoteID

 

int

 

4

 

true

 

Note identifier

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ContentID

 

int

 

4

 

false

 

ContentID for

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

which this

 

 

 

 

 

 

 

 

content

 

 

 

 

 

 

 

 

addresses

 

 

 

 

 

 

 

 

 

Note

 

text

 

16

 

false

 

The note text

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Author

 

int

 

4

 

false

 

Author of the

 

 

 

 

 

 

 

 

Table 14-1: The ContentNotes Database Table Design

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

COLUMN NAME

 

DATA

 

LENGTH

 

KEY

 

DESCRIPTION

 

 

 

 

TYPE

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

note

 

 

 

 

 

 

 

 

 

 

 

 

 

ModifiedDate

 

datetime

 

8

 

false

 

Date domain

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

was last

 

 

 

 

 

 

 

 

 

 

changed

 

 

 

 

 

 

 

 

 

 

 

 

 

CreationDate

 

datetime

 

8

 

false

 

Date domain

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

was created

 

 

 

 

 

 

 

 

 

 

 

 

Notes Implementation

The implementation of content notes simply involves the standard CURVe processes. For those of you who don't remember, the CURVe processes are creating, updating, removing, and viewing. As you can see in Figure 14-3, the design of the notes process closely resembles that of the author's content development process covered in Chapter 11.

Figure 14-3: The NotesList Web page

No new coding is used to develop the notes process. It is really just a simplified cut and paste of the author's CURVe process. Because there is nothing new, none of the code will be displayed, but like all the source code, it can be found on the Apress Web site (www.apress.com) in the Downloads section.

The thing to remember about the notes process is that there is only one copy of the source. All the roles will use the exact same code to handle the maintenance of notes, unlike much of the rest of the common functionality shared by the roles, which have their own copy.

E-mail

CMS.NET automatically sends an e-mail whenever the content is sent to another role for processing. If the person fulfilling the role has already been determined, that person will be the only one receiving the e-mail. Otherwise, when the role changes, all persons in the next role in the process will be notified.

Creating e-mails is extremely easy using .NET. In fact, it can take as few as six lines of code. The first five build the e-mail message, and the final one sends the e-mail on its way.

MailMessage mail = new MailMessage();

mail.To

= "target_email@address.com";

mail.From = "your_email@address.com";

mail.Subject = "Subject of the email";

mail.Body = "Main body of the email";

SmtpMail.Send(mail);

The implementation of the e-mail process for CMS.NET is localized in the EmailAlert class (see Listing 14-2). Most of the class is simply little utility functions to help populate the e-mail message without the help of the Web page developer.

Listing 14-2: The EmailAlert Class

public class EmailAlert

{

private int m_code; private int m_towho;

private string m_body = ""; private HttpContext m_context;

public int Code

{

get { return m_code; } set { m_code = value; }

}

public int ToWho

{

get { return m_towho; } set { m_towho = value; }

}

public string Body

{

get { return m_body; } set { m_body = value; }

}

public EmailAlert(HttpContext context, int code, int towho)

{

m_context = context;

m_code = code;

m_towho = towho;

}

public void Send()

{

AppEnv appenv = new AppEnv(m_context);

string SMTPServer = appenv.GetAppSetting("smtpserver").Trim();

if (SMTPServer.Length <= 0)

return; // do not use email notifications

SmtpMail.SmtpServer = SMTPServer;

Account account = new Account(appenv.GetConnection());

MailMessage mail = new MailMessage();

DataRow dr = account.GetAccountForID(1); // Admin account mail.From = dr["Email"].ToString().Trim();

mail.Subject = generateSubject(); mail.Body = m_body; mail.BodyFormat = MailFormat.Text;

if (m_towho != 0)

{

dr = account.GetAccountForID(m_towho); mail.To = dr["Email"].ToString().Trim(); SmtpMail.Send(mail);

}

else

{

AccountRoles roles =

new AccountRoles(new AppEnv(m_context).GetConnection()); DataTable dt = roles.GetAllRole(getRoleForCode());

foreach (DataRow drr in dt.Rows)

{

dr =

account.GetAccountForID(Convert.ToInt32(drr["AccountID"])); mail.To = dr["Email"].ToString().Trim();

SmtpMail.Send(mail);

}

}

}

private string getRoleForCode()

{

switch (m_code)

{

case StatusCodes.RequiresUpdate: return "Author";

case StatusCodes.AwaitingEdit: case StatusCodes.Editing:

case StatusCodes.RequiresEditing: return "Editor";

case StatusCodes.AwaitingApproval: return "Approver";

case StatusCodes.Approved: return "Deployer";

default: return "";

}

}

private string generateSubject()

{

switch (m_code)

{

case StatusCodes.AwaitingEdit:

return "New content available for editing";

case StatusCodes.Editing:

return "Updated content available for editing";

case StatusCodes.AwaitingApproval: return "Content available for approval";

case StatusCodes.RequiresUpdate: return "Content requires updating";

case StatusCodes.RequiresEditing: return "Content requires editing";

case StatusCodes.Approved:

return "Content available for deployment";

case StatusCodes.Discontinued:

return "Content has been discontinued";

default: return "";

}

}

}

Соседние файлы в предмете Программирование