Error 415 from IAV Rest API - Get verbose error message - yodlee

I have been trying the Instant Account Verification using the REST api but have run into a couple issues. I receive an error 415(Problem Updating Account) when calling either the addTransferAccountForItem or addItemAndStartVerificationDataRequest api. I'm wondering if there is any way to get a more detailed error message to understand what I'm doing wrong when making these calls. The error message is being returned in XML format although it should be returned in JSON.
Here's an example snippet of how I'm making the addItemAndStartVerificationDataRequest call. GDURL is a simple class that holds the url and concatenates all parameters into a string in format "param1=param1Value&param2=param2Value...".
Any nudge in the right direction would be appreciated. Thank you.
The url I am using are:
addItemAndStartVerificationDataRequestURL=
baseUrl+jsonsdk/ExtendedInstantVerificationDataService/addItemAndStartVerificationDataRequest/
addTransferAccountForItem=
baseUrl+jsonsdk/TransferAccountManagement/addTransferAccountForItem/
logger.info("Attempting to add item and start verification");
try{
GDURL iavUrl = new GDURL(restURL + addItemAndStartVerificationDataRequestURL);
iavUrl.addParameter("cobSessionToken", cobrandSessionToken);
iavUrl.addParameter("userSessionToken", userSessionToken);
iavUrl.addParameter("contentServiceId", contentServiceId);
iavUrl.addParameter("accountNumber", accountNumber);
iavUrl.addParameter("routingNumber", routingNumber);
iavUrl.addParameter("credentialFields.enclosedType", "com.yodlee.common.FieldInfoSingle");
iavUrl.addParameter("credentialFields[0].displayName", "UserID");
iavUrl.addParameter("credentialFields[0].fieldType.typeName", "IF_LOGIN");
iavUrl.addParameter("credentialFields[0].helpText", "4710");
iavUrl.addParameter("credentialFields[0].isEditable", "true");
iavUrl.addParameter("credentialFields[0].maxlength", "32");
iavUrl.addParameter("credentialFields[0].name", "LOGIN");
iavUrl.addParameter("credentialFields[0].size", "20");
iavUrl.addParameter("credentialFields[0].value", bankUsername);
iavUrl.addParameter("credentialFields[0].valueIdentifier", "LOGIN");
iavUrl.addParameter("credentialFields[0].valueMask", "LOGIN_FIELD");
iavUrl.addParameter("credentialFields[1].displayName", "Password");
iavUrl.addParameter("credentialFields[1].fieldType.typeName", "IF_PASSWORD");
iavUrl.addParameter("credentialFields[1].helpText", "11976");
iavUrl.addParameter("credentialFields[1].isEditable", "true");
iavUrl.addParameter("credentialFields[1].maxlength", "40");
iavUrl.addParameter("credentialFields[1].name", "PASSWORD");
iavUrl.addParameter("credentialFields[1].size", "20");
iavUrl.addParameter("credentialFields[1].value", bankPassword);
iavUrl.addParameter("credentialFields[1].valueIdentifier", "PASSWORD");
iavUrl.addParameter("credentialFields[1].valueMask", "LOGIN_FIELD");
HttpURLConnection connection = null;
connection = (HttpURLConnection) iavUrl.getURL().openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.addRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.connect();
String s="";
DataOutputStream wr = new DataOutputStream(connection.getOutputStream ());
wr.writeBytes(iavUrl.getParamString());
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
while(bufferedReader.ready())
s+=bufferedReader.readLine()+"/n";
}
System.out.println("add item response: /n" + s);
}catch(IOException e){
logger.error("error occured", e);
}

The 415(problem updating account) is an error thrown by Yodlee's data agent when it encounters an exception while trying to aggregate the account from end site. This particular error is thrown for situations where the end site terminates the session established by the data agent as the user might have already been logged in to the end site directly.
To know more about error code please refer this document

Related

How to get details about an error from RequestFailedException

I am trying to port code that had been using Microsoft.WindowsAzure.Storage classes to use the newer classes in Azure.Data.Tables, Azure.Storage.Queues, etc. From what I have been able to discern, the StorageException class has been replaced by RequestFailedException. Unfortunately, there are some properties in StorageException that do not exist in RequestFailedException, making it difficult to log appropriate messages when an exception is encountered (for example: RequestId, RequestInformation, etc.).
The migration document does not address the differences between StorageException and the new RequestFailedException, or how to get error details from it.
It seems that either the new libraries are not yet mature enough for prime time, or maybe it is just because the documentation is lacking the relevant information and I can't find the appropriate methodologies for getting all of the error information from the RequestFailedException.
Does anyone know how to get more data out of the new class? Here are some examples of what we used to do:
catch (StorageException e)
{
operation.Telemetry.Properties.Add("AzureServiceRequestID", e.RequestInformation.ServiceRequestID);
Changing the above to use RequestFailedException is a problem because RequestInformation is not a property of RequestFailedException.
Here is another case:
catch (StorageException se)
{
var ri = se.RequestInformation;
if (ri.ErrorCode == "TableNotFound")
{
Logger.Info(
$"{SJResult.MakeInfo(64)} {ri.HttpStatusCode} {ri.HttpStatusMessage}, Storage Service code={ri.ErrorCode} This is OK if HL7 has not yet received messages."); // 60240040
}
else
{
Logger.Error(
$"{SJResult.MakeError(65)} HttpStatusCode: {ri.HttpStatusCode}, HttpStatusMessage: {ri.HttpStatusMessage}, Storage Service code={ri.ErrorCode}, " +
$"Extended.ErrorCode: {ri.ExtendedErrorInformation.ErrorCode} Extended.ErrorMessage: {ri.ExtendedErrorInformation.ErrorMessage}"); // E0240041
throw;
}
Again, RequestInformation is not available in RequestFailedException.
How do we get access to all the detailed information (RequestInformation) about an exception from the new RequestFailedException class?
As you can see the definition of RequestFailedException Class (Azure) and constuctors in the latest version of azure sdk.
RequestFailedException(Int32, String, String, Exception) : gives HTTP status code ,specified error message, error code, and a reference to the inner exception .
And
RequestFailedException(Response)
Gives error message, HTTP status code, error code obtained from the specified response.
The response in the argument represents the HTTP response from the service which has ClientRequestId as one of the properties as shown in the table which gets client request id that was sent to server in the form of x-ms-client-request-id headers.You can try the same while catching the error in the try-catch block.
In exception class you can give
public class RequestFailedException : Exception
{
...
public RequestFailedException(int status, string message, string? errorCode, Exception? innerException) : base(message , innerException) { }
}
Or use RequestFailedException(Response) from which you can get ClientRequestId.
I’ve not tested it myself, but please check if below can be worked around which is taken from the below references or check if something similar can give an idea.Also see if content property can be retrieved as a part of response.
try
{
...
}
catch (Exception aex)
{
foreach (var ex in aex.InnerExceptions)
{
if (ex is RequestFailedException except)
{
var innerException = excep.InnerException;
if (innerException != null && innerException.GetType() == typeof(WebException))
{
WebException webEx = innerException as WebException;
WebResponse resp = webEx.Response;
var responseHeaders = resp.Headers;
string requestId = responseHeaders["x-ms-request-id"];
Console.WriteLine("Request Id: " + requestId);
Console.WriteLine(except.InnerException.Message);
}
else
{
// (not a RequestFailedException)
Console.WriteLine($"{ex.Message}");
}
}
References:
How can I get Request ID when an exception occurs? (microsoft.com)
c# - How can you catch a RequestFailedException if making multiple
DownloadToAsync calls in parallel? - Stack Overflow

WebRequest HTTP error code without try-catch (VB.NET) [duplicate]

I am in a situation where when I get an HTTP 400 code from the server, it is a completely legal way of the server telling me what was wrong with my request (using a message in the HTTP response content)
However, the .NET HttpWebRequest raises an exception when the status code is 400.
How do I handle this? For me a 400 is completely legal, and rather helpful. The HTTP content has some important information but the exception throws me off my path.
It would be nice if there were some way of turning off "throw on non-success code" but if you catch WebException you can at least use the response:
using System;
using System.IO;
using System.Web;
using System.Net;
public class Test
{
static void Main()
{
WebRequest request = WebRequest.Create("http://csharpindepth.com/asd");
try
{
using (WebResponse response = request.GetResponse())
{
Console.WriteLine("Won't get here");
}
}
catch (WebException e)
{
using (WebResponse response = e.Response)
{
HttpWebResponse httpResponse = (HttpWebResponse) response;
Console.WriteLine("Error code: {0}", httpResponse.StatusCode);
using (Stream data = response.GetResponseStream())
using (var reader = new StreamReader(data))
{
string text = reader.ReadToEnd();
Console.WriteLine(text);
}
}
}
}
}
You might like to encapsulate the "get me a response even if it's not a success code" bit in a separate method. (I'd suggest you still throw if there isn't a response, e.g. if you couldn't connect.)
If the error response may be large (which is unusual) you may want to tweak HttpWebRequest.DefaultMaximumErrorResponseLength to make sure you get the whole error.
I know this has already been answered a long time ago, but I made an extension method to hopefully help other people that come to this question.
Code:
public static class WebRequestExtensions
{
public static WebResponse GetResponseWithoutException(this WebRequest request)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
try
{
return request.GetResponse();
}
catch (WebException e)
{
if (e.Response == null)
{
throw;
}
return e.Response;
}
}
}
Usage:
var request = (HttpWebRequest)WebRequest.CreateHttp("http://invalidurl.com");
//... (initialize more fields)
using (var response = (HttpWebResponse)request.GetResponseWithoutException())
{
Console.WriteLine("I got Http Status Code: {0}", response.StatusCode);
}
Interestingly, the HttpWebResponse.GetResponseStream() that you get from the WebException.Response is not the same as the response stream that you would have received from server. In our environment, we're losing actual server responses when a 400 HTTP status code is returned back to the client using the HttpWebRequest/HttpWebResponse objects. From what we've seen, the response stream associated with the WebException's HttpWebResponse is generated at the client and does not include any of the response body from the server. Very frustrating, as we want to message back to the client the reason for the bad request.
I had similar issues when trying to connect to Google's OAuth2 service.
I ended up writing the POST manually, not using WebRequest, like this:
TcpClient client = new TcpClient("accounts.google.com", 443);
Stream netStream = client.GetStream();
SslStream sslStream = new SslStream(netStream);
sslStream.AuthenticateAsClient("accounts.google.com");
{
byte[] contentAsBytes = Encoding.ASCII.GetBytes(content.ToString());
StringBuilder msg = new StringBuilder();
msg.AppendLine("POST /o/oauth2/token HTTP/1.1");
msg.AppendLine("Host: accounts.google.com");
msg.AppendLine("Content-Type: application/x-www-form-urlencoded");
msg.AppendLine("Content-Length: " + contentAsBytes.Length.ToString());
msg.AppendLine("");
Debug.WriteLine("Request");
Debug.WriteLine(msg.ToString());
Debug.WriteLine(content.ToString());
byte[] headerAsBytes = Encoding.ASCII.GetBytes(msg.ToString());
sslStream.Write(headerAsBytes);
sslStream.Write(contentAsBytes);
}
Debug.WriteLine("Response");
StreamReader reader = new StreamReader(sslStream);
while (true)
{ // Print the response line by line to the debug stream for inspection.
string line = reader.ReadLine();
if (line == null) break;
Debug.WriteLine(line);
}
The response that gets written to the response stream contains the specific error text that you're after.
In particular, my problem was that I was putting endlines between url-encoded data pieces. When I took them out, everything worked. You might be able to use a similar technique to connect to your service and read the actual response error text.
Try this (it's VB-Code :-):
Try
Catch exp As WebException
Dim sResponse As String = New StreamReader(exp.Response.GetResponseStream()).ReadToEnd
End Try
An asynchronous version of extension function:
public static async Task<WebResponse> GetResponseAsyncNoEx(this WebRequest request)
{
try
{
return await request.GetResponseAsync();
}
catch(WebException ex)
{
return ex.Response;
}
}
This solved it for me:
https://gist.github.com/beccasaurus/929007/a8f820b153a1cfdee3d06a9c0a1d7ebfced8bb77
TL;DR:
Problem:
localhost returns expected content, remote IP alters 400 content to "Bad Request"
Solution:
Adding <httpErrors existingResponse="PassThrough"></httpErrors> to web.config/configuration/system.webServer solved this for me; now all servers (local & remote) return the exact same content (generated by me) regardless of the IP address and/or HTTP code I return.

Exception handling ExchangeWebServices php-ews

I use https://github.com/jamesiarmes/php-ews library to access my exchange account.
If I used correct credentials to create a ExchangeWebServices object, I get accurate response.
$ews = new ExchangeWebServices("outlook.office365.com", "tes#abc.com", "test123");
$request = new EWSType_FindItemType();
$response = $ews->FindItem($request);
But If the credentials are wrong it breaks the site by throwing an exception as
EWS_Exception: SOAP client returned status of 401 in ExchangeWebServices->processResponse()
Is there any way to get the response as "failed" or some boolean value instead of the error message?
There's no way to get the response as a boolean, but you can do something like
$ews = new ExchangeWebServices("outlook.office365.com", "tes#abc.com", "test123");
$request = new EWSType_FindItemType();
try {
$response = $ews->FindItem($request);
} catch (\Exception $e) {
//The response failed.
}
Also, that version of php-ews is out of date and unmaintained. Might I suggest you try https://github.com/Garethp/php-ews

Adding account fails with obscure exception( i.e. IncompleteArgumentException)

I am trying to use the REST API to add accounts to my private zone implementation. I have been modifying SDK sample code, but my minor modification seems to result in failure and I'm not sure why. Note: obviously, I'm not including the actual username and password. Also, the site ID is for AMEX.
Here's the code (again, which is modified from example code):
public String addSiteAccount(String cobrandSessionToken,
String userSessionToken) {
DefaultHttpClient httpclient = new DefaultHttpClient();
String url = HOST_URI + ADD_SITE_ACC;
try {
HttpsURLConnection.setDefaultHostnameVerifier(new NullHostnameVerifier());
PostMethod pm = new PostMethod(url);
pm.addParameter(paramNameCobSessionToken, cobrandSessionToken);
pm.addParameter(paramNameUserSessionToken, userSessionToken);
String theUsername = "...whatever...";
String thePassword = "...whatever...";
pm.addParameter("credentialFields[0].name", "LOGIN");
pm.addParameter("credentialFields[0].displayName", "Username");
pm.addParameter("credentialFields[0].isEditable", "true");
pm.addParameter("credentialFields[0].isOptional", "false");
pm.addParameter("credentialFields[0].helpText", "22059");
pm.addParameter("credentialFields[0].valuePattern", "null");
pm.addParameter("credentialFields[0].defaultValue", "null");
pm.addParameter("credentialFields[0].value", theUsername);
pm.addParameter("credentialFields[0].validValues", theUsername);
pm.addParameter("credentialFields[0].displayValidValues", "null");
pm.addParameter("credentialFields[0].valueIdentifier", "LOGIN");
pm.addParameter("credentialFields[0].valueMask", "LOGIN_FIELD");
pm.addParameter("credentialFields[0].fieldType", "LOGIN");
pm.addParameter("credentialFields[0].validationRules", "null");
pm.addParameter("credentialFields[0].size", "20");
pm.addParameter("credentialFields[0].maxlength", "40");
pm.addParameter("credentialFields[0].userProfileMappingExpression",
"null");
pm.addParameter("credentialFields[0].fieldErrorCode", "1");
pm.addParameter("credentialFields[0].fieldErrorMessage", "null");
pm.addParameter("credentialFields[1].name", "PASSWORD");
pm.addParameter("credentialFields[1].displayName", "Password");
pm.addParameter("credentialFields[1].isEditable", "true");
pm.addParameter("credentialFields[1].isOptional", "false");
pm.addParameter("credentialFields[1].helpText", "AUS_Row_Name");
pm.addParameter("credentialFields[1].valuePattern", "null");
pm.addParameter("credentialFields[1].defaultValue", "null");
pm.addParameter("credentialFields[1].value", thePassword);
pm.addParameter("credentialFields[1].validValues", thePassword);
pm.addParameter("credentialFields[1].displayValidValues", "null");
pm.addParameter("credentialFields[1].valueIdentifier", "PASSWORD");
pm.addParameter("credentialFields[1].valueMask", "LOGIN_FIELD");
pm.addParameter("credentialFields[1].fieldType", "PASSWORD");
pm.addParameter("credentialFields[1].validationRules", "null");
pm.addParameter("credentialFields[1].size", "20");
pm.addParameter("credentialFields[1].maxlength", "40");
pm.addParameter("credentialFields[1].userProfileMappingExpression",
"null");
pm.addParameter("credentialFields[1].fieldErrorCode", "1");
pm.addParameter("credentialFields[1].fieldErrorMessage", "null");
pm.addParameter("credentialFields.objectInstanceType",
"[Lcom.yodlee.common.FieldInfoSingle;");
pm.addParameter("siteId", "12");
// pm.addParameter("siteId.objectInstanceType", "long");
HttpClient hc = new HttpClient();
hc.executeMethod(pm);
String source = pm.getResponseBodyAsString();
System.out.println(pm.getResponseBodyAsString());
} catch (Exception e) {
e.printStackTrace();
} finally {
httpclient.getConnectionManager().shutdown();
}
return userSessionToken;
}
The result I get is:
{"errorOccurred":"true","exceptionType":"Exception Occurred","referenceCode":"_2ee6cfc1450c-42b8-86ec-7caef38f17bc"}
After failing here, I tried to simplify the code based on the minimum required parameters as mentioned here.
pm.addParameter("siteId", "12");
pm.addParameter("credentialFields.enclosedType",
"com.yodlee.common.FieldInfoSingle");
pm.addParameter("credentialFields[0].fieldType.typeName", "IF_LOGIN");
pm.addParameter("credentialFields[0].name", "LOGIN1");
pm.addParameter("credentialFields[0].size", "20");
pm.addParameter("credentialFields[0].value", theUsername);
pm.addParameter("credentialFields[0].valueIdentifier", "LOGIN");
pm.addParameter("credentialFields[0].valueMask", "LOGIN_FIELD");
pm.addParameter("credentialFields[0].isEditable", "true");
pm.addParameter("credentialFields[0].displayName", "Username");
pm.addParameter("credentialFields[1].fieldType.typeName", "IF_PASSWORD");
pm.addParameter("credentialFields[1].name", "PASSWORD");
pm.addParameter("credentialFields[1].size", "20");
pm.addParameter("credentialFields[1].value", thePassword);
pm.addParameter("credentialFields[1].valueIdentifier", "PASSWORD1");
pm.addParameter("credentialFields[1].valueMask", "LOGIN_FIELD");
pm.addParameter("credentialFields[1].isEditable", "true");
However, this fails with:
{"errorOccurred": "true", "exceptionType": "com.yodlee.core.IncompleteArgumentException", "referenceCode": "_0a549c3d-11f4-4c98-8e65-7f845fd83f54","message":"LOGIN"}
This also makes me wonder: do I need to make calls to searchSite() and getLoginForm() before issuing the code above? In our application, we have the site IDs and the login information, so we do not need to interact with a user per se. But I'm not sure if workflow is somehow being tracked on the backend, and we're violating it or something.
Any help would be appreciated. Incidentally, if there are any better examples for using REST to add accounts, it would be greatly appreciated. I have searched the developer portal, but it's a bit difficult to find a concise example. Thank you.
Yes, please we suggest you to use the field's value which you receive in response of getLoginForm API to provide the required input parameters in addSiteAccount1 API.
And to get this working please correct this parameter's value.
credentialFields[0].name= "LOGIN1" instead of "LOGIN"
Ideally that should work but in case you still get same error then please change below mentioned parameter's value as well.
"credentialFields[0].valueIdentifier", "LOGIN" to "LOGIN1"
This should help.

httpwebrequest in windows phone 8 app throws "The remote server returned an error: NotFound."?

i am developing an windows phone 8 app , in my app i am calling services and downloading some data into my app.
i am testing my app in windows phone 8 emulator, many times it throws this error :
"The remote server returned an error: NotFound."
This is how i have created and used my httpwebrequest :-
public async Task<string> ServiceRequest(string serviceurl, string request, string methodname)
{
string response = "";
try
{
var httpwebrequest = WebRequest.Create(new Uri(serviceurl)) as HttpWebRequest;
httpwebrequest.Method = "POST";
httpwebrequest.Headers["SOAPAction"] = "http://tempuri.org/" + iTestservice + "/" + methodname + "";
httpwebrequest.ContentType = "text/xml";
byte[] data = Encoding.UTF8.GetBytes(request);
using (var requestStream = await Task<Stream>.Factory.FromAsync(httpwebrequest.BeginGetRequestStream, httpwebrequest.EndGetRequestStream, null))
{
await requestStream.WriteAsync(data, 0, data.Length);
}
var httpTask = httpRequest(httpwebrequest);
var completeTask = await Task.WhenAny(httpTask, TaskEx.Delay(300000));
if (completeTask == httpTask)
return await httpTask;
else
httpwebrequest.Abort();
throw new TimeoutException("Service Timed Out");
}
catch (TimeoutException Tex)
{
throw Tex;
}
catch (Exception ex)
{
throw ex;
}
}
public async Task<string> httpRequest(HttpWebRequest request)
{
string received;
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
using (var responseStream = response.GetResponseStream())
{
using (var sr = new StreamReader(responseStream))
{
received = await sr.ReadToEndAsync();
}
}
}
return received;
}
i am really not able to figure what was the issue
Please note :-
i tried to open the site (service URL which my app is trying to access) in my emulator browser , it opened correctly , i wasn't facing any issues.
1)is that the problem with my code, if so i request you please correct me ??
2)is this any emulator issue or any connectivity issue ??
3)is this any certification issue opening in emulator ??
Even after a long research to how to fix the issue i was not able to fix it .
Please Help me out.
Thanks in Advance.
I have come across this issue when the webservice requests take longer than 60 seconds. I have read reports that the emulator does not throw this error, but only an actual device. In my experience however, I have had this happen on both emulator and device. This is a default timeout setting that cannot be altered, even if you change it in the config. This issue has been around since WP7.
I've only found this question asked/blogged about once elsewhere. Seems that not a lot of people have picked this up.
AFAIK, Microsoft are aware of this, but don't plan on fixing it. (Proven by the fact that it has been around since WP7, and wasn't fixed for WP8). My guess is that they are of the opinion that web calls shouldn't be taking longer than 60 seconds in any case.
I just resolved it adding empty credentials to https requests, like this
httpwebrequest.Credentials = new NetworkCredential("", "");
here he explains why
http://blog.toetapz.com/2010/11/15/windows-phone-7-and-making-https-rest-api-calls-with-basic-authentication/