| Introduction | |
| The Sample Application | |
| How It Works and How You Can Set It Up | |
| Security Requirements | |
| The ASP Search Page | |
| Conclusion |
The amount of information generated today is exploding, especially within businesses. With the growth of the Internet and the ubiquitous connectivity it provides for businesses, information overload can quickly become a problem for many corporate users. Users can sign up for a variety of information sources such as Internet newsgroups, list servers, or Web page updates. Your corporation may even have internal discussion aliases. Although the availability of information and knowledge sharing helps users make better decisions, it also forces users to spend more time sifting through information to find the relevant bits and pieces they need for their job. What corporations need is a way to index and search across all of these different data sources, making it easier and less time-consuming for users to find relevant information.
Say hello to Microsoft® Site Server 3.0 and Microsoft Exchange Server 5.5. While Site Server provides the necessary features for full-text indexing, and search and knowledge delivery; Exchange Server provides the collaborative infrastructure and functionality that makes creating Internet newsgroups, threaded discussions, customer contact databases, and custom collaborative applications easy. Combine these two products and you have a knowledge management solution that can make your search page the most popular page on your intranet.
This article explains how you can extend the Knowledge Management features of Site Server 3.0 with Microsoft Exchange Server and Microsoft Outlook™ to build high-powered Web-based Knowledge Management solutions. You will learn how to use the built-in full-text indexing of Exchange Public Folders in Site Server, and how to extend the search capabilities of Site Server with custom ASP code that enables you to build customized search pages. These search pages allow your users to find information stored throughout the Exchange system whether the information is a NNTP news item, a posted item in a Public Folder or an email discussion archived in a Public Folder.
This article assumes that you have a working knowledge of Site Server Search. For information on Site Server Search, see Creating a Search Catalog for Your Site. For more how-to information on Site Server, see the SBN/MSDN feature articles.
To start off, I'll show you just one of the possibilities: here's a sample search site that shows you how you can customize the search capabilities provided by Microsoft Site Server when indexing Exchange Public Folders. Figure 1 shows the default page of the application. You can search on who posted the item or when it was posted, and also by custom properties such as the issue type of an item (which can be problem, resolution, or best practice).
When a user clicks the Search button, the page queries the corresponding catalog of information and returns the results to the browser as shown in Figure 2.
Note the HTML page icon next to the hyperlink for the item. The hyperlink on the item will launch Microsoft Outlook on the user's machine so the user can read the item. If the user does not have Microsoft Outlook, Microsoft Outlook Web Access will be launched to display the item. Figure 3 shows Outlook 98 reading the item and Figure 4 shows Outlook Web Access reading the same item.
Please note that the custom Outlook Form was converted to an HTML form by using the new Microsoft Outlook HTML Form Converter. For more information on the form converter, please visit http://www.microsoft.com/exchange/.
The sample application uses a custom Outlook form in an Exchange Public Folder to prompt the user for the item's issue type as they post it. However, there are other ways you can use Public Folders to store information without creating custom Outlook forms. One way is to make Public Folders part of discussion distribution lists. With this method, the Public Folder serves as an archive of the information that is sent to the distribution list. Having this archive lets users search this information and avoid posting a question to the distribution list that may already be answered.
Another way to use Public Folders to gather and distribute information is to set one up as an incoming and outgoing Internet news server. Public Folders support replicating Internet newsgroup information into the folder. You can store this information in a central location rather than having individual users connecting to Internet newsgroups from their own machines. The other benefit is that users can then use Outlook to change the views of the content as well as add new content. This new content can be replicated to the Internet by Exchange Server.
Before you can even start using Site Server with Exchange, you need to create a Public Folder that will contain the items you want your users to share. You can create custom Outlook forms, Web applications, or just use the built-in capabilities of Outlook to add information into this Public Folder. To help you get started with custom forms, there is a custom Outlook form and the Outlook form converted to a Web form in the sample application. To learn how to set up these forms in Outlook and Outlook Web Access, please read the setup guide included with the downloadable sample. The sample application contains three custom fields on the Outlook and Web form: Type, Industry, and Product. When we create the search catalog, Site Server will automatically index these custom properties so that users can search on these properties. You do not have to add custom Exchange and Outlook properties to the Site Server schema to search on the properties. As you will see in the sample code, all you need to do is use the @META_customname syntax in your search page to search on Exchange custom properties.
Now we can set up Site Server to leverage the knowledge you store in Exchange. The first step is to create a search catalog, which is the index and property store that Site Server creates and your users can search. In the same catalog, you can create an index of Exchange Public Folders, and also open database connectivity (ODBC) databases, Web pages, Microsoft Office documents, and items from the file system. When indexing Public Folders, Site Server also indexes any documents in the Public Folder (such as Office documents) and enables you to search for text or properties contained in those Office documents.
To set up Site Server to create this index, you must first run the Create New Catalog Definition Wizard in the Microsoft Management Console (MMC) administrator for Site Server.
1. | In the MMC, right-click your Catalog Build Server as shown in Figure 5 and select New Catalog Definition with Wizard. |
2. | In the wizard, type in a catalog name and then select the Exchange crawl option. The wizard will present a start address that looks like: exch://yourservername/Public Folders/All Public Folders/. |
3. | After the last /, type the path to the Public Folder you want to have Site Server index. For example, if you had a Public Folder in your Public Folder hierarchy named Helpdesk under the IT Applications folder, the Site Server start address would be exch://yourservername/Public Folders/All Public Folders/IT Applications/Helpdesk. You can also enable Site Server to crawl all the subfolders under your start address automatically. This is very useful if you use many child folders in your organization. The best example of this is if you use Exchange for NNTP newsgroups. |
4. | The next step is to tell Site Server where to propagate the final catalog to after it completes indexing the items. |
5. | Finally, click the Build Now check box and select Finish in the wizard. That's it. You are now indexing all the items in the folder. You can rerun this wizard to add either other Public Folders to the catalog or other types of data sources. |
You can schedule Site Server to update the index you create by doing either a full or incremental build of the contents. Because we will be adding new contents to the Public Folder after creating the Search Catalog, I recommend that you manually force Site Server to rebuild the catalog during the development process. This guarantees that you will have the most recent information from the folder in the catalog.
1. | You can find the manual rebuild command by right-clicking the name of your catalog under the Catalog Build Server section of the MMC window. |
2. | Select properties, and go to the Status tab. |
3. | Click the right-pointing arrow next to the State label and select Start Incremental Build. |
When setting up your virtual directory to allow searches against Exchange information, you must authenticate the user before Site Server will return information to the browser. This authentication is necessary so that information a particular user should not see is not returned by the search. Because of this authentication requirement, you should disable anonymous access to the virtual directory where you place your search pages and require Basic or Windows NT Challenge/Response authentication, or you should add code to your search page to authenticate the user directly in Visual Basic® Scripting Edition (VBScript) or JavaScript code.
The crux of the application -- beyond the custom forms and the Site Server full-text catalog -- is the custom ASP search page on which users can search for items that meet specific criteria. What you will see in the search page is searching across one Public Folder; however, Site Server supports crawling multiple Public Folders as well as other data sources such as ODBC databases, file folders, Microsoft Office documents, and HTML pages -- all in a single catalog.
Let's take a look at each section of code in search.asp, to see how to create a custom search page using custom Exchange properties with Site Server catalogs.
The first section of search.asp processes the input from the user. Because the application divides the search results into 10 hits at a time, it uses Session variables in ASP to remember the criteria the user entered for their search across the multiple pages. If you customize this application to search on additional properties, be sure to modify this section so that when the user clicks to see more search results, their search criteria is not lost at the top of the HTML page.
<% ' Process Input Section. %>
<% if Request.QueryString <> "" then %>
<% ' Initialize or set non-predefined variables from information posted to page.
' Purpose of DisplayText variable is to have just the words from the query for
' display in the introductory sentence and in the more results link.
if Request("DisplayText")= "" then
DisplayText= Request("q1")
else
DisplayText = Request("DisplayText")
end if
' Purpose of RecordNum variable is to display which records
' are displayed on each results page.
if Request("RecordNum") = "" then
RecordNum=1
else
RecordNum=Request("RecordNum")
end if
' Purpose of session variables is to store information for use in
' editing a search. Only information from the initial query is stored:
' these variables are not updated on "more results" pages.
' If you add additional search criteria in your search page, make sure
' to add their initial value to the Session object.
' Server.HTMLEncode is required to store queries with double quotes.
if Request("sh") = "" then
Session("q1")=Server.HTMLEncode(Request("q1"))
Session("q2")=Request("q2")
Session("ct")=Request("ct")
Session("c3")=Request("c3")
Session("o3")=Request("o3")
Session("q3")=Request("q3")
Session("o4")=Request("o4")
Session("q4")=Request("q4")
Session("c5")=Request("c5")
Session("q5")=Request("q5")
Session("c6")=Request("c6")
Session("q6")=Request("q6")
Session("c7")=Request("c7")
Session("q7")=Request("q7")
Session("c8")=Request("c8")
Session("q8")=Request("q8")
Session("c9")=Request("c9")
Session("q9")=Request("q9")
end if
' Read session object into variables.
q1=Session("q1")
q2=Session("q2")
ct=Session("ct")
c3=Session("c3")
o3=Session("o3")
q3=Session("q3")
o4=Session("o4")
q4=Session("q4")
c5=Session("c5")
q5=Session("q5")
c6=Session("c6")
q6=Session("q6")
c7=Session("c7")
q7=Session("q7")
c8=Session("c8")
q8=Session("q8")
c9=Session("c9")
q9=Session("q9")
%>
<% end if %>
The second section of search.asp is the search initiation section. This section displays the form for the user to specify the search criteria. As you can see, the input fields on the form are assigned specific names. To make it easy for you to build custom search pages, Site Server provides what is called Conventional Query String Variables. These variables are two-letter tags that are designed to identify the property you want to query on and the value to use for the criteria for the query. For example, the ct tag identifies the catalog to use for the search. The qn tag (where n is a number) specifies the query string variables. You should use the qn tag in conjunction with the cn tag, because the cn tag specifies the column you want to search for the qn value. As you can see in the code, the qn and cn tags are used heavily. An example query string from a typical search looks like:
q1=&c2=@DocAuthor&q2=&c3=@filewrite&o3=%3E%3D&q3=-1y&c5=@MessageEmailAddress&q5=&o4=@DocTitle&q4=&c6=@MessageFolder&q6=&ct=Discussion&c7=@META_Type&q7=&c8=@META_Industry&q8=&c9=@META_Product&q9=
<% ' Search Initiation Section.
' Show the search form. If the search is being edited, read the information
' that has been previously stored in the Session object.
%>
<p>
<table cellpadding=5 border=0>
<form action="Search.asp" method="get">
<tr>
<td nowrap><font size=2>
<% L_QueryLabel_text = "Search for:" %>
<% = L_QueryLabel_Text %>
</font>
</td>
<td>
<input type="text" name="q1" size="25" maxlength="100" value="<% = q1 %>">
</td>
<td width=5></td>
<td>
<%
' Author
L_AuthorLabel_text = "Sent by"
%>
<font size=2><% = L_AuthorLabel_text %>:</font>
</td>
<td>
<input type="hidden" name="c2" value="@DocAuthor">
<input type="text" maxlength=100 size=25 name="q2" value="<% = q2 %>">
</td></tr>
<tr>
<td>
<font size=2>
Sent in the last:
</font>
</td>
<td>
<input type=hidden name="c3" value="@filewrite">
<input type=hidden name="o3" value=">=">
<select name="q3">
<option value="" <%if Request("q3")="" then %>selected<%end if%> >
<option value="-1d" <%if q3="-1d" then %>selected<%end if%> >day
<option value="-1w" <%if q3="-1w" then %>selected<%end if%> >week
<option value="-1m" <%if q3="-1m" then %>selected<%end if%> >month
<option value="-1y" <%if q3="-1y" then %>selected<%end if%> >year
</select>
</td>
<td></td>
<td><font size=2>
Sent to: (alias)
</font></td>
<td>
<input type=hidden name=c5 value="@MessageEmailAddress">
<input type=text name=q5 size=25 maxlength=50 value="<% = q5 %>">
</td>
</tr>
<tr><td>
<font size=2>Subject:</font>
</td>
<td>
<input type=hidden name="o4" value="@DocTitle">
<input type=text name="q4" size=25 maxlength=50 value="<% = q4 %>">
</td>
<td></td>
<td><font size=2>
Folder:
</font></td>
<td>
<input type=hidden name="c6" value="@MessageFolder">
<input type=hidden name="q6" size=25 maxlength=50 value="<% = q6 %>">
<select name="ct" value="ct">
<% ' Enter New Catalog Names here.
%>
<!-- Use the following syntax for to search all catalogs
<option value="Discussion,ProductKnowledge,Business,list_Servers"> All Indexed Folders
-->
<!-- You need to put your catalog name here -->
<option value="Discussion"> \Discussion
</Select>
</td>
</tr>
<tr>
<!-- Add search by Category -->
<td><font size=2>
Category:
</font></td>
<td><input type=hidden name="c7" value="@META_Type">
<select name="q7">
<option value="" <%if q7="" then %>selected<%end if%> >
<option value="Best Practice" <%if q7="Best Practice" then %>selected<%end if%> >Best Practice
<option value="Idea" <%if q7="Idea" then %>selected<%end if%> >Idea
<option value="Issue" <%if q7="Issue" then %>selected<%end if%> >Issue
<option value="Resolution" <%if q7="Resolution" then %>selected<%end if%> >Resolution
</select>
</td>
<td></td>
<!-- Add Search by Industry -->
<td><font size=2>
Industry:
</font></td>
<td><input type=hidden name="c8" value="@META_Industry">
<select name="q8">
<option value="" <%if q8="" then %>selected<%end if%> >
<option value="Communication and Entertainment" <%if q8="Communication and Entertainment" then %>selected<%end if%> >Communication and Entertainment
<option value="Distributed Services" <%if q8="Distributed Services" then %>selected<%end if%> >Distributed Services
<option value="Financial Services" <%if q8="Financial Services" then %>selected<%end if%> >Financial Services
<option value="Government" <%if q8="Government" then %>selected<%end if%> >Government
<option value="Healthcare" <%if q8="Healthcare" then %>selected<%end if%> >Healthcare
<option value="Information Systems(Hardware/Software)" <%if q8="Information Systems(Hardware/Software)" then %>selected<%end if%> >Information Systems(Hardware/Software)
<option value="Manufacturing" <%if q8="Manufacturing" then %>selected<%end if%> >Manufacturing
<option value="Professional Services" <%if q8="Professional Services" then %>selected<%end if%> >Professional Services
<option value="Transportation" <%if q8="Transportation" then %>selected<%end if%> >Transportation
</select>
</td>
</TR>
<TR>
<!-- Add Search by Product -->
<td><font size=2>
Product:
</font></td>
<td><input type=hidden name="c9" value="@META_Product">
<select name="q9">
<option value="" <%if q9="" then %>selected<%end if%> >
<option value="(Other)" <%if q9="(Other)" then %>selected<%end if%> >(Other)
<option value="Access" <%if q9="Access" then %>selected<%end if%> >Access
<option value="Excel" <%if q9="Excel" then %>selected<%end if%> >Excel
<option value="Exchange Server" <%if q9="Exchange Server" then %>selected<%end if%> >Exchange Server
<option value="Mail" <%if q9="Mail" then %>selected<%end if%> >Mail
<option value="Office" <%if q9="Office" then %>selected<%end if%> >Office
<option value="Outlook" <%if q9="Outlook" then %>selected<%end if%> >Outlook
<option value="PowerPoint" <%if q9="PowerPoint" then %>selected<%end if%> >PowerPoint
<option value="Visual Basic" <%if q9="Visual Basic" then %>selected<%end if%> >Visual Basic
<option value="Visual C++" <%if q9="Visual C++" then %>selected<%end if%> >Visual C++
<option value="Word" <%if q9="Word" then %>selected<%end if%> >Word
</select>
</td>
<td colspan=5 align=right>
<% ' Links to tips and search button.
L_SearchButton_label = "Search"
L_SearchTips_link = "Tips"
%>
<input type="submit" value="<% = L_SearchButton_label %>">
<font size=2><a href="tips.htm"><% = L_SearchTips_link %></a>
</font>
</td>
</tr>
</table>
</form>
<% ' End of Search Initiation Section. %>
The next section of the code checks to see if the user has the ActiveX® control installed on his or her machine that launches Outlook so they can view the item. If the user does not, Outlook Web Access will be used to display the item. The code then creates the query to the catalog by using the Site Server Query object. The Query object has a number of properties that you can use to create very complex queries against Site Server catalogs. In the search.asp code, the first step is to create the Query object by calling Server.CreateObject with the ProgID of the Query object, MSSearch.Query. Because the app passes all the information about the query along the URL query string, we can use the method SetQueryFromUrl to have the Query object automatically parse the URL query string and set the Query object properties according to the specified conventional query string variables.
When working with Exchange Server, use the OptimizeFor property to specify that you do not want a hit count. This will improve the performance of your application. The code also uses the MaxRecords property to specify the maximum number of records to return on each page. The Columns property specifies the columns to return in the recordset that we create later on. You have to put the names of the columns you want to display in this property.
The final step in creating the search results is to actually create the recordset of items that match our criteria. To do this, we need to call the CreateRecordSet method on the Query object. This method will create an ActiveX Data Objects (ADO) sequential, forward-only recordset that we can use to display our results. Here's the code:
<% ' Search Results Section. %>
<% if Request.QueryString <> "" then %>
<%
' If site visitors use Outlook to view Microsoft Exchange messages,
' the Exciol control is installed on their computer.
if ExchangeViewer="both" or ExchangeViewer="outlook" then %>
<object id="Exciol" height=0 width=0
CLASSID="CLSID:DAFD7A40-73FF-11D1-A811-00AA006EAC9D"
CODEBASE="/siteserver/knowledge/search/controls/exciol.ocx#version=5,5,2148,0"
TYPE="application/x-oleobject">
</object>
<script language="vbscript">
Sub DisplayMsg(EntryID)
Exciol.DisplayMsg(EntryID)
End Sub
</script>
<% end if %>
<% if ExchangeViewer="both" or ExchangeViewer="owa" then %>
<% ' When linking to Outlook Web Access, open the link in a new window. %>
<script language="Javascript">
function openNewWindow(fileName,theWidth,theHeight) {
window.open(fileName,"NewWindow","toolbar=0,location=0,directories=0,status=1,menubar=1,scrollbars=1,resizable=1,width="+theWidth+",height="+theHeight)
}
</script>
<% end if %>
<% ' Set query object properties.
set Q = Server.CreateObject("MSSearch.Query")
' Define all required query properties: the query itself, and all columns
' that will be used in the results.
Q.SetQueryFromURL(Request.QueryString)
Q.Catalog = request("ct")
Q.OptimizeFor="nohitcount,performance"
Q.MaxRecords = 10
Q.Columns = "DocAuthor, DocTitle, DocAddress, Description, Size, FileWrite"
%>
<% ' The following debug information is useful as you extend this sample page.
' Set DEBUGINFO to true to see what is being passed to this page, and the
' resulting query property setting.
%>
<% if DEBUGINFO=true or Request("debug") <> "" then %>
<p>
<table cellpadding=5 border=1 bgcolor="EEEEEE">
<tr><td>
<b>Useful Debug Information</b><font size=2>
<p><b>QueryString passed to this page:</b>
<br><% = Request.QueryString %>
<p><b>Query:</b> <% = Q.Query %>
<p><b>Catalogs:</b> <% = Q.Catalog %>
</font></td></tr>
</table>
<% end if %>
<hr>
<% ' Create the recordset holding the search results.
on error resume next
set RS = Q.CreateRecordSet("sequential")
if err <> 0 then
createerror = err.description
end if
' Log query for reporting with the Site Server Analysis feature of
' Microsoft Site Server. Only log query for first page of search results.
' if Q.StartHit = "" and Session("q1") <> "" then
' InfoToLog = "&MSS.request.Search Catalog=" & Q.Catalog & _
' "&MSS.request.Search Start Hit=0" & _
' "&MSS.request.Search Query="& Session("q1")
' if err or (RS.EOF and RS.BOF) then
' InfoToLog = InfoToLog & "&MSS.request.Search Row Count=0"
' else
' InfoToLog = InfoToLog & "&MSS.request.Search Row Count=0"
' end if
' ' Information to be appended cannot contain commas or spaces.
' InfoToLog = Replace(InfoToLog, " ", "%20")
' InfoToLog = Replace(InfoToLog,",","+")
' Response.AppendToLog InfoToLog
' end if
' If the query can't be executed, print out the error description.
if err then
Response.write " " & createerror
' If no matches are found, display a message.
elseif RS.BOF and RS.EOF then
Response.write "<p>"
if Q.QueryIncomplete=true then
L_TooComplex_Error = "The query is too complex. Try using a simpler query. For information on search syntax, see <a href=tips.htm>Search Tips</a>."
Response.write L_TooComplex_Error & "<p>"
else
L_NoMatch_Error = "No messages matching your query were found. For suggestions on how to broaden your search, see <a href=tips.htm>Search Tips</a>."
Response.write L_NoMatch_Error & "<p>"
' Display link for a new search.
L_NewSearch_link = "New Search"
%>
<a href="Search.asp"><% = L_NewSearch_Link %></a>
<%
end if
else ' If query could be executed, display results.
The final section of the code displays the actual returned items in the recordset using an HTML table. To return the location of the item as a URL, the code uses the DocAddress property contained for each item in the Site Server catalog. The code also displays two ways for the user to view items: using the Outlook client or using Outlook Web Access.
' Set up the table for displaying results.
%>
<table cellpadding=0>
<tr>
<td colspan=2><font size=2>
<% ' Make introductory sentences match the information displayed.
if Request("sh") = "" then
L_Match_text = "Here are the messages found matching the query"
else
L_Match_text = "Here are more messages found matching the query"
end if
Response.write L_Match_text & "<b> " & DisplayText & "</b>."
%>
<br>
<% if ExchangeViewer="both" then
L_OWA_Info = "For Microsoft® Exchange messages, click the author's name to view the message using Microsoft Outlook. Click the <img src=html.gif width=16 height=16 border=0 align=middle align=middle> icon to view the message using Microsoft Outlook Web Access."
Response.write L_OWA_Info
end if %>
<br>
</font></td>
</tr>
</table>
<table cellpadding=0 cellspacing=0>
<tr bgcolor=cccccc>
<%
L_KBytes_text = "KB"
L_Received_text = "Received"
L_Subject_text = "Subject"
L_Size_text = "Size"
L_From_text = "From"
%>
<td></td>
<td><font size=2><b><% = L_From_text %></b></font></td>
<td></td>
<td><font size=2><b><% = L_Subject_text %></b></font></td>
<td></td>
<td><font size=2><b><% = L_Received_text %></b></font></td>
<td></td>
<td><font size=2><b><% = L_Size_text %></b></font></td>
<td></td>
</tr>
<%
' Set up loop to iterate through results.
Do while not RS.EOF
' Determine format type, set up title for and URL for links.
if InStr(RS("MimeType"), "text/exch") then
DocType="exchange"
else
DocType="doc"
end if
' If message title is blank, use "No subject" instead.
if RS("DocTitle") <> "" then
Title = RS("DocTitle")
else
L_Untitled_text = "No subject"
Title = L_Untitled_text
end if
' Provide alternate text if no author exists. HTMLEncode is
' required to handle author fields with < or >.
if RS("DocAuthor") <> "" then
Author = Server.HTMLEncode(RS("DocAuthor"))
else
L_NoAuthor_text = "Author unknown"
Author = L_NoAuthor_text
end if
' Set up link itself. Link depends on whether item is document or
' Microsoft exchange message.
if DocType="doc" then
Link = RS("DocAddress")
Image = "html.gif"
elseif DocType="exchange" then
Image = "owa.gif"
if ExchangeViewer="owa" then
Link = "JavaScript:self.openNewWindow(" & chr(34) & RS("DocAddress") & "&usemainwnd=1" & chr(34) & ", 640,500)"
elseif ExchangeViewer="outlook" or ExchangeViewer="both" then
Link = "VBScript:self.DisplayMsg(" & chr(34) & RS("DocAddress") & "=1" & chr(34) & ")"
end if
if ExchangeViewer="both" then
OWALink = "JavaScript:self.openNewWindow(" & chr(34) & RS("DocAddress") & "&usemainwnd=1" & chr(34) & ", 640,500)"
end if
end if
%>
<% ' Create table row for each result. %>
<tr><td> </td></tr>
<tr>
<% if DEBUGINFO=true or Request("debug") <> "" then %>
<% ' Display column with record number. %>
<td valign=top><font size=2><% = RecordNum %>.</font></td>
<% end if %>
<td valign=top>
<a href='<% = Link %>'><img src="<% = Image %>" hspace=6 border=0></a>
</td>
<td width=20% valign=top><font size=2>
<a href='<% = Link %>'><b><% = Author %></b></a>
<% if ExchangeViewer = "both" and DocType="exchange" then %>
<a href='<% = OWALink %>'><img src="html.gif" height=16 width=16 border=0 align=top></a>
<% end if %>
</font></td>
<td width=5> </td>
<td width=55% valign=top><font size=2>
<b><% = Title %></b>
</font></td>
<td width=5> </td>
<td valign=top nowrap><font size=1>
<% = RS("FileWrite") %>
</font></td>
<td width=5> </td>
<td valign=top><font size=1>
<% iSize = CInt(CLng(RS("Size"))/1024) %>
<% Response.write iSize & " " & L_KBytes_text%>
</font></td>
</tr>
<tr>
<td></td>
<td colspan=6><font size=2>
<table cellpadding=0 cellspacing=0>
<td width=30> </td>
<td><font size=1>
<% = RS("Description") %>
</font></td>
</tr>
</table>
</td>
</tr>
<% ' Increment the results.
RS.MoveNext
RecordNum = RecordNum + 1
Loop
%>
<% ' If query times out, display message stating that more results are available. %>
<%
if Q.QueryTimedOut = TRUE then
Response.write "<tr><td></td><td colspan=8><font size=2><b>"
L_QueryTimedOut_error = "Not all matching messages were returned. To see all the messages, at the top of the page, click Search again."
Response.write " <p>" & L_QueryTimedOut_error
Response.write "<b></td></tr><font size=2>"
end if
%>
</table>
<hr>
<table cellpadding=4>
<tr><td><font size=2>
<% ' Display a More Results link if there are more results pages.
if RS.Properties("MoreRows") = true then
Q.StartHit = RS.Properties("NextStartHit")
' Repeat query with new start hit. The query must include any
' custom variables you've used: in this case, Text and RecordNum.
Response.write "<a href=search.asp?" _
& Q.QueryToURL & "&" _
& "Category=" & Request("Category") & "&" _
& "DisplayText=" & Server.URLEncode(DisplayText) & "&" _
& "RecordNum=" & RecordNum _
& ">"
L_MoreResults_link = "More Results"
Response.write L_MoreResults_link & "</a> "
end if
%>
<% ' Display link for a new search. %>
<% L_NewSearch_link = "New Search" %>
<a href="Search.asp"><% = L_NewSearch_Link %></a>
</font></td></tr>
</table>
<% end if ' End of display of successful search results. %>
<% end if ' End of Search Results Section. %>
</font>
</body>
</html>
Further instructions and tips are provided in the sample application files.
As you have seen in this article, it is very easy to get started using Exchange Server and Site Server together to manage the daily flood of information that you likely receive into your business. However, this article and sample only scratch the surface of the types of applications you can build when you combine Site Server and Exchange Server. If you are interested in learning more about either of these products and how they can help you build interactive, dynamic and powerful Web sites, please visit http://www.microsoft.com/siteserver/ and http://www.microsoft.com/exchange/.