Tuesday, September 9, 2008

Custom Application Page for ListID issue

Scenario:
You want to provide a link to a particular System Application Page, but all the application pages accepts parameter in form of some ID which is not unique in different environments.

Solution:
Custom Application page that accepts the ListName and page you want to get redirected to. The new custom page will internally gets the correct ListID and then will re-direct to the correct Application page.

Redirect.aspx(12\Template\Layouts\Client\):

<%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Page Language="C#" MasterPageFile="~/_layouts/application.master" Inherits="Microsoft.SharePoint.WebControls.LayoutsPageBase" %>

<%@ Import Namespace="Microsoft.SharePoint" %>

<script runat="server">
protected override void OnLoad(EventArgs e)
{
SPWeb site = this.Web;

Guid listID = default(System.Guid);

string listName = Request.QueryString["List"];
string pageName = Request.QueryString["Page"];

if (listName != null && pageName != null)
{
foreach (SPList list in site.Lists)
{
if (list.Title.ToLower() == listName.ToLower())
{
listID = list.ID;
break;
}
}

Response.Redirect(this.Web.Url + @"/_layouts/" + pageName + ".aspx?List=" + listID);
}
}
</script>

<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
Redirection Page - Please pass the proper Request Query Parameters to get the redirection to work.</asp:Content>

<asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">Redirection Page</asp:Content>

<asp:Content ID="PageTitleInTitleArea" runat="server" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea">Redirection Page</asp:Content>


Usage:
Now you can call this Redirect page as
http://localhost/_layouts/client/redirect.aspx?List=Tasks&Page=listedit

and you will be redirected to the List Settings ( listedit.aspx ) of the Tasks list.

Monday, September 8, 2008

Creating User-Defined Function for Excel

Code:

using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Office.Excel.Server.Udf;

namespace ExcelSamples
{
[UdfClass]
public class MyFirstUDF
{
[UdfMethod]
public Int32 RandomNo()
{
Random r = new Random();
return (Int32)((r.NextDouble()*5)+1);
}
}
}
Article:
http://msdn.microsoft.com/en-us/library/bb428649.aspx
http://www.wrox.com/WileyCDA/Section/Excel-Services-User-Defined-Functions-UDFs-.id-305100.html

Creating Custom Application Page ( Code Behind )

Scenario:
You want to write a Custom Application Page for some additional configurations for all of your sites.

MyConfig.ASPX(12/TEMPLATE/Layouts/Client/):


<%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Assembly Name="CustomApplicationPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d4e5777b16a5749f" %>

<%@ Page Language="C#" MasterPageFile="~/_layouts/application.master"
Inherits="CustomApplicationPages.MyConfig"
EnableViewState="false" EnableViewStateMac="false" %>

<asp:Content ID="Main" contentplaceholderid="PlaceHolderMain" runat="server">
<table border="1" cellpadding="1" cellspacing="0" style="font-size:12">
<tr>
<td>Site Title:</td>
<td><asp:Label ID="lblSiteTitle" runat="server" /></td>
</tr>
<tr>
<td>Site ID:</td>
<td><asp:Label ID="lblSiteID" runat="server" /></td>
</tr>
</table>
</asp:Content>

<asp:Content ID="PageTitle" runat="server"
contentplaceholderid="PlaceHolderPageTitle" >
Hello World
</asp:Content>

<asp:Content ID="PageTitleInTitleArea" runat="server"
contentplaceholderid="PlaceHolderPageTitleInTitleArea" >
Custom Application Page : 'Hello World' with code behind
</asp:Content>

MyConfig.cs(GAC ,CustomApplicationPages.dll)
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace CustomApplicationPages {

public class MyConfig : Microsoft.SharePoint.WebControls.LayoutsPageBase {

// add control fields to match controls tags on .aspx page
protected Label lblSiteTitle;
protected Label lblSiteID;

protected override void OnLoad(EventArgs e) {

// get current site and web
SPSite siteCollection = this.Site;
SPWeb site = this.Web;

// program against controls on .aspx page
lblSiteTitle.Text = site.Title;
lblSiteID.Text = site.ID.ToString().ToUpper();
}
}
}
Usage:
You can access to the page from any web i.e.
 http://localhost/_layouts/client/myconfig.aspx
or you can also write a CustomAction to access the URL

ListID fix for the DataView webpart

Scenario:
You want to use a ListView webpart on your page, but ListView is tied to a ListID which will not be the same ListID in any other environment.

Fix:
Open the ListView in SharePoint Designer and tie it to ListName ( Tasks in this example) rather than ListView ID

Code:

<%@ Register TagPrefix="sharepoint" Namespace="Microsoft.SharePoint.WebControls"
Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register TagPrefix="webpartpages" Namespace="Microsoft.SharePoint.WebPartPages"
Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<sharepoint:SPDataSource runat="server" DataSourceMode="List" SelectCommand="&lt;View&gt;&lt;Query&gt;&lt;OrderBy&gt;&lt;FieldRef Name=&quot;ID&quot;/&gt;&lt;/OrderBy&gt;&lt;/Query&gt;&lt;/View&gt;" UpdateCommand="" InsertCommand="" DeleteCommand="" UseInternalName="True" IncludeHidden="True" ID="datasource1">


<SelectParameters>
<webpartpages:DataFormParameter ParameterKey="ListName" PropertyName="ParameterValues" DefaultValue="Tasks" Name="ListName">
</webpartpages:DataFormParameter>

<asp:QueryStringParameter QueryStringField="RootFolder" Name="RootFolder" Type="String"></asp:QueryStringParameter>
<asp:Parameter DefaultValue="0" Name="StartRowIndex"></asp:Parameter>
<asp:Parameter DefaultValue="0" Name="nextpagedata"></asp:Parameter>
<asp:Parameter DefaultValue="100" Name="MaximumRows"></asp:Parameter>

</SelectParameters>

<UpdateParameters>
<webpartpages:DataFormParameter ParameterKey="ListName" PropertyName="ParameterValues" DefaultValue="Tasks" Name="ListName">
</webpartpages:DataFormParameter>
</UpdateParameters>

<InsertParameters>
<webpartpages:DataFormParameter ParameterKey="ListName" PropertyName="ParameterValues" DefaultValue="Tasks" Name="ListName">
</webpartpages:DataFormParameter>
</InsertParameters>

<DeleteParameters>
<webpartpages:DataFormParameter ParameterKey="ListName" PropertyName="ParameterValues" DefaultValue="Tasks" Name="ListName">
</webpartpages:DataFormParameter>
</DeleteParameters>
</sharepoint:SPDataSource>


Articles:
SPDataSource for every sharepoint developer

SPDatasource every developer friend

SPDatasource fields for webs listsoflists

Rollups with the data view

http://sharepointdevwiki.com/display/public/Accessing+List+Items+using+SPDataSource+using+the+object+model

Local Activation permission for CLSID {61738644-F196-11D0-9953-00C04FD919C1}

Scenario:
I was investigating an error for my Custom Content Source crawl.I checked ( Event Log > System Node )

I found the following information :

The application-specific permission settings do not grant 'Local Activation' permission for the COM Server application with CLSID {61738644-F196-11D0-9953-00C04FD919C1}

After searching for the CLSID in Registry I found that SharePoint AppPool account needed launching privileges to the Ifilter's 'PDFThunkingSvr' DCOM object and the 'IIS WAMREG Admin service' DCOM object.

Steps:

Start > Administrative Tools > Component Services

1. Look for 'PDFThunkingSvr' DCOM and give access to the database account
2. Look for 'IIS WAMREG Admin service' and give access to the database account
3. Restart Search service ( net stop osearch )
4. After re-crawling , I dont see that DCOM error anymore

Protocol Handler Issues

Scenario:
You wrote a new Protocol Handler and configured it to be used by SharePoint Search.

Possible Errors:
1. Protocol Handler is not registered.
2. Access Denied


Possible Resolution:
1. Protocol Handler is not registered.
Make sure you have registerd the protocol handler assembly, you can verify the same by checking the Registry ( REGEDIT ) , make sure 'codebase' value is specified for the Protocol Handler binary

2. Access Denied
Protocol Handler uses two different accounts to get the information to be crawled.
-- First call to 'Init()' function is made using the Account running the deamon process( mssdmn.exe )
-- Second call to 'CreateAccessor()' function is made using the Account you have configured to access the particular Content Source

Sunday, September 7, 2008

Cross-list queries with SPSiteDataQuery

Scenario:
You need to query cross-list items across multiple Web sites

Solution:
'SPSiteDataQuery' is more efficent for such a situation.
'SPQuery' should be used to query a particular list

Sample Code:


SPWeb webSite = SPContext.Current.Web;
SPSiteDataQuery query = new SPSiteDataQuery();

query.Lists = "<Lists ServerTemplate=\"107\" />";
query.Query = "<Where><Eq><FieldRef Name=\"Status\"/>" +
"<Value Type=\"Text\">Completed</Value></Eq></Where>";

System.Data.DataTable items = webSite.GetSiteData(query);

foreach (System.Data.DataRow item in items)
{
Response.Write(SPEncode.HtmlEncode(item["Title"].ToString()) + "<BR>");
}