• No se han encontrado resultados

3.8 Trabajos relacionados

3.8.3 Patrones lingüísticos

The final class located in the special App_Code folder is the AppConfigurationclass. This class belongs more to the web site than to the business or data access layer, so it has been put in the App_Code folder

directly. This isn’t a requirement, so you could move it to one of the existing folders, or create an entirely new folder such as Configuration or Helpers and place it there. The class is called AppConfiguration and not Configuration, for example, to avoid a naming conflict with the existing ASP.NET System .Configurationnamespace. The AppConfigurationclass exposes a single shared property called ConnectionString, which is essentially a wrapper around the ConnectionStringheld in the Web .config file. The pages in the site that use SqlDataSourcecontrols use their own binding syntax to get their ConnectionStringproperty from the Web.config directly. However, the two methods in the data access layer use the AppConfigurationclass to retrieve information about the connection. Instead of writing code that directly accesses the Web.config file, these methods can now access this property. You see this property in use in the next section when the code in the business, data access, and presentation layers is discussed.

Code and Code Explanation

This section walks you through each of the important pages in the Wrox CMS web site. It starts off by looking at a few files located in the root of the site that are used by the other pages. Then you see in great detail the files in the Management folder that allow you to manage the content in the database.

Finally, this section closes with an examination of the two files that are responsible for displaying the content in the public section of the site.

Root Files

The root of the CMS web site contains two master files, a config file, a login page, the default page, and two files that are used to display the content in the database. This section discusses all of these files, except for the last two, which are dealt with after the Management folder has been discussed.

Web.config

This global configuration file contains one appSettingkey and one connectionString. The appSettingkey is used by the FCKeditor, the inline HTML editor discussed later. The connection string is used by the various pages and data access classes in the application.

Under the <system.web>node, you’ll find two configuration sections that configure the Membershipand Roleproviders. The CMS uses these providers to enable users of the CMS to log in to access the protected Management folder and its contents. Because the site uses a custom database, and not the default aspnetdb.mdf as defined in the machine.config that applies to the entire server, you need to configure the application to use the custom database instead. Both the <membership>and the <roleManager>nodes are very similar to the ones you find in machine.config. In fact, the only changes made to the settings copied from the global machine.config are the nameand connectionStringNameattributes of the <providers>node that instructs ASP.NET to use the custom connection string and database instead:

<providers> <add name=”SqlProvider” type=”System.Web.Security.SqlRoleProvider” connectionStringName=”Cms” /> </providers>

Right under the provider settings, you’ll find these settings: <authentication mode=”Forms”> <forms loginUrl=”~/Login.aspx” /> </authentication> <authorization> <allow users=”*”/> </authorization> <pages theme=”Cms”>

The first element, <authentication>, tells .NET to use Forms Authentication. Whenever you’re trying to request a protected page as an anonymous user, you’re taken to the Login.aspx page located in the root of the site that allows you to log on. The second node, <authorization>, allows access to all pages in the site to all users. The Management folder is blocked for users that are not in the Administrator role with a <location>tag that you see next.

The <pages>node tells ASP.NET to use the theme defined in the App_Themes folder. The site features a very simple theme, with a single .skin file that defines the looks of GridViewcontrols used in the site. The GridView.skin file contains a few style definitions with CssClassattributes that point to classes defined in the Styles.css file in the CSS folder.

The final section in the Web.config file you need to look at is the <location>tag at the bottom of the file: <location path=”Management”> <system.web> <authorization> <allow roles=”Administrator” /> <deny users=”*”/> </authorization> </system.web> </location>

This code instructs ASP.NET to block access to all users that are not in the Administrator role. When you try to access one of those pages in that folder, you’re taken to Login.aspx instead.

The remainder of the elements in the Web.config file is placed there by Visual Web Developer when you create a new ASP.NET 2.0 web site.

SiteMaster.master and AdminMaster.master

These two master files determine the look and feel of all the pages in the site. The SiteMaster.master file is used for the public pages in the site, whereas AdminMaster.master defines the look for the pages in the Management folder. The two files have a lot in common; the only difference is that inside the AdminMaster.master file there is a new HTML table and a user control that displays the sub-menu for the Management section. Although ASP.NET 2.0 allows you to use nested master files, the CMS web site doesn’t use that feature. With a nested template, you lose design-time capabilities in Visual Web Developer, which can be a real productivity killer because you’ll need to hand-code the pages yourself. So, instead SiteMaster.master was created first and then its contents were copied to the AdminMaster.master file.

In addition to some regular HTML tags, the SiteMaster.master contains a user control called SiteMenu that displays the main and sub-menus. The SiteMenucontrol that you find in the Controls folder con- tains two Repeatercontrols for the two menus. Each menu item in the main and sub-menus links to the ContentList page and passes it the ID of the selected content type and, if present, of the category through the query string. This allows that page, and any user controls in it, to see which content type and cate- gory is currently being displayed. The SiteMenucontrol also contains two SqlDataSourcecontrols that get their data from stored procedures in the database. Take a look at the data source for the sub-menu that displays the categories to see how this works:

<asp:SqlDataSource ID=”sdsSubMenu” runat=”server” ConnectionString=”<%$ ConnectionStrings:Cms %>”

ProviderName=”System.Data.SqlClient” SelectCommand=”sprocCategorySelectlist” SelectCommandType=”StoredProcedure”

>

... Select Parameter is shown later </asp:SqlDataSource>

The markup for this control contains a few important bits of information. First of all, there is the ConnectionStringattribute. To assign the proper connection string at run time, a new form of data binding is used. The new <%$ %>expression syntax is used to bind attributes to connection strings, resources, and application settings in the Web.config file. In this case, a connection string with the name Cmsis retrieved from the application’s configuration file.

The next important pieces are the SelectCommandand SelectCommandTypeattributes. These tell the .NET Framework to run the stored procedure called sprocCategorySelectlistin the database defined by the connection string.

The stored procedure is pretty straightforward: it requests all the categories that belong to a certain con- tent type:

CREATE PROCEDURE sprocCategorySelectlist

@contentTypeId int AS SELECT Category.Id, Category.Description, Category.ContentTypeId, ContentType.Description AS ContentTypeDescription, Category.SortOrder FROM

Category INNER JOIN

ContentType ON Category.ContentTypeId = ContentType.Id WHERE (Category.ContentTypeId = @contentTypeId) AND Category.Visible = 1 ORDER BY SortOrder RETURN

In addition to the fields of the Category table, the description of the content type is retrieved as well, aliased as ContentTypeDescription. This description is used in the Management section of the site, to show the name of the content type that the category belongs to. The stored procedure expects the ID of the content type as a parameter. In the code for the SqlDataSourcethat parameter is set up as follows:

<SelectParameters>

<asp:QueryStringParameter Name=”contentTypeId” QueryStringField=”ContentTypeId” Type=”Int32” /> </SelectParameters>

With this code, a single Parameterobject is defined that gets its value from a QueryStringFieldcalled ContentTypeId. When the SqlDataSourceis about to retrieve the data from the database, it gets the value from the query string and then stores it in this parameter so it gets passed to the stored procedure. By using the query string as a parameter, the SqlDataSourcecontrol will always retrieve the categories that belong to the currently requested content type.

The other data source control, which gets the items for the main menu, works the same way. However, because this control always needs to return all content types, it does not have any select parameters. When you view a page that is using the SiteMenucontrol, you’ll see something like Figure 5-8.

Figure 5-8

All the menu items between Home and Admin come from the ContentType table, whereas the sub- menus come from the Categories table. You can also see that in the link for the sub-menu both the ContentTypeIdand the CategoryIdare passed to the ContentList page. The final thing you should notice in Figure 5-8 is that one main menu and one sub-menu (Articles and Visual Web Developer) appear as selected by using a different color or font type. This is done by some code in the Loadevent in the code-behind file of the user control.

When the two Repeatercontrols for the menus get their data from the SqlDataSourcecontrols they fire their ItemDataBoundevent for each item added to the repeater. This event is a great place to prese- lect the menu items because you have access to both the query string holding the ID of the chosen con- tent type and category and to the item that is about to be displayed. The following code shows how a sub-menu gets a bold typeface when it is selected:

Protected Sub repSubMenu_ItemDataBound(ByVal sender As Object, _ ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) _ Handles repSubMenu.ItemDataBound

If e.Item.ItemType = ListItemType.Item Or _

e.Item.ItemType = ListItemType.AlternatingItem Then

Dim myDataRowView As DataRowView = DirectCast(e.Item.DataItem, DataRowView)

If Convert.ToInt32(myDataRowView(“Id”)) = _

Convert.ToInt32(Request.QueryString.Get(“CategoryId”)) Then Dim lnkSubmenu As HyperLink = _

DirectCast(e.Item.FindControl(“lnkSubmenu”), HyperLink) lnkSubmenu.CssClass = “Selected”

End If End If End Sub

This code examines the ItemTypeof the item that is currently being data-bound. When an Itemor Alternatingitem is created, the code retrieves the item’s DataItem, which in this case holds a DataRowView. Then DirectCastis used to cast the generic DataItemobject to a DataRowView. Using DirectCastis very similar to CTypebut it performs a bit faster. The downside of DirectCastis that it can only cast objects of exactly the same type. You can’t use it to cast an object to another type higher or deeper in the inheritance hierarchy. In this case, however, that is no problem because the DataItemis a DataRowViewso you can safely use DirectCast.

Once you have the DataRowViewobject, you can retrieve its ID column that holds the ID for the cate- gory you’re adding to the Repeater. If the ID of that category matches the ID of the category you’re cur- rently displaying (determined by looking at the CategoryIdquery string), the code gets a reference to the hyperlink in the menu called lnkSubmenu, again using DirectCast. And finally, the hyperlink’s CssClassis set to Selected. The behavior for the Selectedclass (a bold font in this case) is defined in the Core.css file:

#SubMenu a.Selected {

font-weight: bold; }

This code applies a bold font to all <a>tags that fall within the #SubMenudiv tag and that have a Selectedclass applied which happens to be the selected sub-menu item.

The menu items Home, Admin, and Login are not database-driven, so you cannot preselect them in an ItemDataBoundevent. Instead, in Page_Loadof the SiteMenucontrol you examine the

AppRelativeCurrentExecutionFilePathproperty of the HttpRequestclass. By using string com- paring you can see if you need to preselect one of the static menu items:

If Request.AppRelativeCurrentExecutionFilePath.ToLower() = “~/default.aspx” Then liHome.Attributes(“class”) = “Selected”

End If

This code applies the class Selectedto the static Home menu item when the currently requested page is ~/default.aspx, which is the homepage for the CMS web site. The same principle is applied to prese- lect the other two menu items.

Login.aspx

This page allows you to log in to the site and is shown automatically whenever you try to access one of the pages in the Management folder as an unauthenticated user. The page takes full advantage of the ASP.NET 2.0 security framework offered by the Membership and Role providers. All that this page requires is one simple <asp:Login>control like this:

<asp:Login ID=”Login1” runat=”server” />

Although the control doesn’t look too good with only this markup, it is still fully functional. The pur- poses of this CMS don’t require any visual customization, but if you want you can apply a host of behavior and appearance changes to the control through the Visual Web Developer IDE.

The final two pages located in the root, ContentList.aspx and ContentDetail.aspx, are discussed after the Management folder that’s coming up next.