Detecting when a web service post has occured - windows-phone-8

I just wrote a simple windows 8 form that post to web service api. It works fine. But my challenge is been able to determine when the post operation was a success and a failure. I dont know how to return a value cos aysnc Task is not allowing a return type.
//This class does the post to web service
public class B2cMobileuserService : IB2cMobileuserService
{
private string RegisterUserUrl = RestfulUrl.RegisterMobileUser;
private readonly HttpClient _client = new HttpClient();
public async Task RegisterMobileUser(B2cMobileuserView user)
{
var jsonString = Serialize(user);
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var result = await _client.PostAsync(RegisterUserUrl, content);
}
}
//This class calls the one above
public class WebserviceProcessor
{
//declaring all the service objects that would be used
IB2cMobileuserService mobileuserService = null;
public WebserviceProcessor() {
mobileuserService = new B2cMobileuserService();
}
//This method is going to post values to the web serever
public async void RegisterUser(B2cMobileuserView mobileuser) {
mobileuserService.RegisterMobileUser(mobileuser);
}
}
//Then the code below is from my .xaml user interface that calls the class that sends to webservice
private void Button_Click(object sender, RoutedEventArgs e)
{
B2cMobileuserView user = new B2cMobileuserView();
user.Name = name.Text;
user.Email = email.Text;
user.PhoneType = "Windows Mobile";
user.BrowserType = "None";
user.CountryName = "Nigeria";
user.UserPhoneID = phone.Text;
Serviceprocessor.RegisterUser(user);
progressBar.Visibility = Visibility.Visible;
}
Please I dont know how to return a value cos when I try I get the error that says async method must be void.
I need to set a way to know when the post was a success based on the return value from the web service.

To ensure the POST was successful, call HttpResponseMessage.EnsureSuccessStatusCode:
public async Task RegisterMobileUser(B2cMobileuserView user)
{
var jsonString = Serialize(user);
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var result = await _client.PostAsync(RegisterUserUrl, content);
result.EnsureSuccessStatusCode();
}
If you want to return a value, use a Task<T> return type instead of Task.
On a side note, avoid async void; use async Task instead of async void unless the compiler forces you to write async void:
//This method is going to post values to the web serever
public Task RegisterUser(B2cMobileuserView mobileuser) {
return mobileuserService.RegisterMobileUser(mobileuser);
}
Also, you should name your asynchronous methods ending in *Async:
//This method is going to post values to the web serever
public Task RegisterUserAsync(B2cMobileuserView mobileuser) {
return mobileuserService.RegisterMobileUserAsync(mobileuser);
}
You may find my async intro and MSDN article on async best practices helpful.

Related

get Json Data From URL in C#

I am new to json i want get json data from a link, here from web search i have written code
private void button1_Click(object sender, EventArgs e)
{
string url = #"http://hololens5.northeurope.cloudapp.azure.com/INTERSHOP/web/WFS/inSPIRED-inTRONICS_Business-Site/en_US/-/USD/ViewProduct-Start?SKU=1599925&CategoryName=151&CatalogID=Computers";
using (WebClient wc=new WebClient())
{
json = wc.DownloadString(url);
}
string path = #"ouptputfileJSON.json";
if (!File.Exists(path))
{
using (StreamWriter sw = File.CreateText(path))
{
sw.WriteLine(json);
}
}
}
When i execute this code i'm getting output in html page. how to get in json data of select product in the link provided
Here is the rest endpoint you are looking for:
http://hololens5.northeurope.cloudapp.azure.com/INTERSHOP/rest/WFS/inSPIRED-
inTRONICS_Business-Site/-;loc=en_US;cur=USD/products/1599925
Documentation about other rest endpoints:
https://support.intershop.com/kb/index.php/Display/T27711
Because
http://hololens5.northeurope.cloudapp.azure.com/INTERSHOP/web/WFS/inSPIRED-inTRONICS_Business-Site/en_US/-/USD/ViewProduct-Start?SKU=1599925&CategoryName=151&CatalogID=Computers
Is webpage and not API endpoint so you need to find proper endpoint from where you want to get data
Once you get Proper Endpoint you can use below
Here is an example how you can use httpclient to make a request
static void Main()
{
Task t = new Task(DownloadPageAsync);
t.Start();
Console.WriteLine("Downloading page...");
Console.ReadLine();
}
static async void DownloadPageAsync()
{
// ... Endpoint
string page = "request URL";
// ... Use HttpClient.
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(page))
using (HttpContent content = response.Content)
{
// ... Read the string.
string result = await content.ReadAsStringAsync();
Console.WriteLine(result);
}
}

Error with Null

I am working on a project here and am running into an issue. It was working fine before but what I am doing is sending a request to a url and am expecting a JSON response. However when I check the response it keeps coming back as null. This was not an issue before but randomly started happening. Any help would be greatly appreciate!'
Also I have another class that actually does the url requests.
This first bit is the onclick listener on the login page. It takes the text fields and converts them to strings. The way the login works is it has to push all the information into the URL which is why it is set up this way.
bt.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
String account = acct.getText().toString();
String uname = user.getText().toString();
String passWord = pass.getText().toString();
url = ap+"&t2mdeveloperid="+id+account+"&t2musername="+uname+"&t2mpassword="+passWord;
new Login().execute();
}
}
);
}
Alright here is the Async task that the request runs in.
private class Login extends AsyncTask<Void, Void, Void>{
#Override
protected void onPreExecute(){
super.onPreExecute();
//Here we will display our progress bar. This is dependent on each page.
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Loading Talk2M Account");
pDialog.setCancelable(true);
pDialog.show();
}
#Override
protected Void doInBackground(Void... arg0){
//We need to create an object to call our service handler to make our http request.
ServiceHandler login = new ServiceHandler();
//Now we need to make a request to the url as well as recieve the response.
String response = login.makeServiceCall(url, ServiceHandler.GET);
Log.d("Response: ", "> " + response);
try{
JSONObject jsonObj = new JSONObject(response);
String session = jsonObj.getString(TAG_SESSION);
}catch(JSONException e){
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result){
super.onPostExecute(result);
if(pDialog.isShowing())
pDialog.dismiss();
}
}
If the JSON you're getting back is null, my first guess would be to verify that you are hitting the right URL. If that is the case, then there may be an issue on the api side. You may want to test this HTTP request outside of the context of your application, in a REST client or web browser.
Regards.

Windows Phone link from Tile error

I have a list of theaters and I created a secondary tile from my application to navigate directly to specific theater. I pass the id of the theater in query string :
I load the theaters from a WCF service in the file "MainViewModel.cs"
In my home page, I have a list of theaters and I can navigate to a details page.
But when I want to navigate from the tile, I have an error...
The Tile :
ShellTile.Create(new Uri("/TheaterDetails.xaml?selectedItem=" + theater.idTheater, UriKind.Relative), tile, false);
My TheaterDetails page :
public partial class TheaterDetails : PhoneApplicationPage
{
theater theater = new theater();
public TheaterDetails()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
if (DataContext == null)
{
string selectedIndex = "";
if (NavigationContext.QueryString.TryGetValue("selectedItem", out selectedIndex))
{
int index = int.Parse(selectedIndex);
theater = (from t in App.ViewModel.Theaters
where t.idTheater == index
select t).SingleOrDefault();
DataContext = theater;
....
....
....
The error :
https://dl.dropboxusercontent.com/u/9197067/error.png
Like if the data were not loaded...
Do you have an idea where the problem come from ?
The solution could be easy but I am a beginner... Maybe it's because I load the data asynchronously and the application doesn't wait until it's done...
Thanks
EDIT :
My LoadData() method :
public void LoadData()
{
client.GetTheatersCompleted += new EventHandler<ServiceReference1.GetTheatersCompletedEventArgs>(client_GetTheatersCompleted);
client.GetTheatersAsync();
// Other get methods...
this.IsDataLoaded = true;
}
private void client_GetTheatersCompleted(object sender, ServiceReference1.GetTheatersCompletedEventArgs e)
{
Theaters = e.Result;
}
You should check to see which variable is actually null. In this case it looks to be Theaters (otherwise the error would have thrown earlier).
Since Theaters is populated from a web call it is most likely being called asynchronously, in other words when you return from LoadData() the data is not yet there (it's still waiting for the web call to come back), and is waiting for the web service to return its values.
Possible solutions:
Make LoadData() an async function and then use await LoadData(). This might require a bit of rewriting / refactoring to fit into the async pattern (general introduction to async here, and specific to web calls on Windows Phone here)
A neat way of doing this that doesn't involve hacks (like looping until the data is there) is to raise a custom event when the data is actually populated and then do your Tile navigation processing in that event. There's a basic example here.
So the solution that I found, thanks to Servy in this post : Using async/await with void method
I managed to use async/await to load the data.
I replaced my LoadData() method by :
public static Task<ObservableCollection<theater>> WhenGetTheaters(ServiceClient client)
{
var tcs = new TaskCompletionSource<ObservableCollection<theater>>();
EventHandler<ServiceReference1.GetTheatersCompletedEventArgs> handler = null;
handler = (obj, args) =>
{
tcs.SetResult(args.Result);
client.GetTheatersCompleted -= handler;
};
client.GetTheatersCompleted += handler;
client.GetTheatersAsync();
return tcs.Task;
}
public async Task LoadData()
{
var theatersTask = WhenGetTheaters(client);
Theaters = await theatersTask;
IsDataLoaded = true;
}
And in my page :
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
await App.ViewModel.LoadData();
}

How do I read the basic authorization in a ASP.Net MVC4 api GET request

I have a phone app that trys to GET data from my web api using RestSharp
private void ButtonTestTap(object sender, EventArgs e)
{
var client = new RestClient
{
CookieContainer = new CookieContainer(),
BaseUrl = "http://localhost:21688/api/game",
Authenticator = new HttpBasicAuthenticator("muhcow", "123456")
};
RestRequest request = new RestRequest(Method.GET);
request.AddParameter("id", 5);
//request.AddBody(5);
client.GetAsync<LoginResult>(request, (response, ds) =>
{
System.Diagnostics.Debug.WriteLine(response.StatusDescription);
System.Diagnostics.Debug.WriteLine(response.Data);
System.Diagnostics.Debug.WriteLine(response.Content);
});
}
And then want to read the Authenticator = new HttpBasicAuthenticator("muhcow", "123456") when my api server recieves this GET request so I can verify the user, but I am not sure how to read the data.
I have this
public class GameController : ApiController
{
// GET /api/game/5
public string Get(int id)
{
var sdf2 = ControllerContext.Request.Headers.Authorization.Parameter;
//return LoginManager.VerifyLogin(loginData);
return "Some data";
}
But sdf2 just has a wierd value "bXVoY293OjEyMzQ1Ng=="
That header is base64-encoded. Apply Convert.FromBase64String() to it and you'll see the contents.
Authorization.Parameter is base64 encoded. You can look at an example of how to decode it here http://arcanecode.com/2007/03/21/encoding-strings-to-base64-in-c/
System.Text.Encoding.UTF8.GetString (Convert.FromBase64String (this.ControllerContext
.Request .Headers.Authorization.Parameter ))
the result is
"muhcow", "123456"

ASync JSON REST call problem with MVVM

I am trying to implement the MVVM patter for my WP7 Silverlight app and I am running into a problem with the async JSON Rest call. I moved into my ViewModel class the following two methods that were on my WP7 app Page.
public void FetchGames()
{
ObservableCollection<Game> G = new ObservableCollection<Game>();
//REST call in here
var webClient = new WebClient();
Uri uri = new Uri("http://www.somewebsite.com/get/games/league/" + league);
webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(OpenReadCompletedGames);
webClient.OpenReadAsync(uri);
}
private void OpenReadCompletedGames(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer ser = null;
ser = new DataContractJsonSerializer(typeof(ObservableCollection<Game>));
Games = ser.ReadObject(e.Result) as ObservableCollection<Game>;
this.IsDataLoaded = true;
}
Now the problem is that because it is an async call the following code does not work. The following code is on my app Page.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (NavigationContext.QueryString.TryGetValue("league", out league))
{
try
{
App.gViewModel.league = league;
App.gViewModel.FetchGames();
if(App.gViewModel.IsDataLoaded)
{
lbTeams.ItemsSource = App.gViewModel.Games;
}
}
catch ()
{
//error logging in here
}
}
}
Stepping thru the code shows that FetchGames is called then hits the next line ( if(App.gViewModel.IsDataLoaded)
) before the async call is finished. So IsDataLoaded is always false and I cant bind the listbox on the page.
Doing a lot of googleing I have some possible solutions but I am unable convert them to my particular problem. One is like this and it has to do with continuation passing style'. I couldn't get it to work tho and would greatly appreciate some help.
Thanks!
void DoSomethingAsync( Action<string> callback ) {
HttpWebRequest req; // TODO: build your request
req.BeginGetResponse( result => {
// This anonymous function is a closure and has access
// to the containing (or enclosing) function.
var response = req.EndGetResponse( result );
// Get the result string and call the callback
string resultString = null; // TODO: read from the stream
callback(resultString);
}, null );
}
This can be resolved by moving
lbTeams.ItemsSource = App.gViewModel.Games;
to the end of the OpenReadCompletedGames method. You'll need to use the Dispatcher to update the UI from here.
Dispatcher.BeginInvoke( () => { lbTeams.ItemsSource = App.gViewModel.Games; } );