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.
- ASP.NET MVC 5 - Integrate And Validate DocuSign Connection With Web Application
- ASP.NET MVC 5 - DocuSign - Send A Document For Signature From Web Application
- ASP.NET MVC 5 - DocuSign - Get And Store Envelop Information Into Database Using EF
- ASP.NET MVC 5 - DocuSign - Sign On A Document And Track Envelopes
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)
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) {
- // we set the api client in global config when we configured the client
- ApiClient apiClient = Configuration.Default.ApiClient;
- string authHeader = "{\"Username\":\"" + usr + "\", \"Password\":\"" + pwd + "\", \"IntegratorKey\":\"" + INTEGRATOR_KEY + "\"}";
- Configuration.Default.AddDefaultHeader("X-DocuSign-Authentication", authHeader);
- // we will retrieve this from the login() results
- string accountId = null;
- // the authentication api uses the apiClient (and X-DocuSign-Authentication header) that are set in Configuration object
- AuthenticationApi authApi = new AuthenticationApi();
- LoginInformation loginInfo = authApi.Login();
- // find the default account for this user
- foreach(DocuSign.eSign.Model.LoginAccount loginAcct in loginInfo.LoginAccounts) {
- if (loginAcct.IsDefault == "true") {
- accountId = loginAcct.AccountId;
- break;
- }
- }
- if (accountId == null) { // if no default found set to first account
- 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();
- // call the Login() API which sets the user's baseUrl and returns their accountId
- 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>
Complete Controller
- 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) {
- // we set the api client in global config when we configured the client
- ApiClient apiClient = Configuration.Default.ApiClient;
- string authHeader = "{\"Username\":\"" + usr + "\", \"Password\":\"" + pwd + "\", \"IntegratorKey\":\"" + INTEGRATOR_KEY + "\"}";
- Configuration.Default.AddDefaultHeader("X-DocuSign-Authentication", authHeader);
- // we will retrieve this from the login() results
- string accountId = null;
- // the authentication api uses the apiClient (and X-DocuSign-Authentication header) that are set in Configuration object
- AuthenticationApi authApi = new AuthenticationApi();
- LoginInformation loginInfo = authApi.Login();
- // find the default account for this user
- foreach(DocuSign.eSign.Model.LoginAccount loginAcct in loginInfo.LoginAccounts) {
- if (loginAcct.IsDefault == "true") {
- accountId = loginAcct.AccountId;
- break;
- }
- }
- if (accountId == null) { // if no default found set to first account
- 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();
- // call the Login() API which sets the user's baseUrl and returns their accountId
- 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;
- } = ""; //Enter Docusign Username
- public string Password {
- get;
- set;
- } = ""; //Enter Docusign Password
- }
- }
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.

ahtasham ulhaqPosted Mar 11, 2022, 7:35 AM
CSharpCornerEntities is missing can you please guide in this regard's
Developer SekarPosted Jun 4, 2019, 2:42 AM
Hi, how to get document fields and set required dynamically without creating a custom tab or custom fields.
Santhosh KadambariPosted Apr 12, 2019, 12:16 PM
Hello..why can't we use our own document server for storing the signed documents? Why should we use docusign or any other service? Can't we create our own apps for signing and storing the signed documents. We are a small organization and we just want to save money to add code to our apps to enable the users to sign and so we can save the signed documents to our servers.