I'm new to MvvmCross and Android development. I have a need to call to POST data to a JSON web service in my view model. I then need to display the result of the web service back in my UI. The gist of my view model looks like the following:
public class MyViewModel : MvxViewModel
{
public override void Start()
{
base.Start();
}
public event EventHandler<EventArgs> Service_Finished;
public void CallService()
{
string url = GetServiceUrl();
WebRequest serviceRequest = HttpWebRequest.Create(url);
serviceRequest.Method = "POST";
serviceRequest.ContentType = "application/json";
serviceRequest.BeginGetRequestStream(new AsyncCallback(ServiceBeginGetRequestStreamCallback), serviceRequest);
}
private void ServiceBeginGetRequestStreamCallback(IAsyncResult ar)
{
string json = GetJson();
HttpWebRequest myWebRequest = (HttpWebRequest)(ar.AsyncState);
using (Stream postStream = myWebRequest.EndGetRequestStream(ar))
{
byte[] byteArray = Encoding.UTF8.GetBytes(json);
postStream.Write(byteArray, 0, byteArray.Length);
}
myWebRequest.BeginGetResponse(new AsyncCallback(Service_Completed), myWebRequest);
}
private void Service_Completed(IAsyncResult result)
{
if (Service_Finished != null)
Service_Finished(this, new EventArgs());
}
}
In my View (UI) code, I've added an event-handler for the Service_Finished
event. I've noticed that I can successfully throw the event from the "CallService
" method in my view model. However, if I try to fire Service_Finished
from either the ServiceBeginGetRequestStreamCallback
or the Service_Completed
portions, the event is never fired in the UI.
Due to the fact that the view model is in a portable class library, I can't figure out how to debug this. At this point I know that CallService is getting successfully called. However, I can't tell where I'm getting within ServiceBeginGetRequestStreamCallback
and if I'm even getting to Service_Completed
.
I know from my Windows Phone dev experience, I would need to check to see if I'm on the UI thread, if not, I'd have to do some Deployment.stuff. But, with the MvvmCross approach, I'm not sure a) if I have to do that and b) if that is even an option since the view model should work with both Android and iOS. Regardless, there has to be a way to a) call a web service from a view model and b) send a message back to the view so that the UI can be updated. Unfortunately, I can't seem to figure it out. Can someone (slodge :)) tell me what I'm doing wrong?
Thank you
In general, I put this kind of WebService call in the Model rather than in the ViewModel - it makes both the ViewModel and the WebService client code much more reusable.
Some simple examples of this are in:
I know from my Windows Phone dev experience, I would need to check to see if I'm on the UI thread, if not, I'd have to do some Deployment.stuff. But, with the MvvmCross approach, I'm not sure a) if I have to do that and
Yes, all communication from ViewModel->View should be on the UI thread.
b) if that is even an option since the view model should work with both Android and iOS.
MvvmCross provides an interface to allow you to marshal execution onto the UI thread. In a ViewModel, this is easily done by calling InvokeOnMainThread(() => { /* your code */ })
Behind the scenes, MvvmCross will also marshall all RaisePropertyChanged
executions to the UI thread too. Note - that ObservableCollection
updates are not automatically marshalled though - this is because ObservableCollection
is a class that exists outside of MvvmCross.
Regardless, there has to be a way to a) call a web service from a view model and
See the samples (above)
b) send a message back to the view so that the UI can be updated.
In general you should not send these type of messages via events.
Instead, you should:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With