MonoTouch Parameter Array Length does not match the number of message body parts exception - wcf

I am writing a MonoTouch app for iPhone and i am getting the following exception when calling a WCF web service.
Parameter array length does not match the number of message body parts at System.ServiceModel.Dispatcher.WebMessageFormatter+WebClientMessageFormatter.SerializeRequest (System.ServiceModel.Channels.MessageVersion messageVersion, System.Object[] parameters) [0x0003e] in /Developer/MonoTouch/Source/mono/mcs/class/System.ServiceModel.Web/System.ServiceModel.Dispatcher/WebMessageFormatter.cs:310
at System.ServiceModel.Description.WebHttpBehavior+ClientPairFormatter.SerializeRequest (System.ServiceModel.Channels.MessageVersion messageVersion, System.Object[] parameters) [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/System.ServiceModel.Web/System.ServiceModel.Description/WebHttpBehavior.cs:142
at System.ServiceModel.MonoInternal.ClientRuntimeChannel.CreateRequest (System.ServiceModel.Dispatcher.ClientOperation op, System.Object[] parameters) [0x0001e] in /Developer/MonoTouch/Source/mono/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs:611
at System.ServiceModel.MonoInternal.ClientRuntimeChannel.Request (System.ServiceModel.Description.OperationDescription od, System.Object[] parameters) [0x0002d] in /Developer/MonoTouch/Source/mono/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs:512
at System.ServiceModel.MonoInternal.ClientRuntimeChannel.DoProcess (System.Reflection.MethodBase method, System.String operationName, System.Object[] parameters) [0x00038] in /Developer/MonoTouch/Source/mono/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs:482
at System.ServiceModel.MonoInternal.ClientRuntimeChannel.Process (System.Reflection.MethodBase method, System.String operationName, System.Object[] parameters) [0x00000] in /Developer/MonoTouch/Source/mono/mcs/class/System.ServiceModel/System.ServiceModel/ClientRuntimeChannel.cs:462
I am calling the service with the following methods (Some namespaces have been removed for readability):
public void Begin ()
{
try
{
WebHttpBinding bnd = new WebHttpBinding (WebHttpSecurityMode.Transport);
bnd.MaxBufferSize=2147483647;
bnd.MaxReceivedMessageSize=2147483647;
EndpointAddress addr = new EndpointAddress (new Uri(this.Url));
ServiceClient service = new ServiceClient (bnd, addr);
service.Endpoint.Behaviors.Add(new WebHttpBehavior());
Login login = new Login()
{
InstitutionId=this.InstitutionNumber.ToString ("D4"),
CompanyNumber = (int)this.CompanyId,
Password = this.Password,
UserName = this.Username
};
LoginRequest loginRequest = new LoginRequest{} (GetClientLoginData(), login);
service.LoginCompleted += HandleServiceLoginCompleted;
service.LoginAsync(loginRequest);
}
catch (Exception e)
{
if(failed != null)
{
failed(new ErrorInformation(e));
}
}
}
void HandleServiceLoginCompleted (object sender, LoginCompletedEventArgs e)
{
if(e.Cancelled)
{
if (failed != null)
{
failed (new ErrorInformation ("Request was cancelled"));
}
}
else if(e.Error != null)
{
if (failed != null)
{
failed (new ErrorInformation (e.Error));
}
}
else
{
ServiceClient service = sender as ServiceClient;
LoginResponse response = e.Result;
if (response.LoginResult)
{
if (success != null)
success ();
}
else
{
if (failed != null)
failed (new ErrorInformation (response.errmsg));
}
}
}
When I run this e.Error in HandleServiceLoginCompleted is not null (it is the above exception). I ran wireshark and no packets are sent to the server at all. The service works correctly when called by other means (such as ASP.NET web pages.) I generated the service reference using silverlight's slsvcutil.exe.

Set bnd.ReaderQuotas.MaxArrayLength = int.MaxValue
There are also some other limits that you can increase in ReaderQuotas.

Related

HttpClient.SendAsync in DotNetCore - Is a Deadlock Possible?

We get an occasional TaskCanceledException on a call that, according to our logs, completes well inside the timeout we configure for the request. The first log entry is from the server. This is the last thing the method logs out before returning a JsonResult (MVC 4 Controller).
{
"TimeGenerated": "2021-03-19T12:08:48.882Z",
"CorrelationId": "b1568096-fdbd-46a7-8b69-58d0b33f458c",
"date_s": "2021-03-19",
"time_s": "07:08:37.9582",
"callsite_s": "...ImportDatasets",
"stacktrace_s": "",
"Level": "INFO",
"class_s": "...ReportConfigController",
"Message": "Some uninteresting message",
"exception_s": ""
}
In this case, the request took about 5 minutes to complete. Then 30 minutes later, our caller throws the task canceled exception from HttpClient.SendAsync:
{
"TimeGenerated": "2021-03-19T12:48:27.783Z",
"CorrelationId": "b1568096-fdbd-46a7-8b69-58d0b33f458c",
"date_s": "2021-03-19",
"time_s": "12:48:17.5354",
"callsite_s": "...AuthorizedApiAccessor+<CallApi>d__29.MoveNext",
"stacktrace_s": "TaskCanceledException
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)\r\n
at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n
at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)\r\n
at ...AuthorizedApiAccessor.CallApi(String url, Object content, HttpMethod httpMethod, AuthenticationType authType, Boolean isCompressed)\r\nIOException
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)\r\n
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.GetResult(Int16 token)\r\n
at System.Net.Security.SslStream.<FillBufferAsync>g__InternalFillBufferAsync|215_0[TReadAdapter](TReadAdapter adap, ValueTask`1 task, Int32 min, Int32 initial)\r\n
at System.Net.Security.SslStream.ReadAsyncInternal[TReadAdapter](TReadAdapter adapter, Memory`1 buffer)\r\n
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)\r\nSocketException",
"Level": "ERROR",
"class_s": "...AuthorizedApiAccessor",
"Message": "Nothing good",
"exception_s": "The operation was canceled."
}
Given that within the process that makes the request we block an async call (.Result -- hitting a brownfield caching implementation that doesn't support async), my first guess was that we had a deadlock as described by Stephen Cleary. But the caller is a dotnetcore 3.1 application, so that kind of deadlock is not possible.
Our usage of HttpClient is pretty standard, I think. This is the method that ultimately makes the call:
private async Task<string> CallApi(string url, object content, HttpMethod httpMethod, AuthenticationType authType, bool isCompressed)
{
try
{
var request = new HttpRequestMessage()
{
RequestUri = new Uri(url),
Method = httpMethod,
Content = GetContent(content, isCompressed)
};
AddRequestHeaders(request);
var httpClient = _httpClientFactory.CreateClient(HTTPCLIENT_NAME);
httpClient.Timeout = Timeout;
AddAuthenticationHeaders(httpClient, authType);
var resp = await httpClient.SendAsync(request);
var responseString = await (resp.Content?.ReadAsStringAsync() ?? Task.FromResult<string>(string.Empty));
if (!resp.IsSuccessStatusCode)
{
var message = $"{url}: {httpMethod}: {authType}: {isCompressed}: {responseString}";
if (resp.StatusCode == HttpStatusCode.Forbidden || resp.StatusCode == HttpStatusCode.Unauthorized)
{
throw new CustomException(message, ErrorType.AccessViolation);
}
if (resp.StatusCode == HttpStatusCode.NotFound)
{
throw new CustomException(message, ErrorType.NotFound);
}
throw new CustomException(message);
}
return responseString;
}
catch (CustomException) { throw; }
catch (Exception ex)
{
var message = "{Url}: {HttpVerb}: {AuthType}: {IsCompressed}: {Message}";
_logger.ErrorFormat(message, ex, url, httpMethod, authType, isCompressed, ex.Message);
throw;
}
}
We are at a loss for theories on this behavior. We've seen the task cancelation between 3-5 times a month within a few hundred successful requests, so it's intermittent, but far from rare.
Where else should we be looking for the source of what behaves like a deadlock?
update
Might be relevant to note that we are using the standard HttpClientHandler. The retry policies have been added recently, but we don't retry on a long-running POST, which is the scenario above.
builder.Services.AddHttpClient(AuthorizedApiAccessor.HTTPCLIENT_NAME)
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler()
{
AutomaticDecompression = System.Net.DecompressionMethods.Deflate | System.Net.DecompressionMethods.GZip
})
.AddRetryPolicies(retryOptions);

NPE when trying to use Jetty async HTTP client

When trying to use Firebase Cloud Messaging by Google with the help of non-blocking Jetty HTTP client in a simple test case that I have prepared at GitHub -
private static final HttpClient sHttpClient = new HttpClient();
private static final Response.ContentListener sFcmListener = new Response.ContentListener() {
#Override
public void onContent(Response response, ByteBuffer content) {
if (response.getStatus() != 200) {
return;
}
String body = StandardCharsets.UTF_8.decode(content).toString();
System.out.printf("onContent: %s\n", body);
Map<String, Object> resp = (Map<String, Object>) JSON.parse(body);
try {
Object[] results = (Object[]) resp.get(FCM_RESULTS);
Map result = (Map) results[0];
String error = (String) result.get(FCM_ERROR);
if (FCM_NOT_REGISTERED.equals(error)) {
// TODO delete invalid FCM token from the database
}
} catch (Exception ignore) {
}
}
};
public static void main(String[] args) throws Exception {
sHttpClient.start();
sHttpClient.POST(FCM_URL)
.header(HttpHeader.AUTHORIZATION, FCM_KEY)
.header(HttpHeader.CONTENT_TYPE, "application/json")
.content(new StringContentProvider(JSON.toString(REQUEST)))
.onResponseContent(sFcmListener)
.send();
}
but unfortunately the execution fails immediately with NPE:
2017-06-30 10:46:41.312:INFO::main: Logging initialized #168ms to org.eclipse.jetty.util.log.StdErrLog
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NullPointerException
at org.eclipse.jetty.client.util.FutureResponseListener.getResult(FutureResponseListener.java:118)
at org.eclipse.jetty.client.util.FutureResponseListener.get(FutureResponseListener.java:101)
at org.eclipse.jetty.client.HttpRequest.send(HttpRequest.java:682)
at de.afarber.fcmnotregistered.Main.main(Main.java:68)
Caused by: java.lang.NullPointerException
at org.eclipse.jetty.io.ssl.SslClientConnectionFactory.newConnection(SslClientConnectionFactory.java:59)
at org.eclipse.jetty.client.AbstractHttpClientTransport$ClientSelectorManager.newConnection(AbstractHttpClientTransport.java:191)
at org.eclipse.jetty.io.ManagedSelector.createEndPoint(ManagedSelector.java:420)
at org.eclipse.jetty.io.ManagedSelector.access$1600(ManagedSelector.java:61)
at org.eclipse.jetty.io.ManagedSelector$CreateEndPoint.run(ManagedSelector.java:599)
at org.eclipse.jetty.util.thread.Invocable.invokePreferred(Invocable.java:128)
at org.eclipse.jetty.util.thread.Invocable$InvocableExecutor.invoke(Invocable.java:222)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:294)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:199)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:672)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:590)
at java.lang.Thread.run(Thread.java:745)
Why does it happen please?
UPDATE:
I have switched to using BufferingResponseListener and the NPE is gone, but now the program prints java.net.NoRouteToHostException: No route to host even though the Google FCM endpoint is a well-known host:
private static final HttpClient sHttpClient = new HttpClient();
private static final BufferingResponseListener sFcmListener = new BufferingResponseListener() {
#Override
public void onComplete(Result result) {
if (!result.isSucceeded()) {
System.err.println(result.getFailure()); // No route to host
return;
}
String body = getContentAsString(StandardCharsets.UTF_8);
System.out.printf("onContent: %s\n", body);
Map<String, Object> resp = (Map<String, Object>) JSON.parse(body);
try {
Object[] results = (Object[]) resp.get(FCM_RESULTS);
Map map = (Map) results[0];
String error = (String) map.get(FCM_ERROR);
if (FCM_NOT_REGISTERED.equals(error)) {
// TODO delete invalid FCM token from the database
}
} catch (Exception ex) {
System.err.println(ex);
}
}
};
public static void main(String[] args) throws Exception {
sHttpClient.start();
sHttpClient.POST(FCM_URL)
.header(HttpHeader.AUTHORIZATION, FCM_KEY)
.header(HttpHeader.CONTENT_TYPE, "application/json")
.content(new StringContentProvider(JSON.toString(REQUEST)))
.send(sFcmListener);
}
I get the No route to host for any FCM_URL value I try, why?
Adding SslContextFactory has helped me:
private static final SslContextFactory sFactory = new SslContextFactory();
private static final HttpClient sHttpClient = new HttpClient(sFactory);
private static final BufferingResponseListener sFcmListener = new BufferingResponseListener() {
#Override
public void onComplete(Result result) {
if (!result.isSucceeded()) {
System.err.println(result.getFailure());
return;
}
String body = getContentAsString(StandardCharsets.UTF_8);
System.out.printf("onComplete: %s\n", body);
try {
Map<String, Object> resp = (Map<String, Object>) JSON.parse(body);
Object[] results = (Object[]) resp.get(FCM_RESULTS);
Map map = (Map) results[0];
String error = (String) map.get(FCM_ERROR);
System.out.printf("error: %s\n", error);
if (FCM_NOT_REGISTERED.equals(error) ||
FCM_MISSING_REGISTRATION.equals(error) ||
FCM_INVALID_REGISTRATION.equals(error)) {
// TODO delete invalid FCM token from the database
}
} catch (Exception ex) {
System.err.println(ex);
}
}
};
public static void main(String[] args) throws Exception {
sHttpClient.start();
sHttpClient.POST(FCM_URL)
.header(HttpHeader.AUTHORIZATION, FCM_KEY)
.header(HttpHeader.CONTENT_TYPE, "application/json")
.content(new StringContentProvider(JSON.toString(REQUEST)))
.send(sFcmListener);
}
The still open question I have is how to retrieve the invalid FCM token that I have used in the Jetty HTTP client request, so that I can delete it from my database on the response...

Unity app not responding and get "request time out" when call to WebAPI

I'm having a Unity app call to a Like() method in DLL, which connect to a WebAPI to do the job. However, when I debug the application and code run to
string liked = SocialConnector.LikePost(token, postID);
It got stuck there, unity became not responding and after work normal again, the debug show Request time out.
Below are my detail code in DLL
public static String LikePost(String token, String postID)
{
HttpCommon common = new HttpCommon();
string url = Constant.ApiURL + Constant.API_LINK_POST_LIKE_UNLIKE + "?postID=" + postID;
String result = common.HttpPost<String>(url, token);
return result;
}
Code in HTTPCommon
public T HttpPost<T>(String url, String token)
{
var request = (HttpWebRequest)WebRequest.Create(url);
//var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
//request.ContentLength = data.Length;
request.Headers["Authorization"] = "Bearer " + token;
var stream = request.GetRequestStream();
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
try
{
var responseData = JsonConvert.DeserializeObject<T>(responseString);
return responseData;
}
catch (Exception e)
{
throw new Exception(responseString);
}
}
Error log:
WebException: The request timed out
System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult)
System.Net.HttpWebRequest.GetResponse ()
GSEP_DLL.Connectors.HttpCommon.HttpPost[String] (System.String url, System.String token)
GSEP_DLL.Connectors.SocialConnector.LikePost (System.String token, System.String postID)
Like.onClick () (at Assets/Scripts/Like.cs:39)
UnityEngine.Events.InvokableCall.Invoke (System.Object[] args) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:110)
UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:574)
UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:716)
UnityEngine.Events.UnityEvent.Invoke () (at C:/buildslave/unity/build/Runtime/Export/UnityEvent_0.cs:53)
UnityEngine.UI.Button.Press () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:35)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Button.cs:44)
UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:52)
UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction`1 functor) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:269)
UnityEngine.EventSystems.EventSystem:Update()
Update: Problem solved. The WebAPI return type of bool but my DLL forced to return String.
Problem solved. The WebAPI return type of bool but my DLL forced to return String.

ArgumentException While connecting win phone 8.1 to wcf

While building win phone 8.1 Silverlight,
Added service reference to WCF, some method for reference:
[OperationContract]
Task<GetPlayListResponse> GetPlayList(GetPlayListRequest request);
And using it like this:
private void Button_Click(object sender, RoutedEventArgs e)
{
var service = new MediaServiceClient();
service.GetPlayListCompleted += service_GetPlayListCompleted;
GetPlayListRequest request = new GetPlayListRequest { BusinessId = 41 };
service.GetPlayListAsync(request);
}
void service_GetPlayListCompleted(object sender, MediaService.GetPlayListCompletedEventArgs e)
{
var response = e.Result;
if (response.Result.ResultCode == eRequestResultCode.Success)
{
lb_RequestList.ItemsSource = response.Songs;
}
}
Getting the following error message:
[System.ArgumentException] {System.ArgumentException: Value does not fall within the expected range. at System.Net.Browser.ClientHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult) at System.Net.Browser.ClientHttpWebRequest.<>c__DisplayClasse.<EndGetResponse>b__d(Object sendState) at System.Net.Browser.AsyncHelper.<>c__DisplayClass1.<BeginOnUI>b__0(Object sendState)} System.ArgumentException
The exception is accruing here :
public WinPhone.Silverlight_Client.MediaService.GetPlayListResponse EndGetPlayList(System.IAsyncResult result) {
object[] _args = new object[0];
WinPhone.Silverlight_Client.MediaService.GetPlayListResponse _result = ((WinPhone.Silverlight_Client.MediaService.GetPlayListResponse)(base.EndInvoke("GetPlayList", _args, result)));
return _result;
}

.NET CF WebService ObjectDisposedException

I am trying to solve an issue with one of my Smart Device projects (.NET CF 3.5 on Windows Mobile 6.5 Device).
The code tries to make webservice calls continuously to get some data and use it in the form. During the usage, for a particular case is an ObjectDisposedException thrown and the application crashes. The stacktrace is
System.ObjectDisposedException was unhandled
Message="ObjectDisposedException"
ObjectName=""
StackTrace:
at System.Threading.Timer.throwIfDisposed()
at System.Threading.Timer.Change(UInt32 dueTime, UInt32 period)
at System.Threading.Timer.Change(Int32 dueTime, Int32 period)
at System.Net.HttpWebRequest.startReadWriteTimer()
at System.Net.HttpWebRequest.ConnectionClient.Read(Byte[] data, Int32 offset, Int32 length)
at System.Net.HttpReadStream.NetworkRead(Byte[] data, Int32 offset, Int32 length)
at System.Net.ChunkedReadStream.fillBuffer()
at System.Net.ChunkedReadStream.getLine()
at System.Net.ChunkedReadStream.doRead(Byte[] data, Int32 offset, Int32 length)
at System.Net.HttpReadStream.ReadToDrain(Byte[] buffer, Int32 offset, Int32 length)
at System.Net.HttpReadStream.doClose()
at System.Net.HttpReadStream.Finalize()
I have read many blogs and forums, including this, and the solution suggested seems to be to close the request stream and the request, before getting the response.
requestStream = webRequest.GetRequestStream();
requestStream.Close(); // WE NEED THIS LINE in order to avoid the ObjectDisposedException.
But this does not help my situation. If the requestStream is closed before writing to the data to the stream then it does not do anything. If I close after getting the response, then it throws InvalidOperationException.
Following is my code:
Reference.cs
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="ProductResolveServiceSOAP11Binding", Namespace="urn:ProductResolveService")]
[System.Xml.Serialization.XmlIncludeAttribute(typeof(Exception))]
public partial class ProductResolveService : System.Web.Services.Protocols.SoapHttpClientProtocol {
/// <remarks/>
public ProductResolveService() {
this.Url = "http://172.26.37.115:8080/axis/services/ProductResolveService";
}
/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("urn:getResolvedEpcs", RequestNamespace="http://services.axis.oatsystems.com", ResponseNamespace="http://services.axis.oatsystems.com", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[return: System.Xml.Serialization.XmlElementAttribute("return", IsNullable=true)]
public ResolvedProductList getResolvedEpcs([System.Xml.Serialization.XmlElementAttribute(IsNullable=true)] EpcToResolve message) {
object[] results = this.Invoke("getResolvedEpcs", new object[] {
message});
return ((ResolvedProductList)(results[0]));
}
/// <remarks/>
public System.IAsyncResult BegingetResolvedEpcs(EpcToResolve message, System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("getResolvedEpcs", new object[] {
message}, callback, asyncState);
}
/// <remarks/>
public ResolvedProductList EndgetResolvedEpcs(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((ResolvedProductList)(results[0]));
}
}
Form1.cs
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading;
using System.Web.Services.Protocols;
using System.Windows.Forms;
using NFEHandlingProject.StatusService;
using System.IO;
using MVProductResolveService;
namespace NFEHandlingProject
{
public partial class Form1 : Form
{
private Thread resolveThread;
int counter = 0;
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
if (resolveThread == null)
{
this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("Resolve Product: Creating Thread"); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; });
resolveThread = new Thread(new ThreadStart(GetEpcProductMapping));
resolveThread.IsBackground = true;
resolveThread.Priority = ThreadPriority.BelowNormal;
resolveThread.Start();
}
}
object syncRoot2 = new object();
bool resolving = false;
private void GetEpcProductMapping()
{
lock (syncRoot2)
{
if (resolving)
{
return;
}
resolving = true;
}
while (resolving)
{
using (ProductResolveService2 productResolveService = new ProductResolveService2())
{
EpcToResolve epcToResolve = null;
try
{
this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("Resolve Product: Resolving..."); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; });
productResolveService.Url = "http://172.26.37.115:8080/axis/services/ProductResolveService?wsdl";
productResolveService.Timeout = 60000;
// The input object that is sent to xpress
epcToResolve = new EpcToResolve();
string epcBase = "3410402AEA0000000000";
int baseDec = Convert.ToInt32("1000", 16);
// Creating the input of epc's baed on the ResolveBatchSize and number epcs's that needs to be resolved at xpress
string[] epcs = new string[1];
for (int i = 0; i < 1; i++)
{
int epcDec = baseDec + i;
epcs[i] = epcBase + epcDec.ToString("X");
}
// setting the epc list which is the input that is sent to xpress
epcToResolve.epcList = epcs;
//pass the flag to check if say whether the productInformation or just the product_id is resolved
epcToResolve.returnOnlyProductId = false;
//return productResolveService.getResolvedEpcs(epcToResolve);
productResolveService.getResolvedEpcs(epcToResolve);
this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("Resolved"); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; });
}
catch (SoapHeaderException)
{
// do nothing
}
catch (SoapException se)
{
this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("Problem resolving products at xpress"); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; });
}
catch (WebException we)
{
// get the reason for the exception
WebExceptionStatus status = we.Status;
String description = we.Message;
WebResponse response = we.Response;
if (response != null)
{
Stream respStream = response.GetResponseStream();
if (respStream != null)
{
respStream.Close();
respStream.Dispose();
respStream = null;
}
// close the response
response.Close();
response = null;
}
// Case when there is no connectivity. Just display an error message to the user to indicate that there is no connectivity.
this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("Resolve Product: There is no connectivity to xpress"); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; });
}
catch (ThreadAbortException)
{
// Do nothing. Do not log
}
catch (System.Exception e)
{
this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("An exception occured when fetching data from xpress"); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; });
}
try
{
Thread.Sleep(200);
}
catch
{
}
}
}
resolving = false;
}
private void btnStop_Click(object sender, EventArgs e)
{
if (resolveThread != null && resolving)
{
resolveThread.Abort();
resolveThread.Join();
resolveThread = null;
resolving = false;
this.BeginInvoke((Action)delegate { lstbxStatusMsgs.Items.Add("Resolve Product: Stopped Thread"); lstbxStatusMsgs.SelectedIndex = lstbxStatusMsgs.Items.Count - 1; });
}
}
}
}
On clicking on the Start Button in the form, the thread is created and keeping calling the webservice, when the stop is called, the thread is stopped. Repeated start and stop causes the ObjectDisposedException (that is how I reproduced this exception).
Any help on this regard will be highly appreciated, as I have been trying to solve this issue for a few days now.
Thanks
Senthil
This is a pretty old post. However, I wanted to record my answer here for any body who is still looking for an answer.
Two options:
Move to WCF Clients which is much easier and cleaner.
Use the below solution.
public class ExtendedDataImport : DataImport.DataImport
{
private WebRequest webRequest;
private WebResponse webResponse;
/// <summary>
/// This method overrides the generated method and sets parameters so that HTTP 1.0
/// is used (without chunking). If left with default parameters it
/// sometimes fails.
/// </summary>
protected override WebRequest GetWebRequest(Uri uri)
{
webRequest = base.GetWebRequest(uri);
((HttpWebRequest)webRequest).KeepAlive = false;
((HttpWebRequest)webRequest).ProtocolVersion = HttpVersion.Version10;
return webRequest;
}
protected override WebResponse GetWebResponse(WebRequest request)
{
webResponse = base.GetWebResponse(request);
return webResponse;
}
public void Close()
{
if (webResponse != null)
{
Stream responseStream = webResponse.GetResponseStream();
responseStream.Close();
responseStream.Dispose();
responseStream = null;
webResponse.Close();
webResponse = null;
}
if (webRequest != null)
{
// Aborting the WebRequest, cleans up the webrequest and
// stops the timer which causes the ObjectDisposedException
try
{
webRequest.Abort();
webRequest = null;
}
catch (ObjectDisposedException ex)
{
// Ignoring the object disposed exception as mentioned in the follwoing link
//http://social.msdn.microsoft.com/Forums/en/netfxcompact/thread/8f21514c-9b7c-40d3-96c9-794c0dc167fe
}
}
}
protected override void Dispose(bool disposing)
{
Close();
base.Dispose(disposing);
}
}