SaguiItay

My blog has moved!

You should be automatically redirected in 4 seconds. If not, visit:
http://itaysagui.wordpress.com
and update your bookmarks.

Friday, September 16, 2011

HTTP Services With WCF 4 and Windsor

Although a bit old, I found the following article, Vanilla Yet Composable HTTP Services With WCF 4 and Windsor, extremely helpful.

The article shows how to easily create services, and have their dependencies automatically resolved by the Windsor container, with minimal changes.

Labels: , ,

Thursday, September 15, 2011

SharePoint Client Object Model: Adding a Site Column only if it does not already exist

Before creating a new Site Column, you should make sure that the column doesn't already exist. At the very least, make sure that the ID you are using isn't already taken. The sample below uses the FindField method from a previous post:

public static Field EnsureField(this ClientContext clientContext, Web web, Guid id, string name, string schema)
{
	var field = FindField(clientContext, web, f => f.Id == id);
	if (field != null)
		return field;

	var newField = web.Fields.AddFieldAsXml(schema, false,
		AddFieldOptions.AddToNoContentType | AddFieldOptions.AddFieldInternalNameHint);
	clientContext.ExecuteQuery();
	return newField;
}

Labels: , ,

Wednesday, September 14, 2011

SharePoint Client Object Model: Verifying if a Field is part of a Content Type

Before adding a field to a ContentType, it is important to check that the field is not already part of the Content Type. Here's an extension method to ClientContext that does just that:

public static bool ExistInContentType( this ClientContext clientContext, ContentType contentType, Field field)
{
	var fieldLinks = contentType.FieldLinks;
	var existingFields = clientContext.LoadQuery(fieldLinks.Where(fl => fl.Id == field.Id));
	clientContext.ExecuteQuery();
	var existingField = existingFields.FirstOrDefault();
	if (existingField != null)
		return true;
	return false;
}

Labels: , ,

Tuesday, September 13, 2011

SharePoint Client Object Model: Finding a field in a list

When working with the SharePoint Client Object Model, it is useful to find a field in a list, or a site column in the web. Below are some extension methods to ClientContext, to facilitate these:

public static class FieldClientContextExtensions
{
    public static Field FindField(this ClientContext clientContext, List list,                                       
        Expression<Func<Field, bool>> predicate)
    {
        var webFields = list.Fields;
        var matchingFields = clientContext.LoadQuery(webFields.Where(predicate));
        clientContext.ExecuteQuery();

        Field field = matchingFields.FirstOrDefault();
        return field;
    }

    public static Field FindField(this ClientContext clientContext, Web web, Expression<Func<Field, bool>> predicate)
    {
        var webFields = web.Fields;
        var allFields = web.AvailableFields;
        var matchingWebFields = clientContext.LoadQuery(webFields.Where(predicate));
        var matchingAllFields = clientContext.LoadQuery(allFields.Where(predicate));

        clientContext.ExecuteQuery();
        Field field = matchingWebFields.FirstOrDefault() ?? matchingAllFields.FirstOrDefault();
        return field;
    }
}

Labels: , ,

Saturday, September 10, 2011

Windsor: Loading installers from the execution folder

When using Windsor, it is necessary to load the various IWindowsInstallers into the container. One standard way of doing this is using a code similar to the below:
container.Install(FromAssembly.InDirectory(new AssemblyFilter(".")));
The above code will load all the installed that are located in the execution folder.

However, in certain cases, when your code is running in different contexts, such as under IIS, you need to be a bit more explicit about things. You need to tell Windsor to load assemblies from the folder where you are running, and not from some run-time "copy" or cache folder.

For that, you can use the following class:

public class ExecutingAssemblyFilter : AssemblyFilter
{
    public ExecutingAssemblyFilter()
        : base(new FileInfo(new Uri(Assembly.GetExecutingAssembly).CodeBase).LocalPath).Directory.ToString())
    { }
 }

This class inherits from AssemblyFilter, and automatically provides the correct path. It should be used like this:
container.Install(FromAssembly.InDirectory(new ExecutingAssemblyFilter()));

Labels: ,

Wednesday, March 2, 2011

Windsor Factories and Obfuscation

I love Windsor - it's simplicity yet versatility amazes me every time I use it.

In my last project, I've used it, along with the TypedFactoryFacility in order to "late-resolve" some objects. The resolved object required some parameters to be passed to the CTOR - nothing too complex - you just create an annonymous type with properties that match the names of the parameters, and Windsor handles the matching and passes the values. Piece of cake.

Everything worked perfectly fine for a while. That is, until we started to test our release setups. Our testing team started to complain that the UI is not updated when they click the various buttons.
After some digging, I figured that objects are not being created in the Business Logic layer that uses Windsor, which are then reflected in the UI.

It took me almost a day to figure things out - in our release setups, our code is obfuscated. The anonymous type mentioned earlier is compiler-generated, and then obfuscated. Since it's a private class, it's properties are renamed, which result in Windsor not being able to match properties to parameters.

Once that was clear, the solution was simple - I replaced the anonymous type with a regular class, and marked it as Serializable, which notifies the obfuscation not to touch it.

After that, things went back to work - the class was not obfuscated, which means that the properties where not renamed. That in turn meant that Windsor was able to match properties to parameters, and the factory was able to resolve the objects.

Labels: , , ,

Monday, February 28, 2011

IRibbonExtensibility needs to be ComVisible

When developing an Outlook add-in using VSTO 4, if you are implementing the IRibbonExtensibility interface (for customizing a Ribbon, for example) you might encounter cases where your Ribbon or menu items don't appear in Outlook's UI.
In those cases, you should check the following things first:
  1. Your XML is valid - invalid Ribbon XML, such as placing the node inside the node are common mistakes, which will prevent your controls from appearing
  2. Your class should be marks as ComVisible:
    [ComVisible(true)]
    public class Ribbon : IRibbonExtensibility
    {
       ...
    }

Labels: , , ,