Bad Request 400 eslClient.CreatePackage() after upgrade from 10.3 to 10.13
Tuesday, December 6, 2016 at 12:24pmHello, I recently updated the api version for Silanis.ESL.dll from 10.3 to 10.13, after doing so the code that I'm using to dynamically build the packages for getting signed no longer works. The test code that I use with hard coded values still works, but I keep getting Bad Request 400 errors when I use my dynamic code in a real test from our web application and I can't seem to find any further details as to what is causing the 400 Bad Request.
Here is the "test" code that is working just fine:
Public Function GenerateTestSession(cFilePath As String, cReturnURL As String) As String
Dim eslClient = New EslClient(API_KEY, SDK_URL)
Dim signer = createSignerDynamic("[email protected]", "John", "Smith", "My Co.", "JSmith")
Dim settings As New DocumentPackageSettings
With settings
.CeremonyLayoutSettings = New CeremonyLayoutSettings
.CeremonyLayoutSettings.ProgressBar = False
.CeremonyLayoutSettings.BreadCrumbs = False
.CeremonyLayoutSettings.IFrame = True
.CeremonyLayoutSettings.SessionBar = False
.CeremonyLayoutSettings.GlobalNavigation = False
.CeremonyLayoutSettings.ShowTitle = False
.CeremonyLayoutSettings.Navigator = False
.EnableDecline = True
.EnableOptOut = True
.LinkHref = cReturnURL
.LinkText = "Click here when done!"
.ShowDialogOnComplete = True
End With
Dim db As DocumentBuilder
Dim file As New FileInfo(cFilePath)
db = NewDocumentNamed("My Document").FromFile(file.FullName)
Dim sb As SignatureBuilder = SignatureBuilder.CaptureFor(signer.Email).OnPage(1).AtPosition(450, 380)
Dim fb As FieldBuilder = FieldBuilder.CheckBox.OnPage(1).AtPosition(345, 372)
fb.WithSize(15, 15).WithName("OKResident").WithId("OKResident")
sb.WithField(fb)
Dim fb_radio As FieldBuilder = FieldBuilder.RadioButton("group1").OnPage(1).AtPosition(345, 472)
fb_radio.WithId("radio label")
fb_radio.WithValue(False) ' default to not selected
' not yet fully supported and tested...
sb.WithField(fb_radio)
' do nothing for now so we don't get an error...
Dim fb_drop As FieldBuilder = FieldBuilder.DropList.OnPage(1).AtPosition(345, 572)
fb_drop.WithSize(300, 300)
fb_drop.WithName("dorp label")
fb_drop.WithId("drop id")
fb_drop.WithValue("DropList Option 2") 'default to 2nd option
Dim fvb As FieldValidatorBuilder = FieldValidatorBuilder.Basic _
.WithOption("DropList Option 1") _
.WithOption("DropList Option 2") _
.WithOption("DropList Option 3")
fb_drop.WithValidation(fvb)
sb.WithField(fb_drop)
db.WithSignature(sb)
Dim documentPackage = PackageBuilder.NewPackageNamed("Sample Document") _
.WithSigner(signer).WithDocument(db).WithSettings(settings).Build()
Dim packageId = eslClient.CreatePackage(documentPackage)
eslClient.SendPackage(packageId)
Dim SessionToken = eslClient.SessionService.CreateSessionToken(packageId, signer.Id)
Return SessionToken.Token
End Function
And here's the dynamically built package code that is generating the 400 error (that WAS working just fine before upgrading to 10.13):
Public Function GenerateSession(iTransID As Guid) As String
Dim eslClient = New EslClient(API_KEY, SDK_URL)
Dim esr As New eSignRequest(iTransID, sqlMan) ' eSignRequest is my special class for handling the requests
Dim eSignUser As eSignUser = esr.ESignUser ' eSignUser is also my class
Dim settings As DocumentPackageSettings = createSettings(esr.ReturnURL) ' function included down below
Dim signer As Signer = createSignerDynamic(eSignUser.Email, eSignUser.FirstName,
eSignUser.LastName, eSignUser.Company,
eSignUser.ID) ' function included down below
Dim pkgBuilder = PackageBuilder.NewPackageNamed(esr.PackageName)
pkgBuilder.WithSigner(signer)
pkgBuilder.WithSettings(settings)
createDocumentsDynamic(pkgBuilder, esr.Documents, signer) ' function included down below
Dim docPackage As DocumentPackage = pkgBuilder.Build()
Dim packageId As PackageId = eslClient.CreatePackage(docPackage)
eslClient.SendPackage(packageId)
Dim sessionToken As SessionToken = eslClient.SessionService.CreateSessionToken(packageId, signer.Id)
'Save the eSign Package ID (GUID) to our database
sqlMan.saveAWSGuid(iTransID, packageId.ToString)
Return sessionToken.Token
End Function
Private Function createSettings(cReturnURL As String) As DocumentPackageSettings
Dim settings As New DocumentPackageSettings
With settings
.CeremonyLayoutSettings = New CeremonyLayoutSettings
.CeremonyLayoutSettings.ProgressBar = False
.CeremonyLayoutSettings.BreadCrumbs = False
.CeremonyLayoutSettings.IFrame = True
.CeremonyLayoutSettings.SessionBar = False
.CeremonyLayoutSettings.GlobalNavigation = False
.CeremonyLayoutSettings.ShowTitle = False
.CeremonyLayoutSettings.Navigator = False
.EnableDecline = True
.EnableOptOut = True
'.EnableInPerson = True ' brings up "In Person" dialog, not used right now...
.LinkHref = cReturnURL
.LinkText = "Click here when done!"
.ShowDialogOnComplete = True
End With
Return settings
End Function
Private Function createSignerDynamic(cEmail As String, cFirst As String, cLast As String, cCompany As String, cID As String) As Signer
Dim s As Signer
s = SignerBuilder.NewSignerWithEmail(cEmail) _
.WithFirstName(cFirst) _
.WithLastName(cLast) _
.Build()
'We do not want to have any emails going out to the users
s.DeliverSignedDocumentsByEmail = False
If Not String.IsNullOrEmpty(cCompany) Then
s.Company = cCompany
End If
If Not String.IsNullOrEmpty(cID) Then
s.Id = cID
End If
Return s
End Function
Private Sub createDocumentsDynamic(ByRef pb As PackageBuilder, ByVal Docs As List(Of Document), ByVal signer As Signer)
For Each doc As Document In Docs
pb.WithDocument(createDoc(doc, signer))
Next
pb.Build()
End Sub
Private Function createDoc(dr As DataRow, drSigs() As DataRow, drFields() As DataRow, signer As Signer) As DocumentBuilder
'Create a Document Object for signing from the transaction data for this ceremony
Dim myDoc As New Document(dr, drSigs, drFields)
'Initialize the document, ie read in the PDF whether it is from a file or print job..
Dim db As DocumentBuilder = createDoc_InitDocument(myDoc, signer)
'Create the signatures for the page, this will also place any datafields on as well
createDoc_AddSignatures(db, myDoc, signer)
Return db
End Function
Private Function createDoc(myDoc As Document, signer As Signer) As DocumentBuilder
'Initialize the document, ie read in the PDF whether it is from a file or print job..
Dim db As DocumentBuilder = createDoc_InitDocument(myDoc, signer)
'Create the signatures for the page, this will also place any datafields on as well
createDoc_AddSignatures(db, myDoc, signer)
Return db
End Function
Private Function createDoc_InitDocument(myDoc As Document, signer As Signer) As DocumentBuilder
Dim cID As String = myDoc.DocId
Dim cDisplayName As String = myDoc.DisplayName
Dim cDescription As String = myDoc.Description
Dim cInput As String = myDoc.Input
Dim cDocLocation As String = myDoc.DocLocation
Dim db As DocumentBuilder
Dim cDocDirectory As String = ""
If Not IsNothing(WebContext) Then
cDocDirectory = WebContext.Server.MapPath("~/Documents/" & cDocLocation)
End If
db = NewDocumentNamed(cDisplayName).WithId(cID)
If cInput = "" Then
' If input is blank, cDocLocation will point to a file that's within the project's
' Documents folder.
Dim cPhysicalLocation As String = cDocDirectory & cDocLocation
db.FromFile(cPhysicalLocation)
ElseIf cInput.StartsWith("http") Then
' if it starts with http, then it's going to be a PDF that was generated via
' the Printing Service, so we must go out and download it in order to
' insert it into our package
Dim request As System.Net.WebRequest = System.Net.WebRequest.Create(cInput)
request.Credentials = New System.Net.NetworkCredential("username", "password_haha")
Dim response As System.Net.WebResponse = request.GetResponse()
Dim s As Stream = response.GetResponseStream()
Dim nRemaining As Integer = response.ContentLength
Dim nOffset As Integer = 0
Dim buffer(nRemaining) As Byte
While (nRemaining > 0)
Dim nRead As Integer = s.Read(buffer, nOffset, nRemaining)
If nRead 0 Then
Throw New Exception("Error Reading PDF")
End If
nRemaining = nRemaining - nRead
nOffset = nOffset + nRead
End While
Dim ms As New MemoryStream(buffer)
db.FromStream(ms, DocumentType.PDF)
Else
'Otherwise read in the file from the project directory "Documents"
Dim cPhysicalLocation As String = cDocDirectory & cInput
db.FromFile(cPhysicalLocation)
End If
' if this is an eSign Consent form, we need to add the accept
' button that will be shown at the bottom of the page..
If cID.ToLower = "esignconsent" Then
db.WithSignature(SignatureBuilder.AcceptanceFor(signer.Email))
End If
Return db
End Function
Private Sub createDoc_AddSignatures(ByRef db As DocumentBuilder, myDoc As Document, signer As Signer)
For Each sig As DocumentSignature In myDoc.Signatures
Dim lInitials As Boolean = sig.Initial
Dim nLocX As Integer = sig.Locaction_X
Dim nLocY As Integer = sig.Locaction_Y
Dim nPage As Integer = 0
'Find out on which page the signature should be placed
If Not IsDBNull(sig.Locaction_Page) Then
nPage = sig.Locaction_Page
Else
nPage = 0
End If
If String.IsNullOrEmpty(signer.Email) Then
Throw New ArgumentException("Signer Email Address must be provided.")
End If
Dim sb As SignatureBuilder
If lInitials Then
sb = SignatureBuilder.InitialsFor(signer.Email).OnPage(nPage).AtPosition(nLocX, nLocY)
Else
sb = SignatureBuilder.CaptureFor(signer.Email).OnPage(nPage).AtPosition(nLocX, nLocY)
End If
'create any data fields for the signature...
createDoc_AddDataFields(sb, myDoc.Fields)
db.WithSignature(sb)
Next
End Sub
Private Sub createDoc_AddDataFields(ByRef sb As SignatureBuilder, myFields As List(Of DocumentDataField))
For Each fld As DocumentDataField In myFields
Dim cLabel As String = fld.Label
Dim cFieldType As String = fld.Type
Dim nSize As Integer = fld.Size
Dim lShowLabel As Boolean = fld.ShowLabel
Dim cContentFormat As String = If(fld.ContentFormat, "")
Dim cGroupName As String = If(fld.GroupName, "")
Dim nLocX As Integer = fld.Locaction_X
Dim nLocY As Integer = fld.Locaction_Y
Dim nWidth As Integer = fld.Locaction_W
Dim nHeight As Integer = fld.Locaction_H
Dim nPage As Integer = fld.Locaction_Page
Select Case cFieldType
Case "TextBox"
Dim fb = FieldBuilder.TextField.OnPage(nPage).AtPosition(nLocX, nLocY).WithName(cLabel).WithId(cLabel)
Select Case cContentFormat
Case "numeric"
fb.WithValidation(FieldValidatorBuilder.Numeric)
Case "email"
fb.WithValidation(FieldValidatorBuilder.Email)
Case Else
' no validation needed..
End Select
sb.WithField(fb)
Case "CheckBox"
Dim fb As FieldBuilder = FieldBuilder.CheckBox.OnPage(nPage).AtPosition(nLocX, nLocY)
fb.WithSize(nWidth, nHeight)
fb.WithName(cLabel)
fb.WithId(cLabel)
sb.WithField(fb)
Case "RadioButton"
Dim fb As FieldBuilder = FieldBuilder.RadioButton(cGroupName).OnPage(nPage).AtPosition(nLocX, nLocY)
fb.WithId(cLabel)
fb.WithSize(nWidth, nHeight)
fb.WithValue(False) ' default to not selected
' not yet fully supported and tested...
'sb.WithField(fb)
' do nothing for now so we don't get an error...
Case "Select"
Dim fb As FieldBuilder = FieldBuilder.DropList.OnPage(nPage).AtPosition(nLocX, nLocY)
fb.WithSize(nWidth, nHeight)
fb.WithName(cLabel)
fb.WithId(cLabel)
fb.WithValue("DropList Option 2") 'default to 2nd option
Dim fvb As FieldValidatorBuilder = FieldValidatorBuilder.Basic _
.WithOption("DropList Option 1") _
.WithOption("DropList Option 2") _
.WithOption("DropList Option 3")
fb.WithValidation(fvb)
' not yet fully supported and tested...
'sb.WithField(fb)
' do nothing for now so we don't get an error...
Case Else
Throw New ApplicationException("Invalid DataField: " & cFieldType)
End Select
Next
End Sub
(hopefully this all formatted correctly...)
Reply to: Bad Request 400 eslClient.CreatePackage() after upgrade from 10.3 to 10.13
Tuesday, December 6, 2016 at 05:01pmPublic Function GenerateSession(iTransID As Guid) As String Dim eslClient = New EslClient(API_KEY, SDK_URL) 'Dim esr As New eSignRequest(iTransID, sqlMan) ' eSignRequest is my special class for handling the requests ' Dim eSignUser As eSignUser = esr.ESignUser ' eSignUser is also my class 'Dim settings As DocumentPackageSettings = createSettings(esr.ReturnURL) ' function included down below 'Dim signer As Signer = createSignerDynamic(eSignUser.Email, eSignUser.FirstName, ' eSignUser.LastName, eSignUser.Company, ' eSignUser.ID) ' function included down below 'Dim pkgBuilder = PackageBuilder.NewPackageNamed(esr.PackageName) ' pkgBuilder.WithSigner(signer) 'pkgBuilder.WithSettings(settings) 'createDocumentsDynamic(pkgBuilder, esr.Documents, signer) ' function included down below Dim docPackage As DocumentPackage = pkgBuilder.Build() Dim packageId As PackageId = eslClient.CreatePackage(docPackage) ' eslClient.SendPackage(packageId) ' Dim sessionToken As SessionToken = eslClient.SessionService.CreateSessionToken(packageId, signer.Id) 'Save the eSign Package ID (GUID) to our database 'sqlMan.saveAWSGuid(iTransID, packageId.ToString) Return "blah" End FunctionReply to: Bad Request 400 eslClient.CreatePackage() after upgrade from 10.3 to 10.13
Wednesday, December 7, 2016 at 04:56amPrivate Function createSignerDynamic(cEmail As String, cFirst As String, cLast As String, cCompany As String, cID As String) As Signer Dim s As Signer s = SignerBuilder.NewSignerWithEmail(cEmail) _ .WithFirstName(cFirst) _ .WithLastName(cLast) _ .Build() 'We do not want to have any emails going out to the users s.DeliverSignedDocumentsByEmail = False If Not String.IsNullOrEmpty(cCompany) Then s.Company = cCompany End If If Not String.IsNullOrEmpty(cID) Then s.Id = cID End If Return s End FunctionNow I'll begin looking into what changes might have been made that cause this code to no longer work...Reply to: Bad Request 400 eslClient.CreatePackage() after upgrade from 10.3 to 10.13
Wednesday, December 7, 2016 at 05:36amOk, after more trial and error using the same technique, I narrowed it down to the following bit of code inside createSignerDynamic:
If Not String.IsNullOrEmpty(cID) Then s.Id = cID End IfI was passing in eSignUser.ID with the value of their email address as I didn't have anything else to use for the signer.Id value. After commenting out this code it was now erroring at:
Dim sessionToken As SessionToken = eslClient.SessionService.CreateSessionToken(packageId, signer.Id)Which was being caused by signer.Id being Nothing, so I changed that line to the following
Dim sessionToken As SessionToken = eslClient.SessionService.CreateSessionToken(packageId, eSignUser.Email)And all seems to be well again. So there appears to be an issue with using an email address (SignerBuilder.NewSignerWithEmail()) and then setting the Id to the same email address. However something I found on CreateSessionToken() via google is that starting in API version 10.6 you do not need to set the Custom Id and can just use the email address directly in the call to CreateSessionToken (See here), that's effectively what I'm doing now by commenting out my offending code and changing the one line later on. So now that that's all taken care of, does anyone know of a better way to get error messages out of the ESLClient in .NET in this situation? I feel this could have easily been tracked down had I known more information about what it was complaining about instead of resorting to playing whack-a-mole with commenting out chunks of code..
Reply to: Bad Request 400 eslClient.CreatePackage() after upgrade from 10.3 to 10.13
Wednesday, December 7, 2016 at 05:57am