I have a Windows Phone 7 application built with silverlight. This application has been deployed. I've noticed in the log files that occasionally, my user's actions throw a "NotSupportedException". I have not been able to produce this. However, because of my logs, I know that it is happening in the Execute method shown here:
public void Execute()
{
try
{
// 1. Build the query
string serviceUrl = GetServiceUrl;
// 2. Asynchronously execute the query using HttpWebRequest
WebRequest request = HttpWebRequest.Create(serviceUrl);
request.BeginGetResponse(new AsyncCallback(ServiceRequest_Completed), request);
} catch (Exception ex)
{
LogException(ex, "1");
}
}
private void ServiceRequest_Completed(IAsyncResult result)
{
try
{
// 1. Get the response from the service call
WebRequest request = (WebRequest)(result.AsyncState);
WebResponse response = request.EndGetResponse(result);
// 2. Do stuff with response
}
catch (Exception ex)
{
LogException(ex, "2");
}
}
I know it is happening in the Execute method because the "1" is written in the log file instead of the "2" My question is, what would cause this? I looked at the MSDN documentation and it looks like I'm doing what I should be doing. Like I said, I can't reproduce it locally. But I do know that it is happening regularly by different users because of the log files.
There is a previous question with a very similar title - https://stackoverflow.com/questions/4053197/httpwebrequest-leads-me-to-system-notsupportedexception
The answer to that problem seems to have been using ServiceRequest_Completed instead of new AsyncCallback(ServiceRequest_Completed)
Related
I am using the following code in my controller when I submit a new entry:
// POST /api/Content/
public HttpResponseMessage PostContent(Content content)
{
try
{
content.ModifiedDate = DateTime.Now;
_uow.Contents.Add(content);
_uow.Commit();
var response = Request.CreateResponse<Content>(HttpStatusCode.Created, content);
return response;
}
catch (DbUpdateException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
}
}
This only picks up DbUpdateExceptions so if there is another kind of exception then I think I need to handle it differently.
Can anyone suggest how I should handle other exceptions?
You can add several catch in a row going from the most particular to most general
try
{
content.ModifiedDate = DateTime.Now;
_uow.Contents.Add(content);
_uow.Commit();
var response = Request.CreateResponse<Content>(HttpStatusCode.Created, content);
return response;
}
catch (DbUpdateException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.Conflict, ex);
}
catch (Exception ex)
{
// do what you want
}
If we want to move from quick-and-dirty method to longer-but-safer, we may pass following steps:
Excapsulate data access in separate object and handle it's exceptions in it, passing to the outside world custom exceptions. You may decide to hide all data access exceptions under single custom exception.
(as #Massanu pointed) Concatenate handlers starting with most particular to most general. To react approprietely on different exceptions, do not use single catch (Exception ex) handler.
If something, actually, let unhandled, you may catch it in Application_Error method of global.asax: http://msdn.microsoft.com/ru-ru/library/24395wz3(v=vs.100).aspx
There is a good chapter about error handling in Code Complete book written by Steve Macconell: http://cc2e.com/
Hi Im new at Silverlight/async programming
Situation: Silverlight app as a webresource that make CRUD operations
Problem: The entity have a plugin step registered to it as Synchronous. Then in silverlight when the code execute the EndSaveChages(results) method I get a SystemException.
The message received is:
The current object did not originate the async result.Parameter name:
asyncResult
I tried using a lock, Thread.Sleep, While and the Dispatcher but nothing help. There is a way to hold the process until I receive the asycResult?
Code:
private void OnUpdateRecordComplete (IAsyncResult result)
{
try
{
while (!result.IsCompleted)
{
}
Thread.Sleep(1000);
xrmsm_scores updatedRecord = result.AsyncState as xrmsm_scores;
context.EndSaveChanges(result);
// MessageBox.Show("Save Completed!");
MessageBox.Show(updatedRecord.xrmsm_studentsName.Trim() + "'s Grade has been updated!");
//MessageBox.Show("HUGE SUCCESS!");
}
catch (DataServiceRequestException se)
{
MessageBox.Show("The score information could not be saved.\nReason: " + getXMLError(se), "Error!", MessageBoxButton.OK);
studentName = string.Empty;
}
catch (SystemException se)
{
isSaved = true;
//string error = se.Message.Replace('"', '\'').Replace("\r\n", #"\n");
//MessageBox.Show("OnUpdateRecordComplete SystemExeption Catch: " + error);
//It always goes on catch because we are not using MVC System
//It saves it anyways :P
//MessageBox.Show("OnCreateRecordComplete");
//syncContext.Send(new SendOrPostCallback(showErrorDetails), se);
}
}
You shouldn't have to do sleeping or waiting. My understanding is that the complete event handler is only called once async call returns.
Have you seen this sample? It should help to guide you in the right direction.
Sample: Create, Retrieve, Update and Delete Using the REST Endpoint with Silverlight
I have a problem which seems really strange to me! I am working with java mail api in some POJOs and servlets/jsps running on an embedded Jetty server. The problem is that after I retrieve all the folders, but when trying to cast an individual folder from Folder type to IMAPFolder type, this fails.
The strangest thing is that my JUnit tests work just fine the folder is casted and all the messages are retrieved. However, when running the application, it failed.
I just have the error message
500 ([Lcom.sun.mail.imap.IMAPMessage; cannot be cast to [Lcom.sun.mail.imap.IMAPMessage;)
The code is simple:
//...
for(Folder fl:mailFolders){
try {
if((fl.getType() & Folder.HOLDS_MESSAGES) != 0){
Folder f = fetch.connectToInbox(st, fl.getFullName());
fetch.processAllMessages(f);
}
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//.. }
public synchronized void processAllMessages(Folder fldr){
IMAPFolder fl = (IMAPFolder) fldr ;
}
Can anyone please help me?
You've got two copies of the JavaMail classes available to your application and they're being loaded by different class loaders, which is why you're getting the strange exception.
I've got a Silverlight enabled WCF web service set up and I'm connecting to it from my Silverlight application.
The Service is not written using the ASync pattern but Silverlight generates the async methods automatically.
I have a method that within my service that has a chance of throwing an exception I can catch this exception but I'm not sure of the best way of handling this exception, I've noticed that the event args of the completed method contain an error property.
Is is possible to set the value of this error property?
Example Method
public class service
{
[OperationContract]
public Stream getData(string filename)
{
string filepath = HostingEnvironment.MapPath(filename);
FileInfo fi = new FileInfo(filenpath);
try
{
Stream s = fi.Open(FileMode.Open);
return s;
}
catch (IOException e)
{
return null;
}
}
}
Silverlight Code
btnFoo_Click(object sender, RoutedEventArgs e)
{
ServiceClient svc = new ServiceClient();
svc.getDataCompleted += new EventHandler<getDataCompletedEventArgs>(getData_Completed);
svc.getDataAsync("text.txt");
}
void getData_Completed(object sender, getDataCompletedEventArgs e)
{
e.Error //how can i set this value on the service?
}
Finally if the service is offline or times out is there anyway to catch this exception before it reaches the UnhandledException method within App.xaml?
Thanks
Since silverlight is using services asyncronously you dont get a synchronous exception throw, but instead it is stored in e.Error property, that you need to check in your ServiceCallCompleted method.
To answer your question
how can i set this value on the service?
Simply throw an exception on server and it can be enough given several other conditions.
You may want to introduce FaultContract on your WCF service method, and throw FaultException<T> which is a common way to deal with errors in WCF.
However fault result in return code 500 and silverlight won't be able to get response with such status code and have access to Fault object, even if you add that attribute to service.
This can be solved using several approaches.
Use the alternative client HTTP stack: You can register an alternative HTTP stack by using the RegisterPrefix method. See below for an outline of how to do this. Silverlight 4 provides the option of using a client HTTP stack which, unlike the default browser HTTP stack, allows you to process SOAP-compliant fault messages. However, a potential problem of switching to the alternative HTTP stack is that information stored by the browser (such as authentication cookies) will no longer be available to Silverlight, and thus certain scenarios involving secure services might stop working, or require additional code to work.
Modify the HTTP status code: You can modify your service to return SOAP faults with an HTTP status code of 200, Silverlight 4 so that faults will be processed successfully. How to do this is outlined below. Note that this will make the service non-compliant with the SOAP protocol, because SOAP requires a response code in the 400 or 500 range for faults. If the service is a WCF service, you can create an endpoint behavior that plugs in a message inspector that changes the status code to 200. Then you can create an endpoint specifically for Silverlight consumption, and apply the behavior there. Your other endpoints will still remain SOAP-compliant.
Faults in silverlight
Creating and Handling Faults in Silverlight
OR
[DataContract]
public class MyError
{
[DataMember]
public string Code { get; set; }
[DataMember]
public string Message { get; set; }
[DataMember]
public DateTime Time { get; set; }
}
public class service
{
[OperationContract]
public Stream getData(string filename, out MyError myError)
{
myError = null;
string filepath = HostingEnvironment.MapPath(filename);
FileInfo fi = new FileInfo(filenpath);
try
{
Stream s = fi.Open(FileMode.Open);
return s;
}
catch (IOException e)
{
myError = new MyError() { Code = "000", Message = ex.Message, Time = DateTime.Now };
return null;
}
}
}
I wish successful projects
Im trying to write to a form from an asynchronous call. The examples I seen on line show that this should work but I keep getting an error.
First the call that is made though the Disbatcher never calls p. Second i get a System.Security.SecurityException on the call req.EndGetResponse(a);
What could be causing the problem?
public partial class Page : UserControl
{
Uri url = new Uri("http://www.google.com", UriKind.Absolute);
HttpWebRequest req;
private delegate void PrintToUIThread(string text);
PrintToUIThread p;
public Page()
{
InitializeComponent();
req = (HttpWebRequest)WebRequest.Create(url);
p = new PrintToUIThread(print);
req.BeginGetResponse(new AsyncCallback(WebComplete), req);
}
void WebComplete(IAsyncResult a)
{
try
{
Dispatcher.BeginInvoke(p);
HttpWebRequest req = (HttpWebRequest)a.AsyncState;
HttpWebResponse res = (HttpWebResponse)req.EndGetResponse(a);
Dispatcher.BeginInvoke(p);
}
catch (Exception ex)
{
print(ex.ToString());
}
}
private void print(string text)
{
PageTextBox.Text = text;
}
private void print()
{
PageTextBox.Text = "Call From Invoke";
}
}
There's nothing inherently wrong with your request/response code from what I can see. You're probably running into the security exception because of the cross-domain restrictions implied by google's crossdomain.xml file.
This is Google's crossdomain.xml:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="by-content-type" />
</cross-domain-policy>
All this is really saying is "Hey, RIA app, use a proxy". Basically, set up a WCF or ASMX web service call with your "friendly" server with a clientaccesspolicy.xml file in place, use your server to make the http request, then deliver the results back. I'm not not sure if google supports JSONP, but you could try that as well.