Reference Guide
Tutorials / Other Technologies / SharePoint / Integrating DocuVieware into SharePoint 2019
In This Topic
    Integrating DocuVieware into SharePoint 2019
    In This Topic

    1. Introduction

    For this tutorial, we chose to make an App-in instead of a SharePoint solution.

    A SharePoint App-in has many advantages compared to farm solutions when you consider the safety, scaling, and integration of the deployment environment.

    Here are some important notes regarding SharePoint Apps when compared with SharePoint solutions:

    Prerequisites

    For creating the SharePoint application we used these tools:

    Also, we used a SharePoint 2019 solution host in an Azure cloud environment.

    2. Create your application

    First of all, you’ll need to add the “Office Developer Tools for Visual Studio” component using the Visual Studio installer to make the add-in application work:

    Then, we need to create our app.

    → Launch Visual Studio

    → “Create a new project”

    → “SharePoint add-in” (C#)

    → Configure the projects

    → Click on “Create”

    → Specify your SharePoint Add-in settings

    Information:

    Provider-hosted: hosts the app externally from SharePoint and uses all the options available with the Client-Side Object Model.

    SharePoint-hosted: hosts the app within SharePoint and uses the JavaScript Client-Side Object Model.

    → Type your login/password for the SharePoint server

    → Choose “ASP.NET MVC Web Application”

    → You need to set the STS certificate location’s field, the path where the created certificate is. You can learn how to create/replace the certificate here: Replace the STS certificate for SharePoint Server - SharePoint Server

    You also need to type your password and your Issuer ID (creator’s ID).

    → Click on “Finish”

    Your App-in is generated!

    3. SharePoint configuration

    To declare an application in SharePoint, you should create an App Catalog Site Collection.

    Check out the Microsoft documentation for this step.

    To deploy your application from Visual Studio to SharePoint, you need to link the two of them.

    You can deploy or publish solutions to a local SharePoint server on your development computer. The deployment process copies the .wsp file to the SharePoint server, installs the solution, and then activates the features. The publishing process only copies the .wsp file to the server and installs it. You must manually activate it to enable it in SharePoint.

    By following the MSDN documentation you’ll be able to have a well-implemented solution in your SharePoint environment:

    Developing SharePoint Solutions - Visual Studio

    Set up a general development environment for SharePoint

    Here is the environment we used to develop our solution:

    4. DocuVieware integration

    For the DocuVieware integration, it is pretty similar to the other implementations.

    You also need to set your Global.asax for:

    Global.asax

        
    public class MvcApplication : HttpApplication
        {
            public const int SESSION_TIMEOUT = 20; 
            private const bool STICKY_SESSION = true; 
            private const DocuViewareSessionStateMode DOCUVIEWARE_SESSION_STATE_MODE = DocuViewareSessionStateMode.InProc; 
     
            public static string GetCacheDirectory()
            {
                return HttpRuntime.AppDomainAppPath + "\\Cache";
            }
     
            protected void Application_Start()
            {
                try
                {
                    Assembly.Load("GdPicture.NET.14.WEB.DocuVieware");
                }
                catch (System.IO.FileNotFoundException)
                {
                    throw new System.IO.FileNotFoundException(" The system cannot find the DocuVieware assembly. Please set the Copy Local Property of the GdPicture.NET.14.WEB.DocuVieware reference to true. More information: https://msdn.microsoft.com/en-us/library/t1zz5y8c(v=vs.100).aspx");
                }
     
                DocuViewareLicensing.RegisterKEY("YOUR_API_KEY"); 
                DocuViewareManager.SetupConfiguration(STICKY_SESSION, DOCUVIEWARE_SESSION_STATE_MODE, GetCacheDirectory());
     
                AreaRegistration.RegisterAllAreas();
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
            }
        }
    
    

    Once the assembly is well implemented, we now add the javascript client library.

    For this, you’ll need to add these files:

    Now it’s time to reference it in the code. There are two different ways to do it.

    Implement it into the BundleConfig like this:

        
    public class BundleConfig
        {
            public static void RegisterBundles(BundleCollection bundles)
            {
                bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                            "~/Scripts/jquery-{version}.js"));
     
                bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                          "~/Scripts/bootstrap.min.js"));
     
    bundles.Add(new ScriptBundle("~/bundles/docuvieware").Include(
                          "~/Scripts/docuvieware-min.js"));
     
                bundles.Add(new ScriptBundle("~/bundles/spcontext").Include(
                            "~/Scripts/spcontext.js"));
     
                bundles.Add(new StyleBundle("~/Content/css").Include(
                          "~/Content/bootstrap.min.css"));
     
                bundles.Add(new StyleBundle("~/Content/css").Include(
                          "~/Content/docuvieware-min.css"));
     
            }
    
    

    Or you can also implement it in the cshtml main page:

    DisplayDocument.cshtml

        
    <head>
        <title>DocuVieware - SharePoint Documents Reading Made Simple</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link href="~/Content/docuvieware-min.css" rel="stylesheet" type="text/css" />
        <script src="~/Scripts/docuvieware-min.js"></script>
        <script src="https://code.jquery.com/jquery-3.5.1.min.js"
                crossorigin="anonymous"></script>
    </head>
    
    

    We also need to declare our client ID in the application to make the communication work well.

    Set the Client ID into the AppRegNew.aspx at <site_url>/_layouts/15/AppRegNew.aspx

    After this, declare the ClientID on our AppManifest.xml :

    Now we can declare our <remotewebapplication> with our ClientID.

    AppManifest.xml

    <Properties> <Title>DocuVieware DEMO</Title> <StartPage>~remoteAppUrl/?{StandardTokens}</StartPage> </Properties> <AppPrincipal> <RemoteWebApplication ClientId="YOUR_CLIENT_ID" /> </AppPrincipal> <AppPermissionRequests AllowAppOnlyPolicy="true"> <AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web/list" Right="FullControl" /> <AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web" Right="FullControl" /> <AppPermissionRequest Scope="http://sharepoint/projectserver" Right="Manage" /> </AppPermissionRequests> <RemoteEndpoints> <RemoteEndpoint Url="https://sps/" /> </RemoteEndpoints>

    Let’s finish the configuration with one of the most specific requirements.

    To create a plugged .NET application to SharePoint, you’ll need to set a security certificate for the communication between SharePoint and your add-in.

    In the TokenHelper.cs file, you’ll need to set the username, the password, and the domain name to make the demo work.

    This information is used by SharePoint only to generate a temporary security token to enable the POST request between the application and the SharePoint server.

    Here is the specific line for creating a token and giving the client app the authorization to communicate with the SharePoint server with the POST method:

    TokenHelper.cs

    public static ClientContext GetClientContextWithAccessToken(string targetUrl, string accessToken) { ClientContext clientContext = new ClientContext(targetUrl) { AuthenticationMode = ClientAuthenticationMode.Anonymous, FormDigestHandlingEnabled = false }; CredentialCache myCache = new CredentialCache(); myCache.Add(new Uri(clientContext.Url), "NTLM", new NetworkCredential("sharepoint_demo", "Sharepoint2019", "SHAREPOINT")); clientContext.Credentials = myCache; var dig = clientContext.GetFormDigestDirect().DigestValue; clientContext.ExecutingWebRequest += delegate(object oSender, WebRequestEventArgs webRequestEventArgs) { webRequestEventArgs.WebRequestExecutor.WebRequest.PreAuthenticate = true; webRequestEventArgs.WebRequestExecutor.WebRequest.KeepAlive = true; webRequestEventArgs.WebRequestExecutor.WebRequest.UnsafeAuthenticatedConnectionSharing = true; webRequestEventArgs.WebRequestExecutor.WebRequest.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f"); webRequestEventArgs.WebRequestExecutor.WebRequest.Headers[/fusion_text][/fusion_builder_column][/fusion_builder_row][/fusion_builder_container][fusion_builder_container hundred_percent="yes" overflow="visible" type="legacy"][fusion_builder_row][fusion_builder_column type="1_1" layout="1_1" background_position="left top" background_color="" border_color="" border_style="solid" spacing="yes" background_image="" background_repeat="no-repeat" padding_top="" padding_right="" padding_bottom="" padding_left="" margin_top="0px" margin_bottom="0px" class="" id="" animation_type="" animation_speed="0.3" animation_direction="left" hide_on_mobile="no" center_content="no" min_height="none" align_self="flex-start" border_sizes_undefined="" first="true" last="true" hover_type="none" link="" border_position="all" type="1_1"][fusion_text]["Authorization"] = "Bearer " + accessToken; if (webRequestEventArgs.WebRequestExecutor.WebRequest.Method == "POST" && !webRequestEventArgs.WebRequestExecutor.WebRequest.Headers.AllKeys.Contains("X-RequestDigest")) { webRequestEventArgs.WebRequestExecutor.WebRequest.Headers.Add("X-RequestDigest", dig); } }; return clientContext; }

    5. Let’s code!

    For this article, we chose to show you a custom development which will be very useful, the save on the server.

    First of all, we need to declare our files to SharePoint, so it will know where it can take the files for the save. This part is written into the web.config, we declared it as “defaultFolder” and set its path.

    Warning: This way of setting the defaultFolder is demonstration purposes only and not production due to security issues.

    Web.config

        
    <configuration>
      <appSettings>
        <add key="webpages:Version" value="3.0.0.0" />
        <add key="webpages:Enabled" value="false" />
        <add key="ClientValidationEnabled" value="true" />
        <add key="UnobtrusiveJavaScriptEnabled" value="true" />
        <add key="ClientId" value="YOUR_CLIENT_ID" />
        <add key="ClientSecret" value="YOUR_CLIENT_SECRET" />
        <add key="ClientSigningCertificatePath" value="C:\certs\sharepointaddin_cert.pfx" />
        <add key="ClientSigningCertificatePassword" value="YOUR_SERVER_PASSWORD" />
        <add key="IssuerId" value="YOUR_USER_ID" />
        <add key="defaultFolder" value="/sites/invoices/Shared documents" />
      </appSettings>
    
    

    Let’s implement the call method on our main page:

    DisplayDocument.cshtml

        
    <body style="overflow: hidden; margin: 0; height: 100%">
        @{
            Model.Control.RenderControl(Output);
            Model.Control.Dispose();
        }
     
        <script>
            function SaveOnSharePoint() {
                $.post(
                    `SaveToSharepoint${window.location.search}`,
                    { documentId: "@Model.DocumentId.ToString()", dvSessionId: "@sessionId" },
                    (data) => DocuViewareAPI.DisplayMessageBox("@Model.Control.ID" , {
                        text: data.Message,
                        icon: data.Status === 1 ? 16 : 128
                    }),
                    "json")
            }
        </script>
    </body>
    
    
    

    SharePointContextFilterAttribute.cs

        
    public class SharePointContextFilterAttribute : ActionFilterAttribute
        {
            public override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                if (filterContext == null)
                {
                    throw new ArgumentNullException("filterContext");
                }
     
                Uri redirectUrl;
                switch (SharePointContextProvider.CheckRedirectionStatus(filterContext.HttpContext, out redirectUrl))
                {
                    case RedirectionStatus.Ok:
                        return;
                    case RedirectionStatus.ShouldRedirect:
                        filterContext.Result = new RedirectResult(redirectUrl.AbsoluteUri);
                        break;
                    case RedirectionStatus.CanNotRedirect:
                        filterContext.Result = new ViewResult { ViewName = "Error" };
                        break;
                }
            }
        }
    
    

    The SharePointContext.cs file is a class generated by Visual Studio when it links the SharePoint with the MVC projects.

    For this part, we have a special context (our development environment was out of the AD) and we modified the auto-generated classes (TokenHelper.cs and SharePointContext.cs) to make the project work in our environment.

    If you face some issues (like a 401 error on the POST request to the SharePoint server), you will find the modifications we added in the SharePoint sample delivered with our SDK on your computer’s main drive.

    Let us know if you have any questions, and we’ll be happy to help!