WCF "The given key was not present in the dictionary" - c#

I'm getting this error even though I'm not using a Dictionary, and what's weird is that it's when I call the service.
wsSoapClient client = null;
try
{
client = new wsSoapClient();
}
catch (Exception ex)
{
// - Error in the web.config
}
try
{
SendData sendData = new SendData();
sendData.finishDate = myVar.FinishDate;
sendData.startDate = myVar.StartDate;
// - Other fields
// - This lines throw the error below
ClientResult result = client.FinishCourse(sendData);
}
catch (Exception ex)
{
// - Message: The given key was not present in the dictionary.
}
The stack trace:
StackTrace: at System.Collections.Generic.Dictionary``2.get_Item(TKey key)
at Project.Model.CourseService.FinishCourse(XmlNode node)
The service is up to date, and I couldn't find info on this anywhere else. There's two similar questions on SO but they are about Silverlight and I couldn't figure a relation between this (regular C# WCF calling a service) and the solutions.
What causes this and how do I fix it?
(Edit) More Info: The binding is a basicHttpBinding, http only.
Edit²: The WSDL.
Edit³: Found the issue. Apparently, there was already another error (a value larger than the field allows), the service was returning an error but for some reason, WCF didn't take that as error and didn't threw the exception, and I'm guessing it tried to proceed normally, causing this dictionary error since the XML is not what is was expecting.

Assuming your service method is not the one throwing the exception, then it might be the case with the deserialization of the soap message (i.e request object) that happens on the service side.
Check your code(or wsdl) for SendData and see if there are non nullable properties which you are not setting in the request object i.e. sendData object. Missing required properties might cause issues during deserialization.
Posting the code of SendData and\or FinishCourse service method would be great in analyzing the possible issue.

Related

Passing exception data between two applications

I don't know if this has been already answered or not. But, I am unable to find the example or cause of this problem.
Application 1:
try
{
//Read request and check for the request header element from the soap request
//validating request and salt
...here it might gets failed.
_requestValidationService.ValidateRequest();
}
catch (Exception ex)
{
ex.Data.Add("Exception", "test");
throw ex;
}
Application 2:
catch (Exception ex)
{
string aa = Convert.ToString(ex.Data["Exception"]);
throw ex;
}
I don't know what I am missing here. But aa seems to be always empty and ex.Data.Count is always zero.
I just want to pass one code between two applications without adding new class of an exception.
Note: These two applications are wcf calls.
[EDIT1]
Application 1 validate request is the IDispatchMessageInspector AfterReceiveRequest
Exceptions are not propagated to clients from a WCF service. Instead, a SOAP Fault (assuming you are using SOAP) will be sent to the client.
You can include exception details in the SOAP Fault, but in general it is not recommended to do so in production.
IMHO a better approach is to implement an IErrorHandler that provides the Fault with whatever data you want to send to the client, and also gives you the opportunity to log the exception server-side.
You can then catch FaultException on the client and have access to the data added by your custom error handler.
The exception class is designed by one throw / catch pair. If you should add any additional information to a cached exception, use the inner exception feature by the rethrow technique:
catch (Exception ex)
{
ErrorHandling.WriteError(ex);
var newEx = new MyException("Additional message", ex) // wrap the original exception instance.
newEx.Data.Add("Exception", "test");
throw newEx;
}
After catching the wrapper exception you can find the original exception in the InnerException property. Another advantage that the original and wrapper exceptions contain their own stack trace so it is easier to find location of error source.

Request from C# to Apache: The underlying connection was closed: An unexpected error occurred on a receive

I have two linux Apache servers running behind load balancer.
On both Apache server I have installed exactly the same installation of Yourls API for shortening URLs. I am sending request to that Yourls API to short URL.
Request to these servers are sent from C# production site, for shortening URLs.
It worked fine for months, and then suddenly on request I start receiving error:
The underlying connection was closed: An unexpected error occurred on
a receive.
Nothing is changed in meanwhile. Apache server doesn't have any security restriction or something.
This code for request:
public dynamic SendRequest(string action, NameValueCollection parameters = null)
{
var client = new NoKeepAliveWebClient();
string jsonResult = string.Empty;
dynamic result;
//we need to form url with requests
var data = new NameValueCollection();
data["format"] = "json";
data["action"] = action;
data["signature"] = this.key;
if (parameters != null)
{
foreach (string key in parameters)
{
data[key] = parameters[key];
}
}
try
{
byte[] byteResult = client.UploadValues(url, data);
jsonResult = Encoding.UTF8.GetString(byteResult);
dynamic tempResult = JObject.Parse(jsonResult);
result = tempResult;
}
catch (Exception ex)
{
logger.Error("Error SendRequest (Action: {0}) Json: {1} {2}",
action,
jsonResult,
ex.Message + ex.StackTrace);
throw;
}
return result;
}
I am not getting this error for all request, but I am getting it for most of them.
I don't know anything about C#. I am responsible for Apache server, and I cannot find anything on those servers what can block those requests, or cause errors like this.
So my question is:
Does this can be caused by Apache server or it is specific for C#. Or maybe it have something with load balancer.
I guess that question is kind dumb, but I need to know asap which side is causing the problem.
EDIT
By adding more logs on C# side I got detailed errors.
ErrorType: WebException ErrorMessage: The underlying connection was closed: An unexpected error occurred on a receive.
InnerExceptionType: IOException InnerExceptionMessage: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
EDIT
I concluded that the problem is with load balancer (hproxy)
I have one server on which is installed hproxy. Hproxy serve two aplications servers. When I am sending requests over hproxy I am getting those errors.
Now I stopped using hproxy and I am calling requests directly to one aplications servers and it works fine now, without errors. But I need it works with hproxy.
So any idea, what in hproxy can cause those errors.

How do I get an HTTP status code from TTransport exceptions?

I'm using a thrift HttpClient (C#) to make web requests to a web server I've set up, and if that server returns something other than 200 (or 202 I imagine), my request throws a TTransport exception.
I'd like to respond to this exception based on the specific status code returned, but I don't see anything that exposes the status code in the exception's interface. Have I missed something? I know the exception message contains the status code, but I'd rather not have to parse that message to get at the status code.
If the server encounters an processing error, the recommended method is not throwing a HTTP 500. Instead, the server should signal this by means of an exception. Consider the following Thrift IDL:
exception MyProcessingError
{
1: string reason
2: string errorDetails
3: string recommendedAction
}
service FooBar {
void ProcessPayments( 1: double amount; 2: string receiver)
throws (1: MyProcessingError mpe)
}
Similar to args and struct fields, multiple exception types can be declared. The client can catch these exceptions as usual:
try
{
client.ProcessPayments( 47.11, "Dagobert");
}
catch (MyProcessingError e)
{
// process exception
}
Remarks
The server may only throw exceptions that are declared in the IDL for
the particular call.
Furthermore, oneway calls never return any value, thus no
exceptions either.

Dealing with incorrect HTTP header body size values?

Using C# ASP.NET MVC, when calling a webservice on a Magento site:
Sometimes a Magento site will send wrong HTTP headers, specifically the body-size header saying that the body is bigger than it really is. For example it might say body-size=1000, but the body only consists of 999 bytes. Despite the header being incorrect, the body is correct so I would still like to be able to process it.
Now when I try to read that response in C#
var invoiceInfo = _magentoService.salesOrderInvoiceInfo(sessionId, invoiceId);
It throws an exception:
Connection closed by remote host
Which makes sense kindof, because its trying to read the 1000th byte but its not there. And to make it worse, the code that reads the body is buried deep within the .NET framework, so I cant change it:
[System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:Mage_Api_Model_Server_V2_HandlerAction", RequestNamespace="urn:Magento", ResponseNamespace="urn:Magento")]
[return: System.Xml.Serialization.SoapElementAttribute("result")]
public salesOrderInvoiceEntity salesOrderInvoiceInfo(string sessionId, string invoiceIncrementId) {
object[] results = this.Invoke("salesOrderInvoiceInfo", new object[] {
sessionId,
invoiceIncrementId}); // exception thrown here
return ((salesOrderInvoiceEntity)(results[0]));
}
I can't change the Magento site, or fix whatever problem is causing this (its a 3rd parties webserver).
Is there anything I can do to change the behavior of my own C# code? I would like to be able to somehow force it to stop when it reaches the end of the body and ignore this exception if this case arises
I don't know that this will work, but have you tried putting the code in a try / catch block and ignoring the exception? Does results == null?
Like this:
[System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:Mage_Api_Model_Server_V2_HandlerAction", RequestNamespace="urn:Magento", ResponseNamespace="urn:Magento")]
[return: System.Xml.Serialization.SoapElementAttribute("result")]
public salesOrderInvoiceEntity salesOrderInvoiceInfo(string sessionId, string invoiceIncrementId) {
try
{
object[] results = this.Invoke("salesOrderInvoiceInfo", new object[] {
sessionId,
invoiceIncrementId}); // exception thrown here
}
catch(Exception) {}
if(results != null && results.Count() > 0) return ((salesOrderInvoiceEntity)(results[0]));
throw new Exception("results is null");
}
Try solution from here (changing API endpoint to api.php): stackoverflow.com/a/36200828/1936722
Basically change the API url from:
domain.com/index.php/api/v2_soap/index/wsdl/1
to:
domain.com/api/v2_soap/?wsdl=1

How to handle a exception thrown in c# by a javascript web app?

I'm developing a web application with a client side build with html5 and javascript using, overall, dojo framework (I'm using xhr.post function to communicate with server). The server side is an asmx service in c#.
Here comes the problem: when a webmethod of my service throws an exception:
try
{
throw new Exception("TEST");
}
catch (Exception ex)
{
throw ex;
// TODO: send some info to the client about the error
}
the client is realized than an error has occured and fires the error callback function:
deferred = xhr.post({
url: that.config.urlService,
handleAs: that.config.handleAs,
contentType: that.config.contentType,
postData: that.config.parameters
});
deferred.then(function (res) {
that.success(res);
},
function (err) {
if (that.config.callbackFail) {
that.config.callbackFail(err, that.config.parameters);
}
}
);
But in the 'err' paramater I don't have the exception info, I have the message:
'NetworkError: 500 Internal Server Error - http:/.../Services/Applications/Metrawa/ServiceManagement/WSJob.asmx/Filter'
and inspecting the call to server with firebug, in the response tab I can see strange characters, like if the exception hasn't been serialized.
What I want is to get the exception info in javascript. I've searched some info about this, like to create an own serializable exception class, but it doesn´t work neither. Any solution?
Thanks in advance.
You may opt to handle the exception in your server-side code and send it back as JSON, XML or even String--i.e. something your client can understand.
I would catch the exception server side and always return a valid object with a "Result" property:
eg res.Result (as "OK" or "ERR" etc and handle that on the client)

Categories