Friday, February 18, 2011

Setting time out for Silverlight web part

There is the way to set time out for Silverlight web part. This time out happens when web part can't load xap file.
The value is hard-coded within web part and equal 5 sec which is not so much.
First of all where this value is hard-coded? If you viewed source of the page with Silverlight web part you could found javascript line like that

window.setTimeout("_spCheckIfSilverlightPluginIsLoaded_WebPartctl00_m_g_0f7cd87d_f3fd_49d9_91ec_ad4b46cfe999();", 5000);

This is our bad guy. Value 5000 is hard-coded and function name contains web part Id (ctl00_m_g_0f7cd87d_f3fd_49d9_91ec_ad4b46cfe999 in my case).

So, the easiest way to handle it is to eliminate time out at all by creating same named dummy JavaScript function:

1. Go to page source and search for _spCheckIfSilverlightPluginIsLoaded_WebPart phrase. You suppose to find function which starts with this phrase. Copy function name to clipboard.

2. Add content editor web part after Silverlight web part and put empty JavaScript function with saved name there like that

<script type="text/javascript">
function _spCheckIfSilverlightPluginIsLoaded_WebPartctl00_m_g_0f7cd87d_f3fd_49d9_91ec_ad4b46cfe999(){}
</script>


where _spCheckIfSilverlightPluginIsLoaded_WebPartctl00_m_g_0f7cd87d_f3fd_49d9_91ec_ad4b46cfe999 is a function name I've found on my page.

> Update! - one more (even better!) workaround:

You can override _spSetSLPluginNotLoadedErrorMessage function which is called by web part if XAP file wasn't loaded in 5 sec.

1. Just drop this tag in Content Editor web part on the page:


<script type="text/javascript"> function _spSetSLPluginNotLoadedErrorMessage(wpId){ 

</script>

> end of update

This is working just fine if you have couple pages with Silverlight web part and you are Ok do not have any time out.

Better but little bit more complicate way is creating javascript to set a new time out value. Main idea is put some code in our dummy function with new time out value. I created a web part for that. It is on codeplex.
It scans the page for Silverlight web parts and renders javascript for each instance. It has just one property - time out :)

Please note this web part should be on your page after Silverlight web part.

How I tested it:
I put two Silverlight web parts to my page with wrong reference to xap file. I got time out in 5 secs on both. Then I put my web part in between. I got time out in 15 secs (my default value) for the first Silverlight web part and still 5 secs for the second.

You can check out wsp package and source code.

Have fun with Silverlight!

Friday, January 7, 2011

WSS-like breadcrumb in SharePoint 2010

This was the first user's request after migration had been done. It wasn't very important. Just annoying. I played some time with site navigation and ended up with jQuery. There is a kind of WSS-like breadcrumb on SharePoint 2010 master page but now it is a pop-up. The idea is to put it to page in usual way.

1. Add reference to jQuery into your master page, e.g.

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>


just before tag </head>

2. Add breadcrumb holder div and jQuery next to it where you want to see it

<div class="wss-BreadCrumb"></div>
<script type="text/javascript">
$("a.s4-breadcrumbRootNode").clone().appendTo('div.wss-BreadCrumb');
$("a.s4-breadcrumbNode").clone().appendTo('div.wss-BreadCrumb');
$("a.s4-breadcrumbCurrentNode").clone().appendTo('div.wss-BreadCrumb');
$("<span>></span>").insertAfter('div.wss-BreadCrumb a.s4-breadcrumbRootNode');
$("<span>></span>").insertAfter('div.wss-BreadCrumb a.s4-breadcrumbNode');
$("span.s4-breadcrumbCurrentNode").clone().appendTo('div.wss-BreadCrumb');
</script>


3. Add styles to make it looks like WSS breadcrumb

div.wss-BreadCrumb
{
margin-bottom:5px;
display: inline-block;
}

div.wss-BreadCrumb span
{
margin-left:5px;
margin-right: 5px;
}

div.wss-BreadCrumb span.s4-breadcrumbCurrentNode
{
margin-left:0px;
margin-right:0px;
}


div.wss-BreadCrumb a.s4-breadcrumbNode, div.wss-BreadCrumb a.s4-breadcrumbCurrentNode,
div.wss-BreadCrumb a.s4-breadcrumbRootNode
{
color: blue;
}

Thursday, October 21, 2010

DisableEventFiring is obsolete in SharePoint 2010

You can check this in msdn. However DisableEventFiring()/EnableEventFiring() still works as per Reflector.
Recommended way now is to use new property EventFiringEnabled. This gives us an option to check current status and save it. I found a great post from Adrian Henke and modified his code using this new feature.



The class DisabledItemEventsScope disable/enable event firing for the current thread and could be used in that manner at any place including code behind for the page or web part



BTW: There are couple useful SPList extensions to manage SPListItemEventReceiver collection

Monday, October 11, 2010

SPUrl for WSS 3.0 or SharePoint Foundation

No, expression like <% $SPUrl:~sitecollection/Style Library/mystyles.css %> doesn't work for WSS or SharePoint Foundation. This is part of Publishing Infrastructure and you have to buy MOSS or SharePoint Server license to get it.

So, let's create our own ExpressionBuilder. I didn't implement 'language' support - obviously I need just Site and SiteCollection.


...
using System.Web.Compilation;
using Microsoft.SharePoint;

...
public class WSSUrlExpressionBuilder : ExpressionBuilder
{
public override CodeExpression GetCodeExpression
(System.Web.UI.BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
{
CodeTypeReferenceExpression thisType = new CodeTypeReferenceExpression(base.GetType());

CodePrimitiveExpression expression = new CodePrimitiveExpression(entry.Expression.Trim().ToString());

string evaluationMethod = "GetKeyValue";

return new CodeMethodInvokeExpression(thisType, evaluationMethod, new CodeExpression[] { expression });
}

public static object GetKeyValue(string expression)
{
SPWeb web = SPContext.Current.Web;

string key = "~SiteCollection";
if (expression.IndexOf(key, StringComparison.InvariantCultureIgnoreCase) == 0)
return web.Site.Url+expression.Substring(key.Length);

key = "~Site";
if (expression.IndexOf(key, StringComparison.InvariantCultureIgnoreCase) == 0)
return web.Url+ expression.Substring(key.Length);

return expression;
}

}
...


You need to put this class to some assembly and register it with your prefix(e.g. WSSUrl) in Web.Config


<configuration>
<system.web>
<compilation>
<expressionBuilders>
<add expressionPrefix="WSSUrl"
type="{your Namespace}.WSSUrlExpressionBuilder,{Assembly Name}"/>
</expressionBuilders>
</compilation>
</system.web>
</configuration>


Assembly Name should be fully qualified if you put the assembly into GAC.

Thursday, October 7, 2010

SharePoint: How to get document icon image

There is a method in SPUtility which makes it much easier. It takes image file name from docicon.xml, and should work Ok even if the file name is not follow the pattern ic{doc ext}.gif


string docIcon = SPUtility.ConcatUrls("/_layouts/images/",
SPUtility.MapToIcon(item.Web,
SPUtility.ConcatUrls(item.Web.Url,item.Url), "", IconSize.Size16));


There is a good post about SPUtility.MapToIcon vs SPFile.GetIcon