Using SharePoint’s Event Receivers and Muhimbi to Convert a Document to PDF

In this blog post, I’ll explain how to use use The Muhimbi PDF Converter, along with SharePoint’s Event Receiver to convert MS-Word, Excel, PowerPoint, and other common file formats to PDF.

What is an Event Receiver?

The main functionality of an Event Receiver is to handle/respond to events when a user interacts with SharePoint items, such as files in a library. For example, the code in an event receiver can be triggered when a user adds or changes a file in a library.

Triggering’ actions for SharePoint’s Event Receiver include adding, updating, deleting, moving, checking-in/out, etc.


The Event Receivers are Classified as:

  • Synchronous Event Receiver: Synchronous Event Receivers are also known as Before Event Receivers as they fire before the corresponding event action occurs and before SharePoint has written any data to the content database.
  • Asynchronous Event Receiver: Asynchronous Event Receivers are known as After Event Receivers as they fire after SharePoint has written to the content database to commit the event action. After events do not support cancelling the event action.

Scenario\Use case:

  • We will setup an Event Reciever to trigger when a document is added to a document library.
  • The Event Receiver will convert the file to PDF and the PDF file will be stored in a different document library.

Before we Begin, Please Make Sure the Following Prerequisites are in Place:

  • Download the fully functional free trial of The Muhimbi PDF Converter Services here.
  • Please make sure The Muhimbi PDF Converter Services  is installed exactly as described in chapter 2 of the Administration Guide.  Please follow that guide to the letter and make sure you pay particular good attention to the section about ‘dependencies’.  The Administration Guide is included in the download and available on-line here.
  • You must have installed Visual Studio and a supported edition of Windows and SharePoint.

Now that we Understand the Basics of the Event Listener and we also have our Prerequisites in place, lets start with Configuring the Event Listener:

Step 1 : Setting up your SharePoint Event Reciever.

  • Create New Project in Visual Studio of type ‘SharePoint 2016 – Empty Project’.


SharePoint 
All languages 
No exact matches found 
All platforms 
Clear all 
Service 
Other results based on your search 
SharePoint 2016 - Empty Project 
An empty project for creating a SharePoint 2016 application. 
C# Windows Office


  • Give you Project and Solution a meaningful name.


Configure your new project 
SharePoint 2016 - Empty Project c• CHQ 
Project me 
Mu hi m b iCO 
Location 
Solution name O 
MuhimbiConvertToPdf 
Place solution %Oject in the same directory 
.NET Framework 47.2


  • Add the‘SharePoint Site’ you want to use for debugging and ‘Deploy as a farm solution‘.


ShareA2int Customization Wizard 
Specify the site and security level for debugging 
What site do you want to use for debugging? 
What is the trust level for this Sharepoint solution? 
o 
Deploy as a sandboxed solution 
Validate 
Clicking this option causes the solution to be deployed as a Sandboxed solution. Sandboxed 
solutions can be deployed by the site collection owtkr and are run in a secure, monitored process 
that has limited resource access. 
Note: Share*'int 2019 does not support Code-Based Saru:ibox Solutions 
@ Deploy as a farm solution 
Clicking this option means that users must have ShareR)int administrator privileges to run or deploy 
Finish 
Cancel


  • Right click on your project and Add new item of type ‘Event Receiver’.


Add New Item - MuhimbiConvertTOPdf 
Installed 
Visual Items 
Web 
SQL Server 
Storm I tems 
Office/SharePoint 
Windows Forms 
Sort bye. Default 
6) 
Visual Web Part 
Visual Items 
Visual Web Part (Farm.„ Visual Items 
Visual Items 
Visual C# Items 
Event Receiver 
Visual C# Items 
Visual Items 
Visual Items 
Custom 
Visual Items 
Search (Ctrl•E) 
Type: Visual Items 
An event receiver item, Which 
to handle SharePoint events. 
General 
Online 
Name; 
ConvertTO


  • Select the type of Event you want and what type of event you require. For the purposes of this demo, we can use ‘An item was added‘.



  • Once you click on the Finish button, you will be redirected to the code view with base class created automatically.


	using System;
	using System.Security.Permissions;
	using Microsoft.SharePoint;
	using Microsoft.SharePoint.Utilities;
	using Microsoft.SharePoint.Workflow;
	
	namespace MuhimbiConvertToPdf.ConvertToPdf
	{
	    /// <summary>
	    /// List Item Events
	    /// </summary>
	    public class ConvertToPdf : SPItemEventReceiver
	    {
	        /// <summary>
	        /// An item was added.
	        /// </summary>
	        public override void ItemAdded(SPItemEventProperties properties)
	        {
	            base.ItemAdded(properties);
	        }
	    }
	}

  • Open the Element.xml file and update it to point it to a particular ‘ListUrl‘, so that it points a particular document library.


<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Receivers ListUrl="Shared%20Documents">
      <Receiver>
        <Name>ConvertToPdfItemAdded</Name>
        <Type>ItemAdded</Type>
        <Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
        <Class>MuhimbiConvertToPdf.ConvertToPdf.ConvertToPdf</Class>
        <SequenceNumber>10000</SequenceNumber>
      </Receiver>
  </Receivers>
</Elements>


Step 2:  Converting Office files to PDF Format using a Web Services based interface.

Assuming that we have installed and configured Muhimbi Converter Service lets get started with Integrating the Web Service with our Event Listener.

  • In the Solution Explorer window, right-click References and select ‘Add Service Reference‘.
  • In the Address box enter the WSDL address “http://localhost:41734/Muhimbi.DocumentConverter.WebService/?wsdl“. If the Conversion Service is located on a different machine then substitute localhost with the server’s name
  • Accept the default Namespace of ServiceReference1 and click the OK button to generate the proxy classes.
  • Replace the content of the entire code file with the following:


using System;
using System.IO;
using System.Security.Permissions;
using System.ServiceModel;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using MuhimbiConvertToPdf.ServiceReference1;

namespace MuhimbiConvertToPdf.ConvertToPdf
{
    /// <summary>
    /// List Item Events
    /// </summary>
    public class ConvertToPdf : SPItemEventReceiver
    {
        string SERVICE_URL = "http://localhost:41734/Muhimbi.DocumentConverter.WebService/";
        /// <summary>
        /// An item was added.
        /// </summary>
        public override void ItemAdded(SPItemEventProperties properties)
        {
            base.ItemAdded(properties);
            using (SPWeb web = properties.OpenWeb())              
            {
                try
                {
                    SPListItem currentItem = properties.ListItem;
                    
                    SPFile file = currentItem.File;
                    string sourceFileName = Convert.ToString(currentItem["Name"]);
                    
                    byte[] ConvFile = ConvertLogic(file);
                    if (ConvFile != null)
                    {
                        //upload merged file to document library
                        SPFolder myLibrary = web.Folders[web.ServerRelativeUrl.TrimEnd('/') + "/TestLibrary/"];
                        SPFile spfile = myLibrary.Files.Add(currentItem["BaseName"] + ".pdf", ConvFile, true);
                        // Commit 
                        myLibrary.Update();
                    }
                }
                catch (Exception ex)
                {
                }
            }
        }

        public byte[] ConvertLogic(SPFile file)
        {
            DocumentConverterServiceClient client = null;
            byte[] convFile = null;
            try
            {
                // ** Determine the source file and read it into a byte array.   
                byte[] sourceFile = file.OpenBinary();

                // ** Open the service and configure the bindings
                client = OpenService(SERVICE_URL);

                //** Set the absolute minimum open options
                OpenOptions openOptions = new OpenOptions();
                openOptions.OriginalFileName = Path.GetFileName(file.Name);
                openOptions.FileExtension = Path.GetExtension(file.Name);

                // ** Set the absolute minimum conversion settings.
                ConversionSettings conversionSettings = new ConversionSettings();
                conversionSettings.Fidelity = ConversionFidelities.Full;
                conversionSettings.Quality = ConversionQuality.OptimizeForPrint;

                // ** Carry out the conversion.
                convFile = client.Convert(sourceFile, openOptions, conversionSettings);
            }
            catch (FaultException<WebServiceFaultException> ex)
            {
            }
            finally
            {
                CloseService(client);
            }
            return convFile;
        }
        public static DocumentConverterServiceClient OpenService(string address)
        {
            DocumentConverterServiceClient client = null;

            try
            {
                BasicHttpBinding binding = new BasicHttpBinding();
                // ** Use standard Windows Security.
                binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
                binding.Security.Transport.ClientCredentialType =
                                                            HttpClientCredentialType.Windows;
                // ** Increase the Timeout to deal with (very) long running requests.
                binding.SendTimeout = TimeSpan.FromMinutes(30);
                binding.ReceiveTimeout = TimeSpan.FromMinutes(30);
                // ** Set the maximum document size to 40MB
                binding.MaxReceivedMessageSize = 50 * 1024 * 1024;
                binding.ReaderQuotas.MaxArrayLength = 50 * 1024 * 1024;
                binding.ReaderQuotas.MaxStringContentLength = 50 * 1024 * 1024;

                // ** Specify an identity (any identity) in order to get it past .net3.5 sp1
                EndpointIdentity epi = EndpointIdentity.CreateUpnIdentity("unknown");
                EndpointAddress epa = new EndpointAddress(new Uri(address), epi);

                client = new DocumentConverterServiceClient(binding, epa);

                client.Open();

                return client;
            }
            catch (Exception)
            {
                CloseService(client);
                throw;
            }
        }

        /// <summary>
        /// Check if the client is open and then close it.
        /// </summary>
        /// <param name="client">The client to close</param>
        public static void CloseService(DocumentConverterServiceClient client)
        {
            if (client != null && client.State == CommunicationState.Opened)
                client.Close();
        }
    }

}


Providing the project is named per the steps above, it should build without errors. Deploy it, upload a source file, e.g. an MS-Word document to the ‘Shared Documents’ library and after a few seconds a file will be created in the ‘TestLibrary‘.

In the above example I have hard code the Destination document Library, you can change it to be inline with your requirements.



Subscribe to this blog for the latest updates about SharePoint Online, Power Automate (Microsoft Flow), Power Apps and document conversion and manipulation using The PDF Converter.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s