Asynchronous call C#.Net beginners question - silverlight

So here I am,got some help from some web tutorials and performing following Asynchronous call. I want to return an object of type UserInfo from following async call. But I'm not sure how the program flows after request.BeginResponse(). Is it something like an additional ref parameter of type UserInfo can be passed to callback method?
UserInfo GetUserInfoAsync()
{
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Credentials = new NetworkCredential("myID", "myPWD");
request.Method = "GET";
request.Accept = "application/json";
object data = new object();
RequestState state = new RequestState(request, data, url);
IAsyncResult asr = request.BeginGetResponse(new AsyncCallback(myCallback), state);
return null; //Need guidence here;
}
private static void myCallback(IAsyncResult result)
{
RequestState state = (RequestState)result.AsyncState;
WebRequest request = (WebRequest)state.Request;
HttpWebResponse response =(HttpWebResponse)request.EndGetResponse(result);
Stream s = response.GetResponseStream();
StreamReader readStream = new StreamReader(s);
string dataString = readStream.ReadToEnd();
response.Close();
s.Close();
readStream.Close();
UserInfo ui = ParseJSON(dataString );
}

Your GetUserInfoAsync method will return before the request has completed. That's the meaning of it being asynchronous. You need to make your callback take appropriate action with the UserInfo it's just received - e.g. calling back into the UI thread (using Dispatcher) to update the UI.
You could make your GetUserInfo call wait until it's got a result - but you basically shouldn't. The whole point of asynchronous calls is to avoid blocking.

You need to handle the data in your callback. If you need to return the user info from your initial method call, you need a synchronous operation. There's no way to have that information available until the operation completes.

return null; //Need guidence here;
You cannot return anything meaningful at that point. Use event from callback to notify that result is ready.

Related

Hystrix run() method executing even after timeout

I created a class by extending HystrixCommand and configured timeout for the request using below code
HystrixCommandProperties.Setter().withExecutionIsolationThreadTimeoutInMilliseconds(int milliSec);
Also overriden fallBack method when request not returns response within timeout specified
#Override
protected JSONObject run() throws Exception
{
// performed some http call
final HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders);
ResponseEntity<String> response = restTemplate.exchange(requestUrl, HttpMethod.GET, httpEntity, JSONObject.class)
.getBody();
System.out.println(response);
return response;
}
#Override
protected JSONObject getFallback()
{
final JSONObject json = new JSONObject();
json.put("status", "900");
json.put("message", "Request Failed");
return json;
}
Am getting fallBack method response whenever request takes more time than timeout specified which is expected.
But, what I observed is, when timeout occurs fallBack response is getting returned, and the response of the request which is executed in run method is coming later and am not able to hold or return as we returned the fallback response as soon as timeout.
Is there any way I can return that response ?
Thanks in advance.

WCF Async operations not really async

wonder if anyone can tell me where i'm going wrong.
i've added a service reference in my wpf application VS2012
however my wait on the Async call is blocking, i'm not doing anything with it at the moment.
The Async call I got for free when I added the Service reference...
Yet when I await ma.searchModelsAsync I'm blocked...
can anyone shed some light on this??
first I call the function like this:
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
button1.IsEnabled = false;
var cnt = await GetDataFromWcf();
button1.IsEnabled = true;
}
here is the actual function I call
public async Task<List<ViewModels.ModelInfo>> GetDataFromWcf()
{
using (var ma = new DataGenic.ModelActionsServiceTypeClient())
{
var modelInfos = await ma.searchModelsAsync(new ModelSearchCriteria { Category = "ECB" }, 1, 50);
return modelInfos.Select(mi => new ViewModels.ModelInfo { Id = mi.Id, Name = mi.Name, Uri = mi.Uri }).ToList();
}
}
btw: if I put the function in a Task.Run(() => ... then it behaves as I expcect...
Not sure if WCF is really giving me what I want.. ideas anyone?
Based on the comment thread thus far, it sounds like there's enough work happening before the WCF task starts up such that you'd like to have GetDataFromWcf return to the caller sooner than that. That's a somewhat common issue with async methods (IMHO) - the 'gotcha' that they run synchronously up until that first 'await' call, so they can still cause noticeable UI delays if too much is happening before the first 'await' :)
Because of that, a simple change would be to use Task.Yield (by adding await Task.Yield(); as the first line in GetDataFromWcf) which changes the behavior to have the async method return back to the caller immediately. As the MSDN doc mentions, you can use await Task.Yield(); in an asynchronous method to force the method to complete asynchronously. That sentence alone (and how silly it sounds on the surface) helps show the 'gotcha' IMHO :)

WP7 HttpWebRequest check if file exists (synchronously)

I need to check if a file exists and I need to do it from several places in code.
Some of the places I can handle it with a callback (kinda ugly but it will work). But the one I don't know how to handle seems to require that it be Synchronous.
I need to call the method to check if it exist from a RelayCommand as the "canExecute" method.
Any ideas on how to handle this?
This is what I currently have but calling the .WaitOne on the UI thread is blocking the background worker so it completely locks the app.
private bool FileExists(Uri file)
{
var exists = false;
ManualResetEvent resetEvent = new ManualResetEvent(false);
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, e) =>{
WebRequest request = HttpWebRequest.Create(file);
request.Method = "HEAD"; //only request the head so its quick
request.BeginGetResponse(result =>
{
try
{
//var response = request.EndGetResponse(result);
var req = (HttpWebRequest)result.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
exists = (response.StatusCode.ToString() == "OK");
}
catch
{
exists = false;
}
resetEvent.Set();
}
, request);
};
worker.RunWorkerAsync();
resetEvent.WaitOne();
return exists;
}
You should never make HTTPWebRequest's synchronous on the UI thread - this could block the UI for seconds or minutes...
If you really want to make an HTTPWebRequest appear to be synchronous on a background thread then simply use a ManualResetEvent inside a callback - e.g. something like:
var resetEvent = new ManualResetEvent();
theHttpWebRequest.BeginGetResponse((result) => {
var response = theHttpWebRequest.EndGetResponse(result);
// use response.StatusCode to check for 404?
resetEvent.Set();
});
resetEvent.WaitOne();
Also, please note that checking if a file exists over HTTP might be better done by calling a small webservice which does the check - it depends on the size of the file you are checking.
AFAIK this is not possible. You can never make synchronous calls to web services in Silverlight.
You have to leave canExecute method empty (to always execute the command), and make async call to check if file exists in handler for the command. The real code for the command has to execute in handler for that async call.
I think it is only way you can manage it.
btw-you can use lambda expressions to make it look more like synchronous code. Or maybe Reactive Extensions may help with better looking code (jesse's tutorial).
The way I would approach this problem is to create some kind of flag ( i.e IsFileExists) and return that flag from CanExecute method. Flag shold be set to false initially and your button disabled under assumption that untill we know that file does exits we consider it doesn't. Next I would fire HTTPWebRequest or wcf call or any other async method to check if file exists. Once callback confirms that file exists set flag to true and fire CanExecuteChanged event. If you want to be fancy you can add some visual feedback while waiting for responce. In general user experienc would be much better than locking up screen for duration of the web request.

Mocking Asynchronous Calls in Silverlight WCF Proxy using Moq

I have a typical Silverlight application with a WCF service and I am using slsvcutil.exe to generate the standard client proxy to communicate with the web service. I am trying to write unit tests and I'm attempting to use the Silverlight Unit Testing framework and Moq to mock the proxy and remove the service dependency for testing.
I am very new to Moq and having a lot of trouble automatically raising the various Completed events on the mocked proxy automatically when service calls are made to simulate the async calls.
In order to make the proxy "mockable" I've created my own simple interface for the generated proxy calls and their completed events:
public interface IServiceProxy
{
void TestAsync(TestRequest request);
void TestAsync(TestRequest request, object userState);
event EventHandler<TestCompletedEventArgs> TestCompleted;
}
I also subclassed the generated proxy object to implement that interface:
public class MyServiceProxy : GeneratedServiceClient, IServiceProxy, ICommunicationObject
{
// ... overloaded proxy constructors
}
After looking at the Moq documentation, this is how I am attempting to set up the mock to expect the TestAsync() call and immediately raise the TestCompleted event with the result in the EventArgs:
[TestMethod]
public void Test_Returns_Expected()
{
var mockProxy = new Mock<IServiceProxy>();
var result = new TestResponse() { Value = true };
this.mockProxy.Setup(
p => p.TestAsync(It.IsAny<TestRequest>()))
.Raises(p => p.TestCompleted += null, new TestCompletedEventArgs(new object[] { result }, null, false, null));
// rest of the test to actually use the mock and assert things
}
Everything builds fine, but when I attempt to run any kind of test using the mock and set break points the TestCompleted event is never being raised when I call TestAsync().
Is there anything obvious that I am missing or any better ideas about mocking these types of async service proxies in Silverlight?
Thanks!
EDIT:
To be more clear what I am actually trying to test is a helper class I made which takes an instance of IServiceProxy and provides a cleaner service interface for my ViewModel to use by accepting Action<TResponse, Exception> callback parameters rather than dealing with callback events in my ViewModel. I understand how I could mock this as well to directly test my ViewModel but I figured it would be nice to test the helper class by itself first.
Here is an example of what I am talking about:
public class HelperClient : IServiceHelper
{
private IServiceProxy proxy;
public HelperClient(IServiceProxy proxy)
{
this.proxy = proxy;
// register to handle all async callback events
this.proxy.TestCompleted += new EventHandler<TestCompletedEventArgs>(TestCompleted);
}
public void Test(TestRequest request, Action<TestResponse, Exception> response)
{
this.proxy.TestAsync(request, response);
}
private void TestCompleted(object sender, TestCompletedEventArgs e)
{
var response = e.UserState as Action<TestResponse, Exception>;
if (response != null)
{
var ex = GetServiceException(e);
if (ex == null)
{
response(e.Result, null);
}
else
{
response(null, ex);
}
}
}
}
So in my test what I am really doing is mocking ISerivceProxy and passing it in and just attempting to test a service call to make sure the wrapper it invoking the Action correctly:
[TestMethod]
[Asynchronous]
public void Test_Returns_Expected()
{
var mockProxy = new Mock<IServiceProxy>();
var helper = new HelperClient(mockProxy.Object);
bool expectedResult = true;
var result = new TestResponse() { Value = expectedResult };
this.mockProxy.Setup(
p => p.TestAsync(It.IsAny<TestRequest>()))
.Raises(p => p.TestCompleted += null, new TestCompletedEventArgs(new object[] { result }, null, false, null));
helper.Test(new TestRequest(), (response, ex) =>
{
Assert.AreEqual(expectedResult, response.Value);
EnqueueTestComplete();
});
}
The problem is that the mocked proxy object is never raising the TestCompleted event so my response action is never getting invoked to finish the test (even though the test appears to complete successfully the Assert is never actually run). Sorry for such a long post, just trying to show you as much code as possible.
EDIT 2
Added [Asynchronous] and call to EnqueueTestComplete() which I realized I may need to make the test wait for the event to be raised. This did not really help, the event is still never raised so the test just hangs and never completes.
EDIT 3
Aliostad's answer was correct that my setup expectation's signature did not match the actual Test() signature allowing me to pass in a response Action as the second param. Stupid mistake, but that is what was preventing Moq from raising the Completed event. I was also forgetting to pass the Action in as the userState object in the TestCompletedEventArgs so that it would actually be invoked when the Completed event was raised. Also, the [Asynchronous] and EnqueueTestCompleted did not seem to be necessary in this case.
Here is updated test code for anyone interested:
[TestMethod]
public void Test_Returns_Expected()
{
var mockProxy = new Mock<IServiceProxy>();
var helper = new HelperClient(mockProxy.Object);
bool expectedResult = true;
var result = new TestResponse() { Value = expectedResult };
Action<TestResponse, Exception> responseAction = (response, ex) =>
{
Assert.AreEqual(expectedResult, response.Value);
};
this.mockProxy.Setup(
p => p.TestAsync(It.IsAny<TestRequest>(), It.IsAny<Action<TestResponse, Exception>>()))
.Raises(p => p.TestCompleted += null, new TestCompletedEventArgs(new object[] { result }, null, false, responseAction));
helper.Test(new TestRequest(), responseAction);
}
Mocking events is quite a pain and unit tests become brittle. But as you said there is no way around it. But normally you would make the call you are trying to test and block the current thread (using Sleep or other methods) until event is raised (or a time-out).
It is actually not clear what you are testing. I can see a mock and a response, where is the actual real object?
I will update my answer accordingly.
UPDATE
I can see a problem here:
helper.Test(new TestRequest(), (response, ex) =>
{
Assert.AreEqual(expectedResult, response.Value);
EnqueueTestComplete();
});
in the last statement, you are putting EnqueueTestComplete(); and you assert but this action will never be used because it is passed to the moq object.
Also you are setting the expectation for TestAsync(It.IsAny<TestRequest>())) (one argument) while you are calling it with two arguments in the HelperClient (this.proxy.TestAsync(request, response);) and that is why it never gets fired since expectation is not met.
just searched for mock asynchronous WCF client and found this question.
to prevent this situation Moq can .Verify() that p.TestAsync() has been invoked.
//will throw MockException if p.TestAsync() has never been called.
this.mockProxy.Verify(p => p.TestAsync(It.IsAny<TestRequest>()), Times.Once());

Silverlight Async Design Pattern Issue

I'm in the middle of a Silverlight application and I have a function which needs to call a webservice and using the result complete the rest of the function.
My issue is that I would have normally done a synchronous web service call got the result and using that carried on with the function. As Silverlight doesn't support synchronous web service calls without additional custom classes to mimic it, I figure it would be best to go with the flow of async rather than fight it. So my question relates around whats the best design pattern for working with async calls in program flow.
In the following example I want to use the myFunction TypeId parameter depending on the return value of the web service call. But I don't want to call the web service until this function is called. How can I alter my code design to allow for the async call?
string _myPath;
bool myFunction(Guid TypeId)
{
WS_WebService1.WS_WebService1SoapClient proxy = new WS_WebService1.WS_WebService1SoapClient();
proxy.GetPathByTypeIdCompleted += new System.EventHandler<WS_WebService1.GetPathByTypeIdCompleted>(proxy_GetPathByTypeIdCompleted);
proxy.GetPathByTypeIdAsync(TypeId);
// Get return value
if (myPath == "\\Server1")
{
//Use the TypeId parameter in here
}
}
void proxy_GetPathByTypeIdCompleted(object sender, WS_WebService1.GetPathByTypeIdCompletedEventArgs e)
{
string server = e.Result.Server;
myPath = '\\' + server;
}
Thanks in advance,
Mike
The best would be to use Reactive Extensions. Then (assuming you'd create an extension method IObservable<string> GetPathByTypeId(string typeId) on WS_WebService1SoapClient you can do this:
proxy
.GetPathByTypeId(TypeId)
.Subscribe(server =>
{
//Here you can do stuff with the returned value
});
As close to having synchronous call as it gets :)
Given the asynch nature of Silverlight you cannot return values from myFunction. Instead you can pass an Action which is executed once the service call is complete. See the example code below. I am not sure if it is considered best practice, but I use this "pattern" a lot and it has always worked fine for me.
EDIT
Updated the code below to include multiple arguments in the callback action.
void DoSomething(Guid TypeId, Action<int, bool> Callback)
{
WS_WebService1.WS_WebService1SoapClient proxy = new WS_WebService1.WS_WebService1SoapClient();
proxy.GetPathByTypeIdCompleted += (s, e) =>
{
string server = e.Result.Server;
myPath = '\\' + server;
//
if (myPath == "\\Server1")
{
Callback(888, true);
}
else
{
Callback(999, false);
}
};
proxy.GetPathByTypeIdAsync(TypeId);
}
void CallDoSomething()
{
DoSomething(Guid.NewGuid(), (returnValue1, returnValue2) =>
{
//Here you can do stuff with the returned value(s)
});
}
Put the processing of the GetPathByTypeId result into the GetPathByTypeIdCompleted callback. Assign mypath there. Make mypath a property and implement the INotifyPropertyChanged interface to notify dependents of Mypath that Mypath has changed.
Observer depends on mypath
Observer sets a notification event for mypath
Get Mypath by asynchronous invocation of GetPathByTypeId
Mypath is set, invokes notifiaction of Observer
Observer works with Mypath

Resources