Docusign .net send enevlope issue on one server - docusignapi

We've implement docusign api into our application and it works fine in development and on one of our production servers, but on particular production server it fails when running the following line
var scope = new OperationContextScope(client.InnerChannel);
The exception thrown is
Error: InvalidDataContractException: Message: Type 'System.Threading.Tasks.Task`1[DocuSign.DocuSignWeb.SetSharedAccessResult]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
Here is the complete method that is called
public DocuSignResponse SendEnvelope(Envelope envelope, string templateGUID)
{
var response = new DocuSignResponse();
var client = new DSAPIServiceSoapClient("DSAPIServiceSoap", URL);
try
{
var scope = new OperationContextScope(client.InnerChannel);
{
HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers.Add("X-DocuSign-Authentication", AuthHeader);
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
if (client.InnerChannel.State != System.ServiceModel.CommunicationState.Faulted)
{
// call service - everything's fine
}
else
{
// channel faulted - re-create your client and then try again
response.Success = false;
response.ErrorMessage = "Channel has faulted!!";
return response;
}
client.Open();
EnvelopeStatus envelopeStatus;
if (!string.IsNullOrEmpty(templateGUID))
{
DocuSignWeb.EnvelopeInformation envelopeInfo = new DocuSignWeb.EnvelopeInformation();
envelopeInfo.AccountId = AccountId;
envelopeInfo.EmailBlurb = envelope.EmailBlurb;
envelopeInfo.Subject = envelope.Subject;
// Configure the inline templates
DocuSignWeb.InlineTemplate inlineTemplate = new DocuSignWeb.InlineTemplate();
inlineTemplate.Sequence = "1";
inlineTemplate.Envelope = new DocuSignWeb.Envelope();
inlineTemplate.Envelope.Recipients = envelope.Recipients;
inlineTemplate.Envelope.AccountId = AccountId;
DocuSignWeb.CompositeTemplate template = new DocuSignWeb.CompositeTemplate();
template.InlineTemplates = new DocuSignWeb.InlineTemplate[] {inlineTemplate};
DocuSignWeb.ServerTemplate serverTemplate = new DocuSignWeb.ServerTemplate();
serverTemplate.Sequence = "1";
serverTemplate.TemplateID = templateGUID;
template.ServerTemplates = new[] {serverTemplate};
template.Document = envelope.Documents[0];
envelopeStatus = client.CreateEnvelopeFromTemplatesAndForms(envelopeInfo, new[] {template}, true);
}
else
{
envelopeStatus = client.CreateAndSendEnvelope(envelope);
}
// An envelope ID indicates that it succeeded
response.Success = true;
response.ResponseRef = envelopeStatus.EnvelopeID;
// No point doing this, as it wouldn't have been signed
// Request the status of that envelope
// response.Status = client.RequestStatus(envelopeStatus.EnvelopeID);
// Used if embed option being used
response.Envelope = envelope;
response.Status = envelopeStatus;
if (client.State != CommunicationState.Faulted)
{
client.Close();
}
else
{
client.Abort();
}
}
}
catch (InvalidDataContractException err)
{
err.LogError();
response.Success = false;
response.ErrorMessage = string.Format("InvalidDataContractException: Message: {0} StackTrace: {1} AuthHeader: {2}", err.Message, err.StackTrace, AuthHeader);
}
catch (CommunicationException err)
{
err.LogError();
response.Success = false;
response.ErrorMessage = string.Format("CommunicationException: Message: {0} StackTrace: {1}", err.Message, err.StackTrace);
client.Abort();
}
catch (TimeoutException err)
{
err.LogError();
response.Success = false;
response.ErrorMessage = string.Format("TimeoutException: Message: {0} StackTrace: {1}", err.Message, err.StackTrace);
client.Abort();
}
catch (Exception err)
{
err.LogError();
response.Success = false;
response.ErrorMessage = string.Format("Exception: Message: {0} StackTrace: {1}", err.Message, err.StackTrace);
client.Abort();
}
finally
{
client = null;
}
return response;
}
At the moment i'm at a loss as to what the issue is, given the same code and database works on another machines, so at present thinking it's environmental.
Any help greatly appreciated.

Looks like this turned out to be server issues on DocuSign side. Occasionally there are bugs and other issues that get rolled back in DocuSign's Demo sandbox environment.

Related

What's wrong on using HttpWebRequest this way?

This is the way I do server request to some endpoints from Azure:
public T SingleRead<T>(string url, string method, object entity = null)
{
T returnValue = default(T);
var resp = GetRESTResponse(url, method, entity);
string responseText = GetResponseText(resp);
try
{
returnValue = JsonConvert.DeserializeObject<T>(responseText);
}
catch (Exception ex)
{
return default(T);
}
return returnValue;
}
private HttpWebResponse GetRESTResponse(string url, string method, object entity = null)
{
var address;
if (!url.StartsWith("http"))
{
if (!url.StartsWith("/")) url = $"/{url}";
address = baseAddress + url;
}
else
{
address = url;
}
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(address);
req.Method = method;
if (entity != null)
{
byte[] byteArray = Encoding.Default.GetBytes(JsonConvert.SerializeObject(entity));
req.ContentLength = byteArray.Length;
req.ContentType = "application/json";
Stream dataStream = req.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Flush();
dataStream.Close();
}
HttpWebResponse resp;
try
{
resp = (HttpWebResponse)req.GetResponse();
}
catch (WebException e)
{
Log(e.Reponse);
resp = (HttpWebResponse)e.Response;
}
return resp;
}
private static string GetResponseText(HttpWebResponse resp)
{
var encoding = Encoding.ASCII;
string responseText = ".";
using (var reader = new StreamReader(resp.GetResponseStream(), encoding))
{
responseText = reader.ReadToEnd();
}
if (resp.StatusCode == HttpStatusCode.InternalServerError || resp.StatusCode == HttpStatusCode.BadRequest || resp.StatusCode == HttpStatusCode.NotFound)
{
return "";
}
return responseText;
}
It works quite often. Sometimes, it doesn't, and I get the a "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond" error from the Log.
Is there some wrong in the procedure, or it could be a "timeout" by endpoint?
The called server users says "we don't have any problem, and we don't get the request".
Not sure if its the fault of the code above (maybe some stream not closed?). But I don't see any problem. Do you see any trouble in this?
It can be a network issue, which fails quite often. You need to remember there are several switches until the request goes outside the datacenter, and there are countless requests happening at the same time (you, and all other Azure customers).
This can be a transient fault, which may work if you send another request. You need to implement some retry logic to identify if the failure is transient or not.
More info:
https://learn.microsoft.com/en-us/azure/architecture/patterns/retry
And here's a sample using Polly, which is strongly recommended and even used inside Azure SDKs:
https://stackoverflow.com/a/66554740/1384539
https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/implement-http-call-retries-exponential-backoff-polly
https://github.com/App-vNext/Polly

Xamarin.iOS Cannot display photo in Push Notification

I have a Notification Service Extension and an AppGroup. I save a photo from camera in the PCL project and copy it to the App Group Container (shared folder).
In the Notification Service Extension I try to download the photo from the App Group container and attach it to the notification but it just does not display in the notification.
I also cannot debug the Service Extension to see what is going. As far as I know that is not possible currently still in Xamarin unless someone can correct me on that please.
Here is the code:
1.in my PCL I save the photo to the AppGroup when a save button is pressed:
private void ButtonSavePhoto_Clicked(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(photoFilePath))
{
Preferences.Set(AppConstants.CUSTOM_PICTURE_FILE_PATH, photoFilePath);
Preferences.Set(AppConstants.CUSTOM_PHOTO_SET_KEY, true);
if (Device.RuntimePlatform == Device.iOS)
{
bool copiedSuccessfully = DependencyService.Get<IPhotoService>().CopiedFileToAppGroupContainer(photoFilePath);
if (copiedSuccessfully)
{
var customPhotoDestPath = DependencyService.Get<IPhotoService>().GetAppContainerCustomPhotoFilePath();
// save the path of the custom photo in the AppGroup container to pass to Notif Extension Service
DependencyService.Get<IGroupUserPrefs>().SetStringValueForKey("imageAbsoluteString", customPhotoDestPath);
// condition whether to use custom photo in push notification
DependencyService.Get<IGroupUserPrefs>().SetBoolValueForKey("isCustomPhotoSet", true);
}
}
buttonSavePhoto.IsEnabled = false;
}
}
2.in my iOS project, Dependency injection calls this method when pressing save button:
public bool CopiedFileToAppGroupContainer(string filePath)
{
bool success = false;
string suiteName = "group.com.company.appName";
var appGroupContainerUrl = NSFileManager.DefaultManager.GetContainerUrl(suiteName);
var appGroupContainerPath = appGroupContainerUrl.Path;
var directoryNameInAppGroupContainer = Path.Combine(appGroupContainerPath, "Pictures");
var filenameDestPath = Path.Combine(directoryNameInAppGroupContainer, AppConstants.CUSTOM_PHOTO_FILENAME);
try
{
Directory.CreateDirectory(directoryNameInAppGroupContainer);
if (File.Exists(filenameDestPath))
{
File.Delete(filenameDestPath);
}
File.Copy(filePath, filenameDestPath);
success = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return success;
}
Now the path for the photo in the App Group container is:
/private/var/mobile/Containers/Shared/AppGroup/12F209B9-05E9-470C-9C9F-AA959D940302/Pictures/customphoto.jpg
3.Finally in the Notification Service Extension I try to attach the photo to the push notification:
public override void DidReceiveNotificationRequest(UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
{
ContentHandler = contentHandler;
BestAttemptContent = (UNMutableNotificationContent)request.Content.MutableCopy();
string imgPath;
NSUrl imgUrl;
string notificationBody = BestAttemptContent.Body;
string notifBodyInfo = "unknown";
string suiteName = "group.com.company.appname";
NSUserDefaults groupUserDefaults = new NSUserDefaults(suiteName, NSUserDefaultsType.SuiteName);
string pref1_value = groupUserDefaults.StringForKey("user_preference1");
string[] notificationBodySplitAtDelimiterArray = notificationBody.Split(',');
userPrefRegion = notificationBodySplitAtDelimiterArray[0];
bool isCustomAlertSet = groupUserDefaults.BoolForKey("isCustomAlert");
bool isCustomPhotoSet = groupUserDefaults.BoolForKey("isCustomPhotoSet");
string alarmPath = isCustomAlertSet == true ? "customalert.wav" : "default_alert.m4a";
if (isCustomPhotoSet)
{
// this is the App Group url of the custom photo saved in PCL
imgPath = groupUserDefaults.StringForKey("imageAbsoluteString");
}
else
{
imgPath = null;
}
if (imgPath != null )
{
imgUrl = NSUrl.FromString(imgPath);
}
else
{
imgUrl = null;
}
if (!string.IsNullOrEmpty(pref1_value))
{
if (BestAttemptContent.Body.Contains(pref1_value))
{
if (imgUrl != null)
{
// download the image from the AppGroup Container
var task = NSUrlSession.SharedSession.CreateDownloadTask(imgUrl, (tempFile, response, error) =>
{
if (error != null)
{
ContentHandler(BestAttemptContent);
return;
}
if (tempFile == null)
{
ContentHandler(BestAttemptContent);
return;
}
var cache = NSSearchPath.GetDirectories(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomain.User, true);
var cachesFolder = cache[0];
var guid = NSProcessInfo.ProcessInfo.GloballyUniqueString;
var fileName = guid + "customphoto.jpg";
var cacheFile = cachesFolder + fileName;
var attachmentUrl = NSUrl.CreateFileUrl(cacheFile, false, null);
NSError err = null;
NSFileManager.DefaultManager.Copy(tempFile, attachmentUrl, out err);
if (err != null)
{
ContentHandler(BestAttemptContent);
return;
}
UNNotificationAttachmentOptions options = null;
var attachment = UNNotificationAttachment.FromIdentifier("image", attachmentUrl, options, out err);
if (attachment != null)
{
BestAttemptContent.Attachments = new UNNotificationAttachment[] { attachment };
}
});
task.Resume();
}
BestAttemptContent.Title = "My Custom Title";
BestAttemptContent.Subtitle = "My Custom Subtitle";
BestAttemptContent.Body = "Notification Body";
BestAttemptContent.Sound = UNNotificationSound.GetSound(alarmPath);
}
}
else
{
pref1_value = "error getting extracting user pref";
}
// finally display customized notification
ContentHandler(BestAttemptContent);
}
/private/var/mobile/Containers/Shared/AppGroup/12F209B9-05E9-470C-9C9F-AA959D940302/Pictures/customphoto.jpg
From shared code, when image getting from AppGroup .You can check the file path whether work in this project.
imgPath = groupUserDefaults.StringForKey("imageAbsoluteString");
If not getting file from this path. You can get Url from AppGroup directly.Here is a sample as follow:
var FileManager = new NSFileManager();
var appGroupContainer = FileManager.GetContainerUrl("group.com.company.appName");
NSUrl fileURL = appGroupContainer.Append("customphoto.jpg", false);
And if fileURL can not be directly used, also can convert to NSData and save to local file system. This also can be a try.
Here is a sample below that grabs from local file system:
public static void Sendlocalnotification()
{
var localURL = "...";
NSUrl url = NSUrl.FromString(localURL) ;
var attachmentID = "image";
var options = new UNNotificationAttachmentOptions();
NSError error;
var attachment = UNNotificationAttachment.FromIdentifier(attachmentID, url, options,out error);
var content = new UNMutableNotificationContent();
content.Attachments = new UNNotificationAttachment[] { attachment };
content.Title = "Good Morning ~";
content.Subtitle = "Pull this notification ";
content.Body = "reply some message-BY Ann";
content.CategoryIdentifier = "message";
var trigger1 = UNTimeIntervalNotificationTrigger.CreateTrigger(0.1, false);
var requestID = "messageRequest";
var request = UNNotificationRequest.FromIdentifier(requestID, content, trigger1);
UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) =>
{
if (err != null)
{
Console.Write("Notification Error");
}
});
}

The remote party closed the WebSocket connection without completing the close handshake

I have Open Web Socket Method
public async Task OpenAsync(string url, string bodyMessage,
Dictionary<string, string> additionalHeaders, IImage imageService)
{
_securityService.SetClientToken().Wait();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls |
SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
var cancellationTokenSource = new CancellationTokenSource(new TimeSpan(1, 1, 0, 0));
using (ClientWebSocket clientWebSocket = new ClientWebSocket())
{
Uri serverUri = new Uri(url);
clientWebSocket.Options.SetRequestHeader("Authorization", $"Bearer {Endpoint.ClientAccessToken}");
foreach (var additionalHeader in additionalHeaders)
{
clientWebSocket.Options.SetRequestHeader(additionalHeader.Key, additionalHeader.Value);
}
try
{
clientWebSocket.ConnectAsync(serverUri, cancellationTokenSource.Token)
.Wait(cancellationTokenSource.Token);
}
catch (Exception exception)
{
Console.WriteLine(exception);
throw;
}
while (clientWebSocket.State == WebSocketState.Open)
{
string response = null;
try
{
ArraySegment<byte> bytesToSend = new ArraySegment<byte>(Encoding.UTF8.GetBytes(bodyMessage));
await clientWebSocket.SendAsync(bytesToSend, WebSocketMessageType.Text, true,
CancellationToken.None);
//ArraySegment<byte> bytesReceived = new ArraySegment<byte>(new byte[1024]);
byte[] incomingData = new byte[1024];
WebSocketReceiveResult result =
clientWebSocket.ReceiveAsync(new ArraySegment<byte>(incomingData), CancellationToken.None).Result;
if (result.CloseStatus.HasValue)
{
Console.WriteLine("Closed; Status: " + result.CloseStatus + ", " + result.CloseStatusDescription);
}
else
{
response = Encoding.UTF8.GetString(incomingData, 0, result.Count);
Console.WriteLine("Received message: " + response);
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
if(string.IsNullOrWhiteSpace(response)) continue;
//return response;
var jsonRespone = JsonConvert.DeserializeObject<JObject>(response);
ParkingEvent parkingEvent = jsonRespone != null
? (jsonRespone).ToObject<ParkingEvent>()
: new ParkingEvent();
//await SaveAsync(parkingEvent).ContinueWith(x=> imageService.MediaOnDemand(parkingEvent.Properties.ImageAssetUid, parkingEvent.Timestamp), cancellationTokenSource.Token);
await imageService.MediaOnDemandAsync(parkingEvent.Properties.ImageAssetUid, parkingEvent.Timestamp);
}
}
//return null;
}
I want this connection to be open and process any events received
var jsonRespone = JsonConvert.DeserializeObject<JObject>(response);
ParkingEvent parkingEvent = jsonRespone != null
? (jsonRespone).ToObject<ParkingEvent>()
: new ParkingEvent();
//await SaveAsync(parkingEvent).ContinueWith(x=> imageService.MediaOnDemand(parkingEvent.Properties.ImageAssetUid, parkingEvent.Timestamp), cancellationTokenSource.Token);
await imageService.MediaOnDemandAsync(parkingEvent.Properties.ImageAssetUid, parkingEvent.Timestamp);
Problem is when I get first response and I process it, while loop fails for the second one. How do I keep the connection open and process all events received through socket pipeline?

How to return Json response message for http error like 404 in wcf Service?

I have the below function which i am returning employees list. If
there is no list present in DB, I need to return httpstatusErrorcode
with error message
public List<SelectEventsMClass> FetchAllEmployes(int EmployTypeID)
{
try
{
var EventsList = new List<SelectEventsMClass>();
Employ.Data.EmployTableAdapters.EventsMSelectAllTableAdapter Adp = new Data.EmployTableAdapters.EventsMSelectAllTableAdapter();
Employ.Data.Employ.EventsMSelectAllDataTable Dtl = Adp.GetData(intEventTypeID);
if (Dtl.Rows.Count > 0)
{
var EventsList = (from lst in Dtl.AsEnumerable()
select new SelectEventsMClass
{
TransID = lst.Field<Guid>("TransID"),
SchoolTransID = lst.Field<Guid>("SchoolTransID"),
AcadamicTransID = lst.Field<Guid>("AcadamicTransID"),
EventTypeID = lst.Field<int>("EventTypeID"),
EventTitle = lst.Field<string>("EventTitle"),
}).ToList();
}
return EventsList;
}
catch (Exception ex)
{
throw ex;
}
}

Inconsistent Template Matching

I'm using the CreateEnvelope() method of the SOAP API to upload a document to DocuSign in the Draft status. When I do this and then request a Sender Token to start an Embedded Sending session, I'm immediately prompted to apply a matching template when the DocuSign interface appears.
If I don't start an Embedded Sending session, however, and the user instead logs into the DocuSign console and opens the Draft envelope, they are NOT automatically prompted to apply the matching template. They have to manually press the "Try automatic template matching on all documents" button, at which point the same template that would've been found automatically in the Embeddded Sending session is found. Is there a reason for this discrepancy?
bool retVal = true;
DocuSignService.DocuSignWS.Envelope envelope = new DocuSignService.DocuSignWS.Envelope();
if (credentials == null)
{
error = ErrorCode.NO_CREDENTIALS;
errorMessage = Strings.GetString("STR_DS_NOCREDS");
return false;
}
envelope.Documents = new DocuSignService.DocuSignWS.Document[itemList.Count];
if (credentials != null)
{
int index = 0;
foreach (Document document in itemList)
{
DocuSignService.DocuSignWS.Document doc = new DocuSignService.DocuSignWS.Document();
doc.ID = document.ID.ToString();
doc.Name = document.Name;
//get document bytes
doc.PDFBytes = document.data;
envelope.Documents[index] = doc;
index++;
}
Tab[] tabs = new DocuSignService.DocuSignWS.Tab[0];
envelope.Tabs = tabs;
envelope.Recipients = new Recipient[0];
//send?
envelope.AccountId = credentials.dsaccountid;
envelope.Subject = "Documents are ready for your signature";
envelope.EmailBlurb = "Documents are awaiting your signature.";
envelope.EnableWetSign = false;
DocuSignService.DocuSignWS.EnvelopeStatus envStatus = new DocuSignService.DocuSignWS.EnvelopeStatus();
using (ServiceWrapper client = new ServiceWrapper())
{
client.UserName = credentials.loginemail;
client.Password = credentials.loginpassword;
client.IntegratorKey = "xxx-xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx";
try
{
envStatus = client.CreateEnvelope(envelope);
}
catch (Exception e)
{
ErrorViewerWriter.Write(e);
error = ErrorCode.UPLOADFAILED;
errorMessage = e.Message;
return false;
}
}
}
return retVal;

Resources