Friday, November 30, 2007

Accessing the Current Principal in VSTO Add-In

I recently tried to get access to the Current Principal within an Outlook Add-In. Accessing the Identity was returning a blank name and an unauthorised user. Wierd.

It turns out the the VSTOLoader will load each Add-In into its own AppDomain. As such, you need to set the principal policy explicitly before you access the current principal for the first time.

Example:

AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
string userName = Thread.CurrentPrincipal.Identity.Name;

As it running within an isolated environment, I am sure there are other issues you need to be aware of.

See the AppDomain Class in the MSDN Library for more information on application domains.

Thursday, November 29, 2007

Accessing Custom Resource Mailbox Properties With VSTO

In Exchange 2007 you can create custom resource properties to annotate your resources. For example, you may want to create a custom property called Vehicle and add this to all resources that represent vehicles in your Exchange organisation. The TechNet article, How to Create or Remove Custom Resource Properties, describes how this is done.

Getting access to these custom resource properties via Visual Studio Tools for Office (VSTO) is relatively straight forward, as long as you know exactly what you need to do! The problem is finding this with the documentation and newsgroup postings out there.

Anyway, access to this type of information is not available via properties on the Outlook Object Model. However, in VSTO 3 (for Outlook 2007), most Outlook objects have a PropertyAccessor object that allows you to get access to ALL the properties on the underlying MAPI object, not just the ones exposed by the COM interface. The GetProperty method takes a string identifying a property on the object and returns the value as an object. This string identifier consists of a namespace and some sort of property tag value. There are several namespaces that can be used, but the one used here is http://schemas.microsoft.com/mapi/proptag/. More information on referencing properties by namespace can be found in the MSDN article outrageously called Referencing Properties by Namespace.

Finding out the property tag value is next to impossible looking at the MSDN documentation. They simply don't document it, which I found incredibly frustrating. That is, until I found a copy of Outlook Spy. This is an excellent tool that allows you to browse the object model and also get access to the MAPI objects, including the elusive property tags!

Getting back to custom resource properties, I used Outlook Spy to examine one of my vehicle-type recipients. Under the AddressEntity property is a MAPIObject. If you "browse" this property, a window is displayed listing all of the properties of that MAPI object, including the property tag value, the type and its current value. On the right of the window is a field called DASL. This field is the value that you need to pass into the PropertyAccessor.GetProperty() method to extract its value. In my case, the property listing the custom resource properties was using the DASL http://schemas.microsoft.com/mapi/proptag/0x0806101E.

So, once you have this, the code is simple. The following example assumes you already have a Recipient object which is an Equipment resource with the custom property Vehicle.

public static bool IsVehicleResource(Recipient aRecipient)
{
bool result = false;

if (aRecipient.Type == (int)OlMeetingRecipientType.olResource)
{
try
{
//
// Get resource info property via MAPI property accessor.
// NOTE: this will throw an exception if it doesn't exist (ie: not a resource)
//
object resourceInfo = aRecipient.AddressEntry.PropertyAccessor.GetProperty(
"http://schemas.microsoft.com/mapi/proptag/0x0806101E");
//
// Split comma separated info into parts and look for information identifying
// the resource as Equipment and Vehicle.
//
string[] resourceDetails = resourceInfo.ToString().Split(',');
result = (resourceDetails.Contains("Equipment") && resourceDetails.Contains("Vehicle"));
}
catch (System.Exception ex)
{
// TODO: error handling
}
}

return result;
}

And that is it!

For more information on using the PropertyAccessor object, have a look at the MSDN documentation online.

Tuesday, November 27, 2007

Using LLBLGEN Generated Classes with Web Services

UPDATE: This only applies to version 2.0.

If you are using LLBLGEN with Web Services and you want to return entities and views to the client, you should have configured your machine to work according to the LLGBLGEN article titled Generated code - XML Webservices support.

This works nicely with Entity Classess, and probably Typed Lists (which I haven't used/tested yet), but there is a problem with Typed Views. If you have a Web Method that returns one of your Typed Views, you are probably getting errors generating the proxy classes, or the type specified in the proxy class that is generated does not match the Typed View in your Web Method!

There appears to be a bug in the webServiceHelper.template file that is used by the LLBLGEN generator. You can find this file in the following directory:

C:\Program Files\Solutions Design\LLBLGen Pro v2.0\Templates\SharedTemplates\Net2.x\C#

Open the file in a text editor and look for the following line in the "TypedView Classes" region:

return new XmlQualifiedName("<[CurrentTypedListName]>TypedList", namespaceToUse);

Change the above line to:

return new XmlQualifiedName("<[CurrentTypedViewName]>TypedView", namespaceToUse);

Now instead of having every one of your typed views with an XmlQualifiedName of TypedList, it is actually to the name of the class. Look in WebServiceHelper.cs (or WebServiceHelper.vb) to confirm this change is working.

I generally find that these changes only affect the proxy generation when the service reference is recreated; updating the reference doesn't always work.