Thursday, October 21, 2010

How to control "Access Denied" page

The SPUtility.HandleAccessDenied method provides the functionality to redirect users to the standard "Access Denied Page" pragmatically, thus asking them to re-logon. One of the scenarios of such usage is the public sites, where access to the standard SharePoint specific pages still exists and you want to block those pages

However, you can handle access denied exception via SPSecurity.CatchAccessDeniedException = true (source)

How to avoid Access denied page

Access deined exception is handled by sharepoint platform and user will be redirected to _layouts/AccessDenied.aspx page if user doesnt have permission to perform that task. This might casue usability problem in some cases. You can handle access denied exception in your code by setting CatchAccessDeniedException value to true.
Following code snippet shows how to handle access denied exception:

bool catchException = SPSecurity.CatchAccessDeniedException;
SPSecurity.CatchAccessDeniedException = false;
try
{
//updating list item
SPList list = SPcontext.Current.Web.List["TestList"];
SPListItem item = list.Items[0];
item["title"] = "Some value";
//If user doesnt have permission, exception will be thrown
//If value of CatchAccessDeniedException is true, then user will be
//redirected to AccessDenied.aspx page
item.Update();
}
cach(Exception ex)
{
//Your custom error message can be shown here
}
finally
{
//reset the flag to original value
SPSecurity.CatchAccessDeniedException = catchException;
}

Reference: sridharu blog.

Thanks!
Avinash

Wednesday, October 20, 2010

Custom Content Query Web Part

When we need to add some custom property into OOB CQWP then we have to create custom CQWP.
As well as when we need redeploy CQWP then also we need to use custom content query web part.

Please view below code to create custom content query web part:-

1 point: We need to create a custom class whcih extend OOB content query web part class

public class CustomPortalContentQuery : ContentByQueryWebPart
{
public override ToolPart[] GetToolParts()
{
List toolPart = new List(base.GetToolParts());
toolPart.Insert(0, new CustomPortalToolPart());
return toolPart.ToArray();
}
protected override void OnInit(EventArgs e)
{
FixListGuid(); // this to fix list guid if you are redeploying cqwp to other site
this.ItemXslLink = this.ServerRelativeItemXslLink;
this.MainXslLink = this.ServerRelativeMainXslLink;
base.OnInit(e);

}
protected override void CreateChildControls()
{
base.CreateChildControls();
}

private void FixListGuid(){
try
{
if (!string.IsNullOrEmpty(base.WebUrl) && !string.IsNullOrEmpty(base.ListName))
{
using (SPWeb web = SPContext.Current.Site.OpenWeb(base.WebUrl, true))
{base.ListGuid = web.Lists[base.ListName].ID.ToString();
}
}
}
catch (Exception ex){}
}
}
}

2 point: We need to create a custom class for tool pane.
internal class CountryPortalToolPart : Microsoft.SharePoint.WebPartPages.ToolPart
{
CustomPortalContentQuery webpart;
TextBox itemXslLink;
Panel toolPanel;
Table toolPanelTable;
public CountryPortalToolPart()
{
this.Title = "Custom Settings";
}
protected override void CreateChildControls()
{
webpart = this.WebPartToEdit as CustomPortalContentQuery;
toolPanel = new Panel();toolPanel.CssClass = "ms-ToolPartSpacing";
toolPanel.Controls.Add(GetToolPanel());
this.Controls.Add(toolPanel);
base.CreateChildControls();
}

public override void ApplyChanges()
{try
{
webpart.ItemXslLink = itemXslLink.Text;
}

catch { }

base.ApplyChanges();}
private Control GetToolPanel()
{
toolPanelTable = new Table();
toolPanelTable.CellPadding = 0;
toolPanelTable.CellSpacing = 0;
toolPanelTable.Style["border-collapse"] = "collapse";
toolPanelTable.Attributes.Add("width", "100%");
toolPanelTable.Rows.Add(GetItemXslLinkRow());
return toolPanelTable;
}

private TableRow GetItemXslLinkRow()
{

TableRow row = new TableRow();
TableCell cell = new TableCell();

cell.Controls.Add(new LiteralControl("
Item XSL Link:
"));
cell.Controls.Add(new LiteralControl("
"));


itemXslLink = new TextBox();
if (string.IsNullOrEmpty(webpart.ItemXslLink))
{
itemXslLink.Text = this.webpart.ServerRelativeItemXslLink;
}
else
itemXslLink.Text = this.webpart.ItemXslLink;
cell.Controls.Add(itemXslLink);
cell.Controls.Add(new LiteralControl("
"));
row.Cells.Add(cell);
return row;
}
}


Hope it helps you.

Thanks!
Aviansh

import content query web part to other site

While import exiting CQWP from one site to other site, gives an issue of List GUID. It does not work since it point to old site list guid.

I got solution for this. First of course we need to create Custom CQWP whcih extent OOB CQWP. then i wrote a function to fix listGUID issue.
please refer my article

Making the content query web part deployable

Thanks!
Avinash

Making the content query web part deployable

My biggest issue with the CQWP? its not deployable when connected to a specific list in a specific site.
If you configure a CQWP web part to connect to a list in a site, the web part saves the ID (GUID) of the list - and if you want to deploy the web part as part of a feature or onet.xml so that the web part gets added every time a user creates a site, it will fail - because the ID of the list changes every time you create a new site.
My solution? override the web part and implement the following functions:
private void FixListGuid()
{
try
{

if (!string.IsNullOrEmpty(base.WebUrl) && !string.IsNullOrEmpty(base.ListName))
{
using (SPWeb web = SPContext.Current.Site.OpenWeb(base.WebUrl, true))
{
base.ListGuid = web.Lists[base.ListName].ID.ToString();
}
}
}
catch (Exception ex)
{
SPZetaContext.GetContext(HttpContext.Current).Log.Warn("Unable to resolve SPList '" + this.ListName + "'", ex);
}
}
protected override void OnLoad(EventArgs e)
{
FixListGuid ();
base.OnLoad(e);
}
}

This code works for me..

How to create custom Content Query Web Part


Thanks!
Avinash

Friday, October 8, 2010

This page contains content or formatting that is not valid. You can find more information in the affected sections

You get this error when you are trying to update a SharePoint webpart tool part or something like that and you click on 'Publish' page button. This only happens if you have any Validation Controls on your webpart.

Resolution: As you have validation controls on your webpart UI and you are not filling in anything, it is not letting your page to postback and you need to disable rendering the webpart while you are modifying the toolpart. You can do that by writing down code as below in your 'CreateChildControls method of webpart

protected override void CreateChildControls()
{ 

WebPartManager wp = WebPartManager.GetCurrentWebPartManager(this.Page); 
if (wp.DisplayMode == WebPartManager.BrowseDisplayMode)
{
// add your validator control
} 
else
{
// dont add your validator control
}

base.CreateChildControls(); 

}

Thanks & Regards,
Avinash Dad

Monday, October 4, 2010

Document Icon in CQWP

You can find solution on some blogs like:-
http://edinkapic.blogspot.com/2007/09/document-icon-in-cqwp.html

But I got very short solution which is mentioned below:-

First, we should add the DocIcon in the CommonViewFields property (export the CQWP, edit the .webpart file) as follows:

<property name="CommonViewFields" type="string"">DocIcon, Lookup;</property">

Then, you can use following tempalte to get icon:-

<xsl:template name="RecentDcoument" match="Row[@Style='RecentDcoument']" mode="itemstyle">
<xsl:variable name="SafeLinkUrl">
<xsl:call-template name="OuterTemplate.GetSafeLink">
<xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
</xsl:call-template>
</xsl:variable>
<div id="linkitem" class="item" style="vertical-align:middle;">
<div style="float:left;">
<IMG BORDER="0" ALT="{@FileLeafRef}" title="{@FileLeafRef}" SRC="/_layouts/images/{ddwrt:MapToIcon(string(@DocIcon),string(@DocIcon))}" />
</div>
<div>
<xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/>
<a href="{$SafeLinkUrl}" target="{$LinkTarget}" title="{@LinkToolTip}" style="padding-left:5px;">
<xsl:value-of select="ddwrt:UrlBaseName(string($SafeLinkUrl))" />
</a>
</div>
</div>
</xsl:template>