Tuesday, December 25, 2007

Monday, December 24, 2007

Free ASP.NET Hosting

Finally, I found some good Free ASP.NET Webhosting: Quantasoft (Spain).

The free hosting plan includes 50MB Disk space, ASP.NET 2.0 and Sql Express.

Haven't done heavy programming on it, but the simple ASP.NET stuff (in my case, uploading documents and write/read a sql express database) for the simple sites work, so I'm happy ;-)

Thursday, December 20, 2007

Sharepoint: Force Expiry Policy Timer job to run

To test your custom expiry policy, you have to force the Expiry Policy Timer job to run. I found this very useful posting:

http://blogs.msdn.com/mattlind/archive/2007/06/05/force-execution-of-expiration-policies-in-moss.aspx

Sunday, December 16, 2007

SharePoint: Create and add a Policy to a content type programmatically

I had to add a custom action to the Sharepoint expiry policy of a content type.

How to make a custom action, and add it to a policy in the Sharepoint configuration screen of the content type is not so hard - see http://jack.whyyoung.com/blog/www-sharepointblogs-com-MainFeed-aspx-GroupID-3/19732-aspx.htm for this.

But to add this policy to a content type automatically - in code int the feature event receiver of this content type - I had to search a little bit harder..

Use the Policy (in namespace Microsoft.Office.RecordsManagement.InformationPolicy) object (do not use the SPPolicy class, that's for other purposes :) ) to add the expiration policy programmatically to the content type. Here is the code:

using (SPSite site = (SPSite)properties.Feature.Parent)
            {
                string policyFeatureId = "Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration";
                SPContentType administrativeDocumentContentType = site.RootWeb.ContentTypes[new SPContentTypeId("0x01010091C4CA4E2BA24AE9BD4F276750C0A5A9")];

                //Add the custom action "AdministrativeDocumentExpirationSendEmail" to the policy resource collection
                string actionmanifest = @"<?xml version=""1.0"" encoding=""utf-8"" ?><p:PolicyResource id=""Dolmen.SharePoint.Customer.ExpirationActions.AdministrativeDocumentExpirationSendEmail"" featureId=""Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration"" type=""Action"" xmlns:p=""urn:schemas-microsoft-com:office:server:policy""><p:LocalizationResources>dlccore</p:LocalizationResources><p:Name>AdministrativeDocumentExpirationSendEmail</p:Name><p:Description>Sends a mail on the Expiration date</p:Description><p:Publisher>Dolmen Computer Applications</p:Publisher><p:AssemblyName>Dolmen.SharePoint.Customer.ExpirationActions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=79b87b017c9b0654</p:AssemblyName><p:ClassName>Dolmen.SharePoint.Customer.ExpirationActions.AdministrativeDocumentExpirationSendEmail</p:ClassName></p:PolicyResource>";
                //string actionmanifest = System.IO.File.ReadAllText("actionmanifest.xml");
                PolicyResourceCollection.Add(actionmanifest);

                if (Policy.GetPolicy(administrativeDocumentContentType) == null)
                {
                    //if the content type hasn't got a Policy yet, create a new Policy
                    Policy.CreatePolicy(administrativeDocumentContentType, null);
                }

                Policy policyOfContentType = Policy.GetPolicy(administrativeDocumentContentType);
                policyOfContentType.Name = "Administrative Document - Expiration Policy";
                //Add expiration policy to the content type
                if (policyOfContentType.Items[policyFeatureId] == null)
                {
                    string customData = @"<data><formula id=""Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.Formula.BuiltIn""><number>0</number><property>Expiration</property><period>days</period></formula><action type=""action"" id=""Dolmen.SharePoint.Customer.ExpirationActions.AdministrativeDocumentExpirationSendEmail"" /></data>";

                    policyOfContentType.Items.Add(policyFeatureId, customData);
                }
            }

Tip: to get the customData and the policyFeatureId you can create a policy with the standard Sharepoint configuration screen and read it out in a console application using following code:

SPContentType administrativeDocumentContentType = site.RootWeb.ContentTypes[new SPContentTypeId("0x01010091C4CA4E2BA24AE9BD4F276750C0A5A9")];

                Policy policy = Policy.GetPolicy(administrativeDocumentContentType);

                foreach (PolicyItem item in policy.Items) {
                    Console.WriteLine("Custom data: " + item.CustomData + "\n policy feature id: " + item.Id);
                }

Wednesday, November 21, 2007

Set custom properties of a custom field in List Definition

Problem:

I made a custom field, named "CrossSiteLookupFilterFieldControl". This field has some properties:

...

<PropertySchema>

<Fields>

<Field Name="SelectedSite" DisplayName="Site" Type="Text" Hidden="TRUE" />
<Field Name="SelectedList" DisplayName="List" Type="Text" Hidden="TRUE" />
<Field Name="SelectedColumn" DisplayName="Column" Type="Text" Hidden="TRUE" />
<Field Name="FilterValue" DisplayName="Filter value" Type="Text" Hidden="TRUE" />
<Field Name="FilterQuery" DisplayName="Filter query" Type="Text" Hidden="TRUE" />

</Fields>

</PropertySchema>
...

I want to use this field in a Custom List, so I add the following to schema.xml of my List:

<Field ID="{222EF3E9-3470-4619-89EC-7FFCDA18A3FC}" Name="Segment"  SourceID="{F9C3BB43-1EAA-4ac1-8878-EDBD7AFF3B4C}" StaticName="Segment"  Type="CrossSiteLookupFilterFieldControl" DisplayName="Segment" />

This works. But if I want to add a value for the FilterQuery property of the field, something like this doesn't work automatically:

<Field ID="{222EF3E9-3470-4619-89EC-7FFCDA18A3FC}" FilterQuery="Test" Name="Segment"  SourceID="{F9C3BB43-1EAA-4ac1-8878-EDBD7AFF3B4C}" StaticName="Segment"  Type="CrossSiteLookupFilterFieldControl" DisplayName="Segment" />

Solution

In the constructor of your custom field, you can read out the SchemaXml, and find the desired attributes. This way, you can set the values of your custom field with the values in the attributes:

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(this.SchemaXml);
XmlAttributeCollection fieldAttributes = xmlDoc.FirstChild.Attributes;

if (fieldAttributes["FilterQuery"] != null)
                this.FilterQuery = fieldAttributes["FilterQuery"].Value;

 

PS: More about custom field definitions later..

Tuesday, November 13, 2007

Upload an InfoPath attachment to a document library

To copy a file attachment in an InfoPath form to a document library, I used this code. The "workfiche" object is an instance of a class generated by the XML Class Generator. For more information about this tool, go to http://www.canerten.com/xml-c-class-generator-for-c-using-xsd-for-deserialization/

byte[] attachFile = workfiche.Vlerick_TP_GeneralInformation.Brochure.AttachDraftText;

//get filename
int namebufferlen = attachFile[20] * 2;
byte[] filenameBuffer = new byte[namebufferlen];
for (int i = 0; i < filenameBuffer.Length; i++)
{
          filenameBuffer[i] = attachFile[24 + i];
}
char[] asciiChars = UnicodeEncoding.Unicode.GetChars(filenameBuffer);
string filename = new string(asciiChars);

filename = filename.Substring(0, filename.Length - 1);

//upload to Input Documents doc library

SPFolder inputDocumentsList = web.GetFolder("InputDocuments");

inputDocumentsList.Files.Add(filename, attachFile);

Sharepoint: Programmatically set an alert on a task list for a User

This code adds an alert for all users in a site, with a filter: The task has to be assigned to the user, the status has to be Completed and the Start date has to be less than "today". In other words: the active tasks :-)

foreach (SPUser user in newWeb.SiteUsers)
{
SPAlert alert = newWeb.Alerts.Add();

alert.Filter = "<Query><And><And><Eq><FieldRef Name=\"AssignedTo\"/><Value type=\"string\">" + user.LoginName + "</Value></Eq><Neq><FieldRef Name=\"Status\"/><Value type=\"string\">completed</Value></Neq></And><Leq><FieldRef Name=\"StartDate\"/><Value type=\"datetime\"><Today/></Value></Leq></And></Query>";

alert.User = user;
alert.AlertType = SPAlertType.List;
alert.List = newWeb.Lists["Tasks"];
alert.EventType = SPEventType.Modify;
alert.AlertFrequency = SPAlertFrequency.Immediate;
alert.Update();

}