Introduction
In this article, we will see how to get the document(s) from DocuSign using envelope id, store it to a local directory, and list and download in the web application view. Please take a look at my previous articles for basic account creation, integration, validation, and creation of a signature request on a document, storing the envelope information, sign on a document and track envelopes within our application.
Let's move forward to get and download the document(s) for respective envelopes.
Prerequisites
- Visual Studio
- Basic knowledge of ASP.NET MVC
- Basic knowledge of C#
- Should have an account on DocuSign
Article Flow
- Get document(s) using Envelop id and Store document(s) to Local Directory
- List document(s) in view
- Download document(s)
Get document(s) using Envelope id and Store document(s) to Local Directory
In the last article, we have seen how to view the document using mailbox or DocuSign portal. Now, let's try to get the document from DocuSign to our application. We can get the documents using a DocuSign account and recipient envelope id. In the below code, we are getting an account id by passing the DocuSign credentials.
- public string loginApi(string usr, string pwd) {
-
- ApiClient apiClient = Configuration.Default.ApiClient;
- string authHeader = "{\"Username\":\"" + usr + "\", \"Password\":\"" + pwd + "\", \"IntegratorKey\":\"" + INTEGRATOR_KEY + "\"}";
- Configuration.Default.AddDefaultHeader("X-DocuSign-Authentication", authHeader);
-
- string accountId = null;
-
- AuthenticationApi authApi = new AuthenticationApi();
- LoginInformation loginInfo = authApi.Login();
-
- foreach(DocuSign.eSign.Model.LoginAccount loginAcct in loginInfo.LoginAccounts) {
- if (loginAcct.IsDefault == "true") {
- accountId = loginAcct.AccountId;
- break;
- }
- }
- if (accountId == null) {
- accountId = loginInfo.LoginAccounts[0].AccountId;
- }
- return accountId;
- }
And, we have stored the recipient's envelope information in our local database. So, we can get the envelope information by calling the recipient table. Now, let's loop the table values.
- List < DocusignDemo.Models.Recipient > recipientsDocs = new List < DocusignDemo.Models.Recipient > ();
- public ActionResult ListDocuments() {
- ApiClient apiClient = new ApiClient("https://demo.docusign.net/restapi");
- Configuration.Default.ApiClient = apiClient;
- MyCredential myCredential = new MyCredential();
-
- string accountId = loginApi(myCredential.UserName, myCredential.Password);
- DocusignDemo.Models.CSharpCornerEntities cSharpCornerEntities = new DocusignDemo.Models.CSharpCornerEntities();
- var recipients = cSharpCornerEntities.Recipients.ToList();
- string serverDirectory = Server.MapPath("~/Uploadfiles/");
- if (!Directory.Exists(serverDirectory)) {
- Directory.CreateDirectory(serverDirectory);
- }
- foreach(var recipient in recipients) {
- if (recipient.Name == "GnanavelSekar") {
- string recipientDirectory = Server.MapPath("~/Uploadfiles/" + recipient.EnvelopeID);
- if (!Directory.Exists(recipientDirectory)) {
- Directory.CreateDirectory(recipientDirectory);
- }
- EnvelopeDocumentsResult documentList = ListEnvelopeDocuments(accountId, recipient.EnvelopeID);
- int i = 0;
- string SignedPDF = string.Empty;
- EnvelopesApi envelopesApi = new EnvelopesApi();
- foreach(var document in documentList.EnvelopeDocuments) {
- string signingStatus = recipient.Status == "completed" ? "Signed" : "Yet to Sign";
- MemoryStream docStream = (MemoryStream) envelopesApi.GetDocument(accountId, recipient.EnvelopeID, documentList.EnvelopeDocuments[i].DocumentId);
- string documentName = document.Name != "Summary" ? document.Name : "Summary";
- SignedPDF = Server.MapPath("~/Uploadfiles/" + recipient.EnvelopeID + "/" + recipient.EnvelopeID + "_" + documentName + ".pdf");
- using(var fileStream = System.IO.File.Create(SignedPDF)) {
- docStream.Seek(0, SeekOrigin.Begin);
- docStream.CopyTo(fileStream);
- }
- recipientsDocs.Add(new DocusignDemo.Models.Recipient {
- EnvelopeID = recipient.EnvelopeID, Name = recipient.Name, Email = recipient.Email, Status = signingStatus, documentURL = SignedPDF, SentOn = recipient.SentOn, UpdatedOn = recipient.UpdatedOn
- });
- i++;
- }
- }
- }
- return View(recipientsDocs);
- }
In the above code, we are getting the list of recipients. For that, I have created the list object to hold it. Then, we have created the local directory to store the recipient documents. Now, let's loop the recipient to get the list of documents. And we have created a directory for each recipient envelope.
- public EnvelopeDocumentsResult ListEnvelopeDocuments(string accountId, string envelopeId) {
- EnvelopesApi envelopesApi = new EnvelopesApi();
- EnvelopeDocumentsResult docsList = envelopesApi.ListDocuments(accountId, envelopeId);
- return docsList;
- }
Every time, we will get the two documents for each envelop.
- Sent document with/without Signature
- Certified document - It represents the Summary document; it contains the information, such as sender details, recipient details, etc.
List document(s) in View
We have got the list of the documents in "recipientsDocs" object. Now, let's create a strongly typed view to list these documents.
- @model IEnumerable<DocusignDemo.Models.Recipient>
- @{
-
- ViewBag.Title = "ListDocuments";
- Layout = "~/Views/Shared/_Layout.cshtml";
- }
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
- </head>
-
- <body style="margin-top:20px">
- <div class="container">
- <div class="table-responsive">
- <table class="table table-bordered">
- <thead class="btn-primary">
- <tr>
- <th> @Html.DisplayNameFor(model => model.Name) </th>
- <th> @Html.DisplayNameFor(model => model.Email) </th>
- <th> @Html.DisplayNameFor(model => model.EnvelopeID) </th>
- <th> @Html.DisplayNameFor(model => model.Status) </th>
- <th> @Html.DisplayNameFor(model => model.SentOn) </th>
- <th> @Html.DisplayNameFor(model => model.UpdatedOn) </th>
- <th> @Html.DisplayNameFor(model => model.documentURL) </th>
- </tr>
- </thead>
- <tbody>
- @foreach (var item in Model)
- {
- <tr>
- <td> @Html.DisplayFor(modelItem => item.Name) </td>
- <td> @Html.DisplayFor(modelItem => item.Email) </td>
- <td> @Html.DisplayFor(modelItem => item.EnvelopeID) </td>
- <td> @Html.DisplayFor(modelItem => item.Status) </td>
- <td> @Html.DisplayFor(modelItem => item.SentOn) </td>
- <td> @Html.DisplayFor(modelItem => item.UpdatedOn) </td>
- <td> @Html.DisplayFor(modelItem => item.documentURL) </td>
- </tr>
- }
- </tbody>
- </table>
- </div>
- </div>
- </body>
Now, run your application.
I made a few more signature requests to the below recipients.
Now, you can see the "Yet to Sign" status which is recently sent.
Download document(s)
Still, we have shown the local directory path in documentUrl so, let's change that into the link to download the respective document
@Html.ActionLink(item.Status, "Download", "Docusign", new { filePath = item.documentURL }, null)
\
Now, create a download action DocuSign controller to download the file from the respective path. I am passing the input parameter "filePath " value while calling the Download action.
- public FileResult Download(string filePath) {
- string fileName = Path.GetFileName(filePath);
- string contentType = "application/pdf";
- return File(filePath, contentType, fileName);
- }
Now, run your application.
Complete View
- @model IEnumerable<DocusignDemo.Models.Recipient>
- @{
-
- ViewBag.Title = "ListDocuments";
- Layout = "~/Views/Shared/_Layout.cshtml";
- }
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
- </head>
-
- <body style="margin-top:20px">
- <div class="container">
- <div class="table-responsive">
- <table class="table table-bordered">
- <thead class="btn-primary">
- <tr>
- <th> @Html.DisplayNameFor(model => model.Name) </th>
- <th> @Html.DisplayNameFor(model => model.Email) </th>
- <th> @Html.DisplayNameFor(model => model.EnvelopeID) </th> @*<th> @Html.DisplayNameFor(model => model.Status) </th>*@ <th> @Html.DisplayNameFor(model => model.SentOn) </th>
- <th> @Html.DisplayNameFor(model => model.UpdatedOn) </th>
- <th> Document </th>
- </tr>
- </thead>
- <tbody> @foreach (var item in Model) { <tr>
- <td> @Html.DisplayFor(modelItem => item.Name) </td>
- <td> @Html.DisplayFor(modelItem => item.Email) </td>
- <td> @Html.DisplayFor(modelItem => item.EnvelopeID) </td> @*<td> @Html.DisplayFor(modelItem => item.Status) </td>*@ <td> @Html.DisplayFor(modelItem => item.SentOn) </td>
- <td> @Html.DisplayFor(modelItem => item.UpdatedOn) </td>
- <td> @*@Html.DisplayFor(modelItem => item.documentURL)*@ @Html.ActionLink(item.Status, "Download", "Docusign", new { filePath = item.documentURL }, null) </td>
- </tr> } </tbody>
- </table>
- </div>
- </div>
- </body>
- using DocuSign.eSign.Api;
- using DocuSign.eSign.Client;
- using DocuSign.eSign.Model;
- using DocusignDemo.Models;
- using Newtonsoft.Json;
- using System.Collections.Generic;
- using System.Data.Entity;
- using System.IO;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using Document = DocuSign.eSign.Model.Document;
- namespace DocusignDemo.Controllers {
- public class DocusignController: Controller {
- public string loginApi(string usr, string pwd) {
-
- ApiClient apiClient = Configuration.Default.ApiClient;
- string authHeader = "{\"Username\":\"" + usr + "\", \"Password\":\"" + pwd + "\", \"IntegratorKey\":\"" + INTEGRATOR_KEY + "\"}";
- Configuration.Default.AddDefaultHeader("X-DocuSign-Authentication", authHeader);
-
- string accountId = null;
-
- AuthenticationApi authApi = new AuthenticationApi();
- LoginInformation loginInfo = authApi.Login();
-
- foreach(DocuSign.eSign.Model.LoginAccount loginAcct in loginInfo.LoginAccounts) {
- if (loginAcct.IsDefault == "true") {
- accountId = loginAcct.AccountId;
- break;
- }
- }
- if (accountId == null) {
- accountId = loginInfo.LoginAccounts[0].AccountId;
- }
- return accountId;
- }
- List < DocusignDemo.Models.Recipient > recipientsDocs = new List < DocusignDemo.Models.Recipient > ();
- public ActionResult ListDocuments() {
- ApiClient apiClient = new ApiClient("https://demo.docusign.net/restapi");
- Configuration.Default.ApiClient = apiClient;
- MyCredential myCredential = new MyCredential();
-
- string accountId = loginApi(myCredential.UserName, myCredential.Password);
- DocusignDemo.Models.CSharpCornerEntities cSharpCornerEntities = new DocusignDemo.Models.CSharpCornerEntities();
- var recipients = cSharpCornerEntities.Recipients.ToList();
- string serverDirectory = Server.MapPath("~/Uploadfiles/");
- if (!Directory.Exists(serverDirectory)) {
- Directory.CreateDirectory(serverDirectory);
- }
- foreach(var recipient in recipients) {
- string recipientDirectory = Server.MapPath("~/Uploadfiles/" + recipient.EnvelopeID);
- if (!Directory.Exists(recipientDirectory)) {
- Directory.CreateDirectory(recipientDirectory);
- }
- EnvelopeDocumentsResult documentList = ListEnvelopeDocuments(accountId, recipient.EnvelopeID);
- int i = 0;
- string SignedPDF = string.Empty;
- EnvelopesApi envelopesApi = new EnvelopesApi();
- foreach(var document in documentList.EnvelopeDocuments) {
- string signingStatus = recipient.Status == "completed" ? "Signed" : "Yet to Sign";
- MemoryStream docStream = (MemoryStream) envelopesApi.GetDocument(accountId, recipient.EnvelopeID, documentList.EnvelopeDocuments[i].DocumentId);
- string documentName = document.Name != "Summary" ? document.Name : "Summary";
- SignedPDF = Server.MapPath("~/Uploadfiles/" + recipient.EnvelopeID + "/" + recipient.EnvelopeID + "_" + documentName + ".pdf");
- using(var fileStream = System.IO.File.Create(SignedPDF)) {
- docStream.Seek(0, SeekOrigin.Begin);
- docStream.CopyTo(fileStream);
- }
- recipientsDocs.Add(new DocusignDemo.Models.Recipient {
- EnvelopeID = recipient.EnvelopeID, Name = recipient.Name, Email = recipient.Email, Status = signingStatus, documentURL = SignedPDF, SentOn = recipient.SentOn, UpdatedOn = recipient.UpdatedOn
- });
- i++;
- }
- }
- return View(recipientsDocs);
- }
- public EnvelopeDocumentsResult ListEnvelopeDocuments(string accountId, string envelopeId) {
- EnvelopesApi envelopesApi = new EnvelopesApi();
- EnvelopeDocumentsResult docsList = envelopesApi.ListDocuments(accountId, envelopeId);
- return docsList;
- }
- public FileResult Download(string filePath) {
- string fileName = Path.GetFileName(filePath);
- string contentType = "application/pdf";
- return File(filePath, contentType, fileName);
- }
- }
- public class MyCredential {
- public string UserName {
- get;
- set;
- } = "";
- public string Password {
- get;
- set;
- } = "";
- }
- }
Model
- namespace DocusignDemo.Models {
- using System;
- using System.Collections.Generic;
- public partial class Recipient {
- public long Id {
- get;
- set;
- }
- public string Name {
- get;
- set;
- }
- public string Email {
- get;
- set;
- }
- public string EnvelopeID {
- get;
- set;
- }
- public byte[] Documents {
- get;
- set;
- }
- public string Description {
- get;
- set;
- }
- public string Status {
- get;
- set;
- }
- public Nullable < System.DateTime > SentOn {
- get;
- set;
- }
- public Nullable < System.DateTime > UpdatedOn {
- get;
- set;
- }
- public string documentURL {
- get;
- set;
- }
- }
- }
Refer to the attached project for reference. I have attached the demonstrated project without package due to the size limit.
Summary
In this article, we discussed how to get the document(s) from DocuSign using envelope id, store them to a local directory, and list and download those into our web application view. I hope it will help you. Your valuable feedback and comments about this article are always welcome.