How to apply alert dialog after response - xamarin.android

public async Task<ObservableCollection<CustomerModel>> GetCustomer(string customerNumber, string department)
{
try
{
progressBar.Visibility = ViewStates.Visible;
progressBar.Progress = 0;
listofItems = new ObservableCollection<CustomerModel>();
string url = _client.BaseAddress + "/getcustomers(Number='" + customerNumber + "',department='" +
department + "')";
var response = await _client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
progressBar.Visibility = ViewStates.Invisible;
progressBar.Progress = 100;
string returnjson = await response.Content.ReadAsStringAsync();
ReplyCustomerModel replyCustomerModel =
JsonConvert.DeserializeObject<ReplyCustomerModel>(returnjson);
if (replyCustomerModel != null)
{
listofItems = replyCustomerModel.Customers;
}
}
else
{
AlertDialog.Builder alertDiag = new AlertDialog.Builder();
alertDiag.SetTitle("Butikscanner App");
alertDiag.SetMessage("User Does not exist");
alertDiag.SetPositiveButton("OK",
(senderAlert, args) => { });
alertDiag.SetNegativeButton("Cancel", (senderAlert, args) => { alertDiag.Dispose(); });
Dialog diag = alertDiag.Create();
diag.Show();
}
return listofItems;
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
Actually that is what i am doing if my response is false i am trying to show alert dialog that user does not exist I am working my project in MVVM light
Actually that is what i am doing if my response is false i am trying to show alert dialog that user does not exist I am working my project in MVVM light
Actually that is what i am doing if my response is false i am trying to show alert dialog that user does not exist I am working my project in MVVM light

Usually, API calls are made in a background thread using async-await if that is the case with you as well then I would suggest that you do is call the dialog's show method on the UIThread. For this, you will need an activity context i.e. An activity's reference.
There are two way for you to do it either directly call this method as an action something like this:
private void ShowDialog()
{
AlertDialog.Builder alertDiag = new AlertDialog.Builder();
alertDiag.SetTitle("Butikscanner App");
alertDiag.SetMessage("User Does not exist");
alertDiag.SetPositiveButton("OK",(senderAlert, args) => { });
alertDiag.SetNegativeButton("Cancel", (senderAlert, args) => { alertDiag.Dispose(); });
Dialog diag = alertDiag.Create();
diag.Show();
}
assuming above is how your method is defined you can run it on UI thread like:
activity.RunOnUIThread(ShowDialog);
But in your scenario, I do not personally think that this is a smart thing to do because the only line of code that is supposed to be on UIThread(at least i think so) is the dialog.Show();
What you should do rather would be use a lamba expression for a anonymous method something like:
private void ShowDialog(Activity activity)
{
AlertDialog.Builder alertDiag = new AlertDialog.Builder();
alertDiag.SetTitle("Butikscanner App");
alertDiag.SetMessage("User Does not exist");
alertDiag.SetPositiveButton("OK",(senderAlert, args) => { });
alertDiag.SetNegativeButton("Cancel", (senderAlert, args) => { alertDiag.Dispose(); });
Dialog diag = alertDiag.Create();
activity.RunOnUIThread(()=>
{diag.Show();});
}

Related

MVC SignalR not firing from Controller Post Method

When Saving schedule to calendar it must auto update the activity logs on my notification bar in my Home Controller. It saves the data but only show when notification bar is refreshed. It seems that Hub is not starting when saved.
CalendarController.cs
[HttpPost]
public JsonResult SaveSchedule(Schedule s)
{
var userid = User.Identity.GetUserId();
var profile = _context.Profiles.Single(p => p.Id == userid);
var status = false;
if (s.Schedule_ID > 0)
{
//Update
var v = _context.Schedules.Where(a => a.Schedule_ID == s.Schedule_ID).FirstOrDefault();
if (v != null)
{
v.Shift = s.Shift;
}
}
var activitylog = new ActivityLog
{
UserId = userid,
LogDate = DateTime.Now,
Activity = ActivityHelper.GetActivityLog(4, profile.FirstName)
};
// save to data and must be shown on notification bar
_context.ActivityLogs.Add(activitylog);
_context.SaveChanges();
ActivityHub.StartLogging();
status = true;
return new JsonResult { Data = new { status = status } };
}
HomeController.cs
public JsonResult GetLogs()
{
return Json(ActivityHelper.GetActivityLogs(), JsonRequestBehavior.AllowGet);
}
ActivityHub.cs
public class ActivityHub : Hub
{
public static void StartLogging()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<ActivityHub>();
//calls the signalR client part to execute javascript method
context.Clients.All.displayLog();
}
}
My CSHTML
<script>
$(function () {
var activityFromHub = $.connection.activityHub;
$.connection.hub.start().done(function () {
FetchLogs();
});
activityFromHub.client.displayLog = function () {
console.log('Hub Started');
FetchLogs();
}
function FetchLogs() {
$.ajax({
type: 'GET',
url: '/Home/GetLogs',
datatype: 'json',
success: function (data) {
$("#logs tr").remove();
data = $.parseJSON(data);
if (data.length > 0) {
.... do some append here
}
},
error: function (error) {
alert("error");
}
});
}
});
</script>
ActivityHelper.cs
static readonly string connString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
public static class ActivityHelper
{
public static string GetActivityLogs()
{
string sqlCommand = #"my select query here";
try
{
var messages = new List<ActivityLog>();
using(var connection = new SqlConnection(connString))
{
connection.Open();
using (SqlConnection con = new SqlConnection(connString))
{
SqlCommand cmd = new SqlCommand(sqlCommand, con);
if(con.State != System.Data.ConnectionState.Open)
{
con.Open();
}
cmd.Notification = null;
SqlDependency dependency = new SqlDependency(cmd);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
var reader = cmd.ExecuteReader();
while (reader.Read())
{
messages.Add(item: new ActivityLog
{
Activity = reader["Activity"] != DBNull.Value ? (string)reader["Activity"] : "",
LogDate = (DateTime)reader["LogDate"]
});
}
}
}
var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(messages);
return json;
}
catch(Exception ex)
{
throw;
}
}
public static void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
SqlDependency dependency = sender as SqlDependency;
dependency.OnChange -= dependency_OnChange;
var activityHub = GlobalHost.ConnectionManager.GetHubContext<ActivityHub>();
GetActivityLogs();
}
}
}
FIRST METHOD
First Solution change your javascript code like this. If this not works move to the second method:
$(function () {
var activityFromHub = $.connection.ActivityHub;
$.connection.hub.start().done(function () {
FetchLogs();
});
activityFromHub.client.displayLog = function () {
console.log('Hub Started');
FetchLogs();
}
});
SECOND METHOD:
Each client connecting to a hub passes a unique connection id. You can retrieve this value in the Context.ConnectionId property of the hub context. And i found there is nothing happening like this. You may try this solution.
I think the simplest solution for your question is to use groups.
http://www.asp.net/signalr/overview/guide-to-the-api/working-with-groups
Your hub class would contain methods to join a group:
public Task JoinGroup(string groupName)
{
return Groups.Add(Context.ConnectionId, groupName);
}
public Task LeaveGroup(string groupName)
{
return Groups.Remove(Context.ConnectionId, groupName);
}
and your hub will be look like this:
public static void StartLogging(string groupName)
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<ActivityHub>();
context.Clients.Group(groupName).displayLog();
//calls the signalR client part to execute javascript method
//context.Clients.All.displayLog();
}
And change your javascript as like this:
$(function () {
var activityFromHub = $.connection.ActivityHub;
$.connection.hub.start().done(function () {
activityFromHub.server.joinGroup("Group1");
activityFromHub.server.StartLogging("Group1");
FetchLogs();
});
activityFromHub.client.displayLog = function () {
console.log('Hub Started');
FetchLogs();
}
});
I hope this will resolve your issue. If you are still facing issue. Please leave comments. Thank you.

Showing error message after checking the back-end

My controller is something like this:
[HttpPost]
[Route("Somewhere")]
public JsonResult SetSomething(string propertyName, string propertyValue)
{
var successSave = this.SaveIt(propertyName,propertyValue);
if(successSave)
return Json(propertyValue);
else
// Show a message in front end that there was problem in saving
}
And then my view is currently something like:
#Model.SomethingFeild
That just loads the value and shows it in a textbox field in there .
So how can I change this to be able to handle the psedo-code scenario I wrote in the controller, so that if something is wrong in DB ( not front-end vlaidation) such as duplicate entry, then it comes back and tells the UI that so UI shows a hard coded message?
Wrap it in try catch block and add an extension method for reading exception (or your exception type that is thrown) like so:
[HttpPost]
[Route("Somewhere")]
public JsonResult SetSomething(string propertyName, string propertyValue)
{
try
{
var successSave = this.SaveIt(propertyName, propertyValue);
if (successSave)
return Json(new { success = true, value = propertyValue });
}
catch (Exception ex)
{
return Extensions.ReturnExceptionToView(ex);
}
}
Example extension method (static method):
internal static JsonResult ReturnExceptionToView(Exception ex)
{
List<object> viewErrors = new List<object>();
viewErrors.Add(new { ErrorMessage = ex.ToString() });
return new JsonResult() { Data = (new { success = false, errors = viewErrors }) };
}
Then check for success property in the response in JS. Example below is using response of ajax call and pushing to Knockout observable array.
if (response.success) {
// do something with successful response
} else {
// we have an error in the response.errors collection
$.each(response.errors, function () {
vm.saveErrors.push(new ErrorMsg(this.ErrorMessage));
});

WepApi TaskCanceledException A task was canceled. httpClient

It was working good, but I made some changes in the api, adding more controllers nothing out of the place, and then it stops working, always thrown an exception: "TaskCanceledException: A task was canceled" in the line GetAsync().result. I increase the timeout and infinitely stays loading.
The code controller APP who make a request to the controller API:
public ActionResult Login(LoginM us)
{
try
{
cuentaM account = new cuentaM();
HttpClient client = new HttpClient();
var result = client.GetAsync("http://localhost:26723/api/Login" + "?email=" + us.email + "&password=" + us.password).Result;
if (result.IsSuccessStatusCode)
{
account = result.Content.ReadAsAsync<cuentaM>().Result;
}
Session["cuenta"] = account;
return RedirectToAction("Index", "Home");
}
catch (Exception ex)
{
throw;
}
}
The controller API code:
public HttpResponseMessage Get(string email, string password)
{
try
{
using (elevationbEntities db = new elevationbEntities())
{
usuario user = db.usuarios.Where(m => m.email == email && m.password == password).SingleOrDefault();
cuentaM account = new cuentaM();
if (user != null)
{
account = (from o in db.cuentas
join cu in db.cuentausuarios on o.idCuenta equals cu.idCuenta
join u in db.usuarios on cu.idUsuario equals u.idUsuario
where u.idUsuario == user.idUsuario
select new cuentaM { idUsuario = user.idUsuario, idCuenta = o.idCuenta, CodigoUnico = o.CodigoUnico })
.FirstOrDefault();
}
else
{
account.Error = "Wrong Password or Email";
}
HttpResponseMessage response;
response = Request.CreateResponse(HttpStatusCode.OK, account);
return response;
}
}
catch (TaskCanceledException ex)
{
HttpResponseMessage response;
response = Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex);
return response;
}
}
Making blocking calls (.Result) on HttpClinet's async API can cause deadlocks especially if being used asp.net MVC, which may have async operations being invoked when the blocking call was made.
Make the code async all the way through.
Also try to avoid creating an instance of HttpClient on every request. This can cause sockets to be exhausted.
private static HttpClient client = new HttpClient();
public async Task<ActionResult> Login(LoginM us) {
try {
cuentaM account = new cuentaM();
var url = "http://localhost:26723/api/Login" + "?email=" + us.email + "&password=" + us.password
var result = await client.GetAsync(url);
if (result.IsSuccessStatusCode) {
account = await result.Content.ReadAsAsync<cuentaM>();
}
Session["cuenta"] = account;
return RedirectToAction("Index", "Home");
} catch (Exception ex) {
throw;
}
}
You may be deadlocking by blocking on an async call, as described in this article. Here's the problematic line:
account = result.Content.ReadAsAsync<cuentaM>().Result;
Change the method signature for Login to:
public async Task<ActionResult> Login(LoginM us)
Then change the problematic line to use await instead of .Result:
account = await result.Content.ReadAsAsync<cuentaM>();

Web ApI: HttpClient is not invoking my web api action

See first how i design my web api action.
[System.Web.Http.RoutePrefix("api/Appointments")]
public class AppointmentsServiceController : ApiController
{
[System.Web.Http.HttpGet, System.Web.Http.Route("UserAppointments/{email}")]
public IHttpActionResult UserAppointments(string email)
{
if (!string.IsNullOrEmpty(email))
{
AppointmentsService _appservice = new AppointmentsService();
IEnumerable<Entities.Appointments> app = _appservice.GetUserWiseAppointments(email);
if (app.Count() <= 0)
{
return NotFound();
}
else
{
return Ok(app);
}
}
else
{
return BadRequest();
}
}
}
Now this way i am calling web api action from my asp.net mvc action by HttpClient.
public async Task<ActionResult> List()
{
var fullAddress = ConfigurationManager.AppSettings["baseAddress"] + "api/Appointments/UserAppointments/" + Session["useremail"];
IEnumerable<Entities.Appointments> app = null;
try
{
using (var client = new HttpClient())
{
using (var response = client.GetAsync(fullAddress).Result)
{
if (response.IsSuccessStatusCode)
{
var customerJsonString = await response.Content.ReadAsStringAsync();
app = JsonConvert.DeserializeObject<IEnumerable<Entities.Appointments>>(customerJsonString);
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(response.Content.ReadAsStringAsync().Result);
//MessageBox.Show(dict["Message"]);
}
}
}
}
catch (HttpRequestException ex)
{
// catch any exception here
}
return View();
}
}
i want capture the return IEnumerable and if not data return that also i have to capture. please show me the right direction.
Where i made the mistake. thanks
Mixing async with blocking calls like .Result
var response = client.GetAsync(fullAddress).Result
And
response.Content.ReadAsStringAsync().Result
can lead to deadlocks, which is possibly why it it not hitting your API.
Refactor the code to be async all the way.
That would mean updating the using to
var response = await client.GetAsync(fullAddress)
and the reading of the content in the else statement to
await response.Content.ReadAsStringAsync()
Reference Async/Await - Best Practices in Asynchronous Programming
It looks like you are not awaiting your GetAsync call, so in the following if (response.IsSuccessStatusCode) is probably always returning false. Try calling your method like this:
using (var response = (await client.GetAsync(fullAddress)).Result)
{

Please wait screen appearing after the login button

I am trying to implement a "Wait Screen" in my BlackBerry app. The screen is to appear when the user clicks "Login" and it should go away after login has successfully been made. I am calling the screen in the "Login" listener after which I call a methd to fetch data from webs ervice. When the data is fetched, and the new screen is shown, the "Wait Screen" should disappear. However, on clicking login I get Uncaught - RuntimeException after which new screen is displayed with the "Waiting Screen" on top of it. Can somebody help me with this?
public class MessageScreen extends PopupScreen
{
private String message;
public MessageScreen (String message)
{
super( new HorizontalFieldManager(), Field.NON_FOCUSABLE);
this.message = message;
final BitmapField logo = new BitmapField(Bitmap.getBitmapResource( "cycle.gif"));
logo.setSpace( 5, 5 );
add(logo);
RichTextField rtf = new RichTextField(message, Field.FIELD_VCENTER | Field.NON_FOCUSABLE | Field.FIELD_HCENTER);
rtf.setEditable( false );
add(rtf);
}
}
I am calling this in the "Login" click event - button listener.
public void fieldChanged(Field field, int context)
{
// Push appropriate screen depending on which button was clicked
String uname = username.getText();
String pwd = passwd.getText();
if (uname.length() == 0 || pwd.length()==0) {
Dialog.alert("One of the textfield is empty!");
} else {
C0NNECTION_EXTENSION=checkInternetConnection();
if(C0NNECTION_EXTENSION==null)
{
Dialog.alert("Check internet connection and try again");
}
else
{
UiApplication.getUiApplication().invokeLater( new Runnable()
{
public void run ()
{
UiApplication.getUiApplication().pushScreen( new MessageScreen("Signing in...") );
}
} );
doLogin(uname, pwd);
}
}
}
private String doLogin(String user_id, String password)
{
String URL ="";
String METHOD_NAME = "ValidateCredentials";
String NAMESPACE = "http://tempuri.org/";
String SOAP_ACTION = NAMESPACE+METHOD_NAME;
SoapObject resultRequestSOAP = null;
HttpConnection httpConn = null;
HttpTransport httpt;
SoapPrimitive response = null;
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("username", user_id);
request.addProperty("password", password);
System.out.println("The request is=======" + request.toString());
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
httpt = new HttpTransport(URL+C0NNECTION_EXTENSION);
httpt.debug = true;
try
{
httpt.call(SOAP_ACTION, envelope);
response = (SoapPrimitive) envelope.getResponse();
String result = response.toString();
resultRequestSOAP = (SoapObject) envelope.bodyIn;
String[] listResult = split(result, sep);
strResult = listResult[0].toString();
strsessionFirstName = listResult[1].toString();
strsessionLastName = listResult[2].toString();
strsessionPictureUrl = MAINURL + listResult[3].substring(2);
strsessionStatusId = listResult[4].toString();
strsessionStatusMessage = listResult[5].toString();
strsessionLastUpdateTst = listResult[6].toString();
if(strResult.equals("credentialaccepted"))
{
if(checkBox1.getChecked() == true)
{
persistentHashtable.put("username", user_id);
persistentHashtable.put("password", password);
}
Bitmap bitmap = getLiveImage(strsessionPictureUrl, 140, 140);
StatusActivity nextScreen = new StatusActivity();
nextScreen.getUsername(user_id);
nextScreen.getPassword(password);
nextScreen.setPictureUrl(bitmap);
nextScreen.setImage(strsessionPictureUrl);
nextScreen.setFirstName(strsessionFirstName, strsessionLastName, strsessionLastUpdateTst, strsessionStatusMessage);
UiApplication.getUiApplication().pushScreen(nextScreen);
UiApplication.getUiApplication().invokeLater( new Runnable()
{
public void run ()
{
UiApplication.getUiApplication().pushScreen( UiApplication.getUiApplication().getActiveScreen() );
}
} );
}
if(strResult.equals("credentialdenied"))
{
Dialog.alert("Invalid login details.");
UiApplication.getUiApplication().pushScreen(new LoginTestScreen() );
}
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("The exception is IO==" + e.getMessage());
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
System.out.println("The exception xml parser example==="
+ e.getMessage());
}
System.out.println( resultRequestSOAP);
//UiApplication.getUiApplication().pushScreen( UiApplication.getUiApplication().getActiveScreen() );
return response + "";
//UiApplication.getUiApplication().pushScreen(new InfoScreen());
//Open a new Screen
}
Like Eugen said, you should run doLogin() on a background Thread:
final String uname = username.getText();
final String pwd = passwd.getText();
Thread backgroundWorker = new Thread(new Runnable() {
public void run() {
doLogin(uname, pwd);
}
});
backgroundWorker.start();
If you do that, you'll need to use UiApplication.invokeLater() (or another similar technique) to show your screens (back on the main/UI thread). You can't leave the doLogin() method exactly as it originally was, because it makes calls to change the UI. For example, you have a couple calls to directly use pushScreen(), which should not be called (directly) from the background.
This is not ok (from the background):
UiApplication.getUiApplication().pushScreen(nextScreen);
But, this is:
UiApplication.getUiApplication().invokeLater( new Runnable()
{
public void run ()
{
UiApplication.getUiApplication().pushScreen(nextScreen);
}
} );
But, also, what is this code supposed to do? :
UiApplication.getUiApplication().pushScreen(nextScreen);
UiApplication.getUiApplication().invokeLater( new Runnable()
{
public void run ()
{
UiApplication.getUiApplication().pushScreen( UiApplication.getUiApplication().getActiveScreen() );
}
} );
This doesn't make sense to me. What are you trying to do with those lines of code?
I see only one issue so far - networking in the UI thread. Please put all your networ operations into another Thread.run().
You could also get more detailed error description by:
1) Navigate to home screen
2) Hold alt button and press LGLG on the keyboard
3) Explore showed event log for specific error
try this -
public void fieldChanged(Field field, int context)
{
// Push appropriate screen depending on which button was clicked
String uname = username.getText();
String pwd = passwd.getText();
if (uname.length() == 0 || pwd.length()==0) {
Dialog.alert("One of the textfield is empty!");
} else {
C0NNECTION_EXTENSION=checkInternetConnection();
if(C0NNECTION_EXTENSION==null)
{
Dialog.alert("Check internet connection and try again");
}
else
{
Dialog busyDialog = new Dialog("Signing in...", null, null, 0, Bitmap.getPredefinedBitmap(Bitmap.HOURGLASS));
busyDialog.setEscapeEnabled(false);
synchronized (Application.getEventLock()) {
busyDialog.show();
}
doLogin(uname, pwd);
}
}
}

Resources