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 FunctionAnd 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:01pmReply to: Bad Request 400 eslClient.CreatePackage() after upgrade from 10.3 to 10.13
Wednesday, December 7, 2016 at 04:56amReply 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:
I 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:
Which was being caused by signer.Id being Nothing, so I changed that line to the following
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