DocVault Listings Web Part

We will now create a custom Web Part that can provide dynamic content rollups across the different DocVault site collections. There are two views available in the initial Web Part, but additional ones can be identified as needed by extending the code and defined QueryMode property.

Creating the Web Part

The DocVault Listings Web Part will be added to the previously created SPBlueprints.WebParts project created in Chapter 2, Building an Out of Office Delegation Solution.

To add the additional Web Part:

  1. Open the SPBlueprints.WebParts project in Visual Studio 2010.
  2. Browse to the Installed Templates and select Visual C# | SharePoint | 2010.
  3. Right-click on the project file and select Add then New Item.
  4. From the template selection screen select the Web Part option.
  5. Provide the name DocVaultListings and click on the Add button.
  6. Edit the DocVaultListings.webpart file with the following definition:
    <properties>
    <Property Name="Group" type="string">SPBlueprints</Property>
    <property name="Title" type="string">DocVault
    Listings</property>
    <property name="Description" type="string">SPBlueprints - The
    DocVault Rollup web part displays content rollups for
    DocVault documents.</property>
    <property name="SearchProxyName" type="string">Search Service
    Application</property>
    <property name="SearchScopeName"
    type="string">DocVault</property>
    <property name="DisplayLimit" type="int">15</property>
    </properties>
    
    

Importing the needed Web Part and search references

Start by editing the DocVaultListings.cs file and add in the following references:

using System.Collections;
using System.Data;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.Office.Server.Search;
using Microsoft.Office.Server.Search.Query;
using Microsoft.Office.Server.Search.Administration;

Defining the Web Part properties

Next we will need to define the Web Part's properties starting with the Search Proxy Name property. This property will be used to manage the connection to the Search service application.

private string searchProxyName;
[WebBrowsable(true),
Category("Custom Properties"),
WebDisplayName("Search Proxy Name"),
WebDescription("Please provide the name of your Search Service
Application."),
Personalizable(PersonalizationScope.Shared)]
public string SearchProxyName
{
get { return searchProxyName; }
set { searchProxyName = value; }
}

Next we will define the Search Scope Name property which can be used to target the desirable content for display.

private string searchScopeName;
[WebBrowsable(true),
Category("Custom Properties"),
WebDisplayName("Search Proxy Name"),
WebDescription("Please provide the name of your Search Service
Application."),
Personalizable(PersonalizationScope.Shared)]
public string SearchProxyName
{
get { return searchProxyName; }
set { searchProxyName = value; }
}

Next we will define the Display Limit property used to determine how many records to display.

private int displayLimit;
[WebBrowsable(true),
Category("Custom Properties"),
WebDisplayName("Result limit"),
WebDescription("The number of items to display."),
Personalizable(PersonalizationScope.Shared)]
public int DisplayLimit
{
get { return displayLimit; }
set { displayLimit = value; }
}

In order to provide multiple views, we will add an enum property that will display as a drop-down list from within the Web Part properties page. This requires that we define and set a value so that it can be used within the Web Part.

private queryMode _queryMode;
public enum queryMode
{
ByUser,
Recent
}
[WebBrowsable(true),
Category("Custom Properties"),
WebDisplayName("Query Mode"),
WebDescription("Please select the query mode."),
Personalizable(PersonalizationScope.Shared)]
public queryMode QueryMode
{
get { return _queryMode; }
set { _queryMode = value; }
}
public DocVaultListings()
{
_queryMode = queryMode.ByUser;
}

Formatting the Web Part

The output will be built within a literal control defined within the class, and instantiated within the CreateChildControls() method shown as follows:

protected Literal _output;
protected override void CreateChildControls()
{
this._output = new Literal();
this._output.ID = "output";
this.Controls.Add(this._output);
}

With all of the setup work complete, we can now define the Display() method that can be called from the OnLoad() method. The method starts by defining the StringBuilder class, which we will use to build the output of the Web Part, and then attempts to connect to the Search Proxy specified in the Web Part properties.

protected void Display()
{
StringBuilder messages = new StringBuilder();
try
{
SearchQueryAndSiteSettingsServiceProxy settingsProxy =
SPFarm.Local.ServiceProxies.GetValue<SearchQueryAndSiteSettingsSer
viceProxy>();
SearchServiceApplicationProxy searchProxy =
settingsProxy.ApplicationProxies.GetValue<SearchServiceApplication
Proxy>(this.searchProxyName);
FullTextSqlQuery mQuery = new FullTextSqlQuery(searchProxy);

Next we will do some preparation work that is common to each of the views.

try
{
ResultTableCollection resultsTableCollection;
DataTable results = new DataTable();
bool bAltRow = true;

The multiple views of the Web Part are handled by a central switch statement that will check the _queryMode value and display the appropriate view.

switch (_queryMode){
case queryMode.ByUser:
break;
case queryMode.Recent:
break;
}

Within the ByUser view, we will construct and execute a query and then format the returned results. The FullTextSQLQuery will grab the desired properties from the specified search scope and filter them based on content generated by the current user. The Display Limit Web Part property will be used to limit the number of results returned. The included output will present the returned data similar to a normal list view, though the complex view functions have not been included.

string user = SPContext.Current.Web.CurrentUser.Name;
mQuery.QueryText = "SELECT Title, Customer, CustomerAccount,
LastModifiedTime, DocID, SiteTitle, ContentTypeSearch, CreatedBy,
Filename, FileExtension, Path FROM SCOPE() WHERE ("scope" = '" +
searchScopeName + "') AND Author = '" + user + "' ORDER BY
LastModifiedTime Desc";
mQuery.ResultTypes = ResultType.RelevantResults;
mQuery.TrimDuplicates = false;
mQuery.RowLimit = DisplayLimit;
resultsTableCollection = mQuery.Execute();
if (resultsTableCollection.Count > 0)
{
ResultTable relevantResults =
resultsTableCollection[ResultType.RelevantResults];
results.Load(relevantResults, LoadOption.OverwriteChanges);
messages.AppendFormat(@"<table width='100%' border='0'
cellpadding='1' cellspacing='0' class='ms-listviewtable'>
<tr class='ms-viewheadertr ms-vhltr'>
<td>Type</td><td>Site</td><td>Customer</td>
<td>Account</td><td>DocumentID</td>
<td>Name</td><td>Modified</td></tr>");
foreach (DataRow row in results.Rows)
{
messages.AppendFormat(@"<tr ");
if (bAltRow) {
messages.AppendFormat(@"class='ms-alternatingstrong'"); }
messages.AppendFormat(@"><td><a href='{6}'><img src='{7}'
border='0'></a></td><td>{0}</td><td>{1}</td><td>{2}</td>
<td>{3}</td><td><a href='{6}'>{4}</a></td><td>{5}</td></tr>",
row[5].ToString(), row[1].ToString(), row[2].ToString(),
row[4].ToString(), row[0].ToString(), row[3].ToString(),
row[10].ToString(), getImageRef(row[9].ToString()));
bAltRow = !bAltRow;
}
messages.AppendFormat(@"</table>");
}

Within the Recent view, we will construct and execute a similar query as the ByUser, but this query will look for documents recently edited by any user. It will also search against the specified search scope and limit the results to the Display Limit specified in the Web Part property.

mQuery.QueryText = "SELECT Title, Customer, CustomerAccount,
LastModifiedTime, DocID, SiteTitle, ContentTypeSearch, CreatedBy,
Filename, FileExtension, Path FROM SCOPE() WHERE ("scope" = '" +
searchScopeName + "') AND LastModifiedTime >= DATEADD (DAY, -30,
GETGMTDATE()) ORDER BY LastModifiedTime Desc";
mQuery.ResultTypes = ResultType.RelevantResults;
mQuery.TrimDuplicates = false;
mQuery.RowLimit = DisplayLimit;
resultsTableCollection = mQuery.Execute();
if (resultsTableCollection.Count > 0)
{
ResultTable relevantResults =
resultsTableCollection[ResultType.RelevantResults];
results.Load(relevantResults, LoadOption.OverwriteChanges);
messages.AppendFormat(@"<table width='100%' border='0'
cellpadding='1' cellspacing='0' class='ms-listviewtable'>
<tr class='ms-viewheadertr msvhltr'>
<td>Type</td><td>Site</td><td>Customer</td><td>Account</td>
<td>Document ID</td><td>Name</td><td>Modified</td></tr>");
foreach (DataRow row in results.Rows)
{
messages.AppendFormat(@"<tr ");
if (bAltRow) {
messages.AppendFormat(@"class='ms-alternatingstrong'"); }
messages.AppendFormat(@"><td><a href='{6}'><img src='{7}'
border='0'></a></td><td>{0}</td><td>{1}</td><td>{2}</td>
<td>{3}</td><td><a href='{6}'>{4}</a></td><td>{5}</td></tr>",
row[5].ToString(), row[1].ToString(), row[2].ToString(),
row[4].ToString(), row[0].ToString(), row[3].ToString(),
row[10].ToString(), getImageRef(row[9].ToString()));
bAltRow = !bAltRow;
}
messages.AppendFormat(@"</table>");

To complete the Display() method, we will set the Text property of the literal control named _output to the StringBuilder object message that we have been building. There is some additional error handling and object disposal included as part of the overall code flow.

this.EnsureChildControls();
this._output.Text = messages.ToString();
}
catch (Exception ex)
{
this.EnsureChildControls();
this._output.Text = "Error: " + ex.Message.ToString();
}
finally
{
mQuery.Dispose();
}
}
catch
{
this.EnsureChildControls();
this._output.Text = "Error: Please specify a Search Service
Application.";
}
}

The views also reference a simple method that will display an appropriate document icon for the specified file extension.

private string getImageRef(string extension)
{
string image = "";
switch (extension){
case "DOCX":
image = "/_layouts/images/icdocx.gif";
break;
case "XLSX":
image = "/_layouts/images/icdocx.gif";
break;
case "PDF":
image = "/_layouts/images/ICLOG.GIF";
break;
default:
image = "/_layouts/images/ICLOG.GIF";
break;
}
return image;
}

Display DocVault Listings Web Part

As we have seen, the DocVault Listings Web Part supports both a DocVault Recently Added view and a DocVault Edited by Me view. The rendered screenshots are shown as follows:

Display DocVault Listings Web Part
Display DocVault Listings Web Part
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.154.208