Category Archives: DMS

SSL and Send To Locations

When you are using SharePoint in combination with SSL and Send To locations you have to register you certificate with SharePoint when you would like to register a Send To location that runs under a https address.

When you try to add the location you will receive the following error:

Verification failed: URL is not a valid routing destination.

You will also find a entry within your event viewer which let you see what certificate you need to register:

Log Name:           Application
Source:               Microsoft-SharePoint Products-SharePoint Foundation
Date:                  5/02/2011 16:83:51 PM
Event ID:            8311
Task Category:   Topology
Level:                 Error
Keywords:
User:                  Development\svc_spfarm
Computer:          Diablo.development.com 
Description:
An operation failed because the following certificate has validation errors:\n\nSubject Name: CN=intra.development.com, OU=IT, O=Development, L=Diablo, S=NC, C=US\nIssuer Name: CN=Development-Diablo-CA, DC=Development, DC=com\nThumbprint: 3ACA9260547711E0B9C08CEADFD72085\n\nErrors:\n\n The root of the certificate chain is not a trusted root authority

 

This states that you will have to register your certificate you can register your certificate by using PowerShell:

Add-PSSnapin Microsoft.SharePoint.PowerShell 

$rootca = New-Object System.Security.Cryptography.x509Certificates.x509Certificate2("[Your Certificate]") 

New-SPTrustedRootAuthority –Name "[Certificate Name]" –Certificate $rootca 

Tanx to: http://blogs.technet.com/b/blairb/archive/2010/08/18/using-ssl-with-sharepoint-2010-send-to-connections.aspx

Re-Submitting files with the Content Organizer (Submitting files through code)

About a week ago I wrote an article about the “Content Organizer” feature of SharePoint 2010.

The “Content Organizer” feature makes it possible to route all kind of different information within your SharePoint site. If you want to read more about this feature click here.

In certain scenarios you would like to be able to re-submit documents when certain metadata of that document is changed. Out of the box this isn’t possible this means you will have to create a custom solution.

What you can do is create a list settings page that you will have to register on document libraries.

With this page you can enable the re-submitting feature and select the fields that have to be changed if the file needs to be re-submitted.

If you enable the re-submitting feature on the page it will install an event receiver on the current list. This event receiver will run on the ItemUpdated event. In the ItemUpdated event you can then check which fields are changed and then send the document for re-routing.

I hear you asking how can I submit a file for routing. Let’s take a look at the ItemUpdated receiver I have written.

/// <summary>
/// An item is being updated.
/// </summary>
public override void ItemUpdated(SPItemEventProperties properties)
{
    base.ItemUpdated(properties);

    if (CheckForReRouteItem(properties))
    {
        if (ReRoutItem(properties))
        {
            properties.ListItem.Delete();
        }
    }
}

This code will be executed by the event Receiver. The method Check ForReRouteItem will check if certain fields were changed.

private bool CheckForReRouteItem(SPItemEventProperties properties)
{
    List<string> changesFields = GetField(properties);

    foreach (string field in changesFields)
    {
        if (properties.AfterProperties[field] != properties.BeforeProperties[field])
        {
            return true;
        }
    }

    return false;
}

In the above method the fields for which we have to check if they are changed are retrieved by another method called GetFields(properties). This method will retrieve the fields that are saved in the property bag by the list settings page.

If a field is changed the method will return true to indicate that the files needs to be submitted to the Content Organizer.

private bool ReRoutItem(SPItemEventProperties properties)
{
    Guid webId = properties.Web.ID;
    Guid siteId = properties.SiteId;
    bool retVal = false;

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        using (SPSite site = new SPSite(siteId))
        {
            using (SPWeb web = site.OpenWeb(webId))
            {
                SPFile file = properties.ListItem.File;
                string fileType = properties.ListItem.ContentType.Name;
                SPFieldCollection fields = file.Item.Fields;
                List<RecordsRepositoryProperty> itemProperties = new List<RecordsRepositoryProperty>();

                foreach (SPField spField in fields)
                {
                    try
                    {
                        string fieldValue = file.Item[spField.Id] != null ? file.Item[spField.Id].ToString() : string.Empty;
                        string value = spField.GetFieldValue(fieldValue) as string;
                        RecordsRepositoryProperty property = new RecordsRepositoryProperty
                        {
                            Name = spField.Title,
                            Type = spField.TypeAsString,
                            Value = value
                        };
                        itemProperties.Add(property);
                    }
                    catch (ArgumentException) { }
                }

                string result = string.Empty;
                OfficialFileResult outcome = OfficialFileCore.SubmitFile(properties.Web, file.OpenBinary(), itemProperties.ToArray(), fileType, file.Web.Url + file.Url, out result);
                if (outcome == OfficialFileResult.Success)
                {
                    retVal = true;
                }
            }
        }
    });

    return retVal;
}

The above method performs the actual submitting of the file to the Content Organizer by calling OfficialFileCore.SubmitFile().

This method will return an OfficialFileResult to indicate whether the submitting was successful of not.

Important: With submitting the file we had a problem because it was giving us an outcome of NotFound every time we submitted the file. After debugging the SharePoint dlls we found out that Microsoft performs the following method EcmDocumentRoutingWeb.IsSubmitter(web)):

internal static bool IsSubmitter(SPWeb web)
{
    if (web == null)
    {
        return false;
    }
    bool flag = false;
    try
    {
        string str = web.Properties["_dlc_RepositoryUsersGroup"];
        if (!string.IsNullOrEmpty(str))
        {
            flag = web.IsCurrentUserMemberOfGroup(int.Parse(str, NumberFormatInfo.InvariantInfo));
        }
    }
    catch (FileNotFoundException exception)
    {
        ULS.SendTraceTag(0x636d7539, ULSCat.msoulscat_DLC_Routing, ULSTraceLevel.Medium, "Routing Engine: User does not have permissions to submit to this site. Exception: {0}", new object[] { exception.Message });
        flag = false;
    }
    return flag;
}

In this method Microsoft checks if the current user is in a specific group to allow the submission of the file. If you are not in this group Microsoft will return an outcome of NotFound.

I hope this post will help you guys develop cool SharePoint solutions.

SharePoint 2010 Content Organizer Feature

Within SharePoint 2010 Microsoft has changed a lot of the content management features. One of those features is content routing which you can do with the Content Organizer Feature.

When you activate the Content Organizer feature on your site (Web scoped feature). It will automatically create a Drop-off library for you.

ContentOrganizerFeature

All the documents that you upload to the site will be uploaded to the Drop-off library and that library will then route you document to the correct library or folder.

Settings

SettingsThe settings for the content organizing can be changed by using two web settings features that can be found under the category “Site Administration” on the “Site Settings” screen.

With the option “Content Organizer Rules” you can specify specific rules to route you content within the Site or outside your site collection.

When you want your content to be routed outside your site collection the other site were you want the content to move to also has to have the “Content Organizer” feature enabled.

Besides that you will have to enable the option “Sending to another site” within the “Content Organizer Settings”

image

After you have enabled this option you also have to specify the site were the content has to be routed to as a sent to location within central administration. This can be done by following these steps:

  1. Navigate to “Central Administration”
  2. Click on “General Application Settings”
  3. And then click on “Configure send to connections”

Send-To-Locaiton

On the screen that appears you can specify your sent to location.

If you specify a rule that routes a document to another site collection the document will be placed into the drop-off library of the destination site collection.

The document does get routed to a certain place directly but will be prosed by a Timer job. This timer job is scheduled ones a day. You can find this timer job by following these steps:

  1. Navigate to “Central Administration”
  2. Click on “Monitoring”
  3. Click on “Review Job Definitions” under the category “Timer Jobs”
  4. Then find the “Content Organizer Processing” Job specified for you web application.

Organizer

By clicking the name of the job you can reschedule the job to run within another time frame. Besides that you can also click the “Run now” button.

Routing Documents and Workflows

When you route documents to a document library on which you have connected workflows, those workflows will not start automatically. If you take a look in the ULS log you will find a message like this:

“Declarative workflows cannot automatically start if the triggering action was performed by System Account. Cancelling workflow auto-start.”

It is said that Microsoft knows this bug so lets hope the will fix it in some kind of service pack.

So what can you do about this issue. You will have to create a Item event receiver on the list that will start the workflow associations of the list item:

public override void ItemAdded(SPItemEventProperties properties)
{
    SPListItem addedItem = properties.ListItem;
    SPWorkflowManager manager = addedItem.ParentList.ParentWeb.Site.WorkflowManager;
    SPWorkflowAssociationCollection assoCollection = addedItem.ContentType.WorkflowAssociations;

    foreach (SPWorkflowAssociation asso in assoCollection)
    {
        manager.StartWorkflow(addedItem, asso, "");
    }

    base.ItemAdded(properties);
}

Custom routing

To be more flexible with the routing of your documents you can also create a custom router. I will discuss this option in a later post if there are enough people that will want to here about it.