This is the first of a five-part series on implementing an event calendar in Community Server 2007. Our first step today will be to implement dynamic URLs, and the page stubs to go with them.
Your first instinct might be to dive right in to the SiteUrls.config file, and start adding content. While you can certainly do this, Community Server provides support another file for just such a purpose: SiteUrls_Override.config. The benefit of using this file lies in encapsulation and separation. If and when an upgrade comes along that modifies the SiteUrls.config file, you won't have to scramble to save your changes. You also won't have to dig through hundreds of default URL configurations to find your stuff.
Go ahead and create a file called SiteUrls_Override.config in your root Community Server directory. For our purpose, the contents look like this:
<?xml
version="1.0"
encoding="utf-8" ?>
<Overrides>
<Override
xpath="/SiteUrls/locations"
mode="add">
<location
name="events"
path="/events/"
themeDir="events">
<url
name="eventhome"
path=""
pattern="default.aspx"
physicalPath="##eventthemeDir##"
vanity="{2}"
page="eventlist.aspx" />
<url
name="eventapplication"
path="default.aspx"
pattern="default.aspx"
physicalPath="##eventthemeDir##"
vanity="{2}?App=${{app}}"
page="eventlist.aspx" />
<url
name="eventday"
path="archive/{1}/{2}/{3}.aspx"
pattern="archive/(\d{4})/(\d{1,2})/(\d{1,2})\.aspx"
physicalPath="##eventthemeDir##"
vanity="{2}?y=$1&m=$2&d=$3"
page="eventlist.aspx" />
<url
name="eventmonth"
path="archive/{1}/{2}.aspx"
pattern="archive/(\d{4})/(\d{1,2})\.aspx"
physicalPath="##eventthemeDir##"
vanity="{2}?y=$1&m=$2&d=1"
page="eventlist.aspx" />
<url
name="eventId"
path="archive/{1}/{2}/{3}/{4}.aspx"
pattern="archive/(\d{4})/(\d{1,2})/(\d{1,2})/(\d+)\.aspx"
physicalPath="##eventthemeDir##"
vanity="{2}?y=$1&m=$2&d=$3&EventID=$4"
page="event.aspx" />
<url
name="eventName"
path="archive/{1}/{2}/{3}/{4}.aspx"
pattern="archive/(\d{4})/(\d{1,2})/(\d{1,2})/([a-zA-Z0-9\-\._]*?)\.aspx"
physicalPath="##eventthemeDir##"
vanity="{2}?y=$1&m=$2&d=$3&EventName=$4"
page="event.aspx" />
<url
name="eventcategory"
path="archive/category/{1}.aspx"
pattern="archive/category/(\d+)\.aspx"
physicalPath="##eventthemeDir##"
vanity="{2}?CT=Event&CategoryID=$1"
page="eventlist.aspx" />
<url
name="eventalltags"
path="archive/tags/default.aspx"
pattern="archive/tags/default.aspx"
physicalPath="##eventthemeDir##"
vanity="{2}"
page="eventtaglist.aspx"/>
<url
name="eventtags"
path="archive/tags/{1}/default.aspx"
pattern="archive/tags/(.*?)/default.aspx"
physicalPath="##eventthemeDir##"
vanity="{2}?Tags=$1"
page="eventlist.aspx"/>
</location>
</Override>
<Override
xpath="/SiteUrls/transformers"
mode="add"
where="after">
<add
key = "##eventthemeDir##"
value = "/themes/{0}/{1}/" />
<add
key = "##eventdirectory##"
value = "{0}/" />
</Override>
<Override
xpath="/SiteUrls/navigation"
mode="update">
<navigation>
<link
name="home"
resourceUrl="home"
resourceName="home"
roles="Everyone" />
<link
name="blog"
resourceUrl="webloghome"
resourceName="weblogs"
roles="Everyone"
applicationType = "Weblog" />
<link
name="events"
navigateUrl="/events/"
resourceName="events"
roles="Everyone" />
<link
name="forums"
resourceUrl="forumshome"
resourceName="forums"
roles="Everyone"
applicationType = "Forum" />
<link
name="gallery"
resourceUrl="galleryhome"
resourceName="photos"
roles="Everyone"
applicationType = "Gallery" />
<link
name="files"
resourceUrl="fileshome"
resourceName="files"
roles="Everyone"
applicationType = "FileGallery" />
<link
name="controlpanel"
resourceUrl="controlpanel"
resourceName="controlpanel"
roles="SystemAdministrator,BlogAdministrator,ForumsAdministrator,Moderator,GalleryAdministrator,FileAdministrator,ReaderAdministrator,MembershipAdministrator" />
</navigation>
</Override>
</Overrides>
Don't worry; it's not really as bad as it looks. Inside of the Overrides root tag are two Override tags. The Override tag tells Community Server which section of the SiteUrls.config you are overriding. The override tag has two main attributes; xpath and mode. The xpath attribute defines which section of the SiteUrls.config file you are overriding. The mode specifies how you are overriding that section, and has three options: add, update, and change. For the add value, you can specify an additional attribute: where.
<Override xpath="" mode="[add|update|change]" where="[start|end]">
</Override>
The URL has a number of attributes that need to be specified.
One exception to the above attributes is that in this case I am using ##eventthemeDir## because we are using a custom theme directory. This takes place in the transformers override.
In the first group, I am adding a new location tag, and adding URLs to that location. URLs include tags, categories, and separation by date, just like blog posts. In the second group I am rebuilding (updating) the navigation bar that lives right below the header. Though it seems like duplication, you need to use mode="update", and re-include each item that you want in the navigation in order to be able to place your new item where you want.
And voila, you now have a new menu item in your menu bar.
But don't get too excited, we're not done yet. If you were to attempt to navigate to your /events/ folder, the request would most likely fail. This is because when IIS receives the request for the folder, it sees that the folder doesn't exist and throws a 404 error, rather than passing it on to the ASP.NET runtime. In order to fix that situation, we need to create the /events/ folder, and add an empty Default.aspx file to it. Well, not quite empty, you need to add an empty Page declaration. I added a comment line as well for maintainability.
<%@
Page
%>
<%-- Placeholder for URL rewriting--%>
Yup, that's it. The reason for this is to make sure any requests for this directory get passed to the ASP.NET runtime (aspnet_wp.dll).
So we're almost there, but there is still one more thing to do. In order to accommodate our new event location URLs, we need to create the event theme directory and the page stubs. For now, create a directory named Events in your Themes/[theme] directory. Next, create three normal ASPX files called eventlist.aspx, eventtaglist.aspx, and event.aspx. What I did was to add a little content to the page to identify each one, and write out the querystring value.
event content here
<p>
<%= Server.UrlDecode(Request.Url.Query) %>
</p>
Now you can go ahead and test out your URL rewriting, and check the results on the resulting pages.
Here are some URLs to try:
- /events/archive/category/mycategory.aspx
- /events/archive/2007/06/01.aspx
- /events/archive/2007/06.aspx
- /events/archive/tags/default.aspx
- /events/archive/tags/mytag/default.aspx
Stay tuned for Part 2 of this series, where we will explore creating a Community Server data and application provider for our calendar event system; the business and data layers of our event calendar.