Display Information to the UI - xamarin.forms

So what I have been trying is this: After successful registration the user gets a Message in the interface to show that Registration was successful. My first method was I declared a Message variable and use Data Binding to bind the result to a label in my RegisterPage.xaml. That failed because whether the message is successful or not the label is not showing. So I commented out using a label and tried DisplayAlert but DisplayAlert is giving an error- does not exist in the current context.
Please help, still learning.
public class RegisterViewModel
{
private readonly DataService dataService = new DataService();
public string Email { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
public string Message { get; set; }
public ICommand RegisterCommand
{
get
{
return new Command(async () =>
{
var isRegistered = await dataService.RegisterUserAsync(Email, Password, ConfirmPassword);
Settings.Username = Email;
Settings.Password = Password;
if (isRegistered)
{
//DisplayAlert( "Alert" , "Registered", "OK");
//Message = "Registered Successfully :)";
// DependencyService.Get<Toast>().Show("You have registered succefully");
Application.Current.MainPage = new NavigationPage(new EntryPage());
}
else
{
Message = " Retry Later :(";
}
});
}
}
}

DisplayAlert is part of the Page class. If you want to display an alert from a view model (there are many results on Google), you'd call a method like:
private async Task DisplayGenericDialog(string title, string message)
{
await App.Current.MainPage.DisplayAlert(title, message, "OK");
}

Related

Realtime validation of a button, using fody

I a trying to disable and enable a button based on user input. I implemented fody property changed Nuget package, to help me reduce my code a bit.
and it works, when I start typing, the breakpoint in my LoginViewModel gets hit and display my values ViewModel getting hit every time I type
but I can't seem to trigger CanLogin() method
[AddINotifyPropertyChangedInterface]
public class LoginPageViewModel {
public ICommand OpenRegisterPopupCommand { get; set; }
public ICommand Register { get; set; }
public ICommand Login { get; set; }
public Users Users { get; set; }
public bool IsPopUpOpen { get; set; }
public LoginPageViewModel() {
Users = new Users();
Login = new Command(LoginAction, CanLogin);
Register = new Command(RegisterAction);
OpenRegisterPopupCommand = new Command(() => {
IsPopUpOpen = true;
});
}
private void LoginAction(object obj) {
throw new NotImplementedException();
}
private bool CanLogin(object arg) {
if (Users != null && !string.IsNullOrEmpty(Users.Email) && !string.IsNullOrEmpty(Users.Password)) {
return true;
}
return false;
}
You are using a Command with a CanExecute method. If the CanExecute method returns false, the command will not ve able to be executed. But this validation does not happen all the time, you have to trigger it.
You have to call Login.ChangeCanExecute() when you modify any of the related properties (like Users, Users.Email or Users.Password), this will fire the CanExecute validation of the command.
Command documentation.

Xamarin App does nothing after await the GetAsync method

I have created a class, in Xamarin Forms, that requests to a web API about the details of countries. Right now, I am testing only with a country.
However, once the line "HttpResponseMessage response = await client.GetAsync(uri);" is executed, the app does nothing additional.
In order to validate if the app executes other instructions after this line, I have included additional lines to write the sequence into the device log.
All the lines before the previous instruction are written into the log and none of them after this instruction.
On the other hand, the screen of the device remains blank, without insert the Label created by code.
Here is the code of the class and the method that consumes the API.
...
using Android.Util;
using System.Net.Http;
using System.Threading.Tasks;
class Country
{
public int iIdCountry { get; set; }
public string sCountryName { get; set; }
public string sCountryIsoCode { get; set; }
public string sCountryPhoneCode { get; set; }
public bool bCountryContainsPrefix { get; set; }
public bool bCountryActive { get; set; }
private static readonly HttpClient client = new HttpClient();
public static async Task<Country> GetCountryAsync(int id)
{
string baseUri = new BaseUri().baseUri;
string sufixUri = "/CountriesApi/GetItem/" + id;
var uri = baseUri + sufixUri;
string tag = "myapp";
Country country = null;
HttpResponseMessage response = await client.GetAsync(uri);
Log.Info(tag, "Response received");
if (response.IsSuccessStatusCode)
{
country = await response.Content.ReadAsAsync<Country>();
Log.Info(tag, "Country received");
}
Log.Info(tag, "Country returned");
return country;
}
}
...
This is the component that makes the call to the previous class:
...
using Android.Util;
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace EnubexMobile.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Start : ContentPage
{
public Start()
{
var stackLayout = new StackLayout();
string tag = "myapp";
InitializeComponent();
Log.Info(tag, "Started");
var country = Country.GetCountryAsync(1).GetAwaiter().GetResult();
Log.Info(tag, country.sCountryName);
var label = new Label() { Text = country.sCountryName };
Log.Info(tag, "Label created");
stackLayout.Children.Add(label);
Log.Info(tag, "Label added");
}
private void InitializeComponent()
{
throw new NotImplementedException();
}
}
}
...
The idea is to insert a label into the StackLayout with the name of the country received from the API.
Could someone help me to understand what I am missing here?
Thanks !
Regards,

.Net Core Handle exceptions that returned from web api

I'm using .Net 5.0 as backend and .Net 5.0 for client-side.
I want to know how to handle exceptions that returned from web api in Client Side and show them to client.
The api result on exception is like :
{
"Version": "1.0",
"StatusCode": 500,
"ErrorMessage": "User not found!"
}
How to handle this type of exception globally in the client side (using .Net Core MVC)?
According to your description, I suggest you could use try catch on the server-side to capture the exception and return as a json response.
In the client side, you could use deserlize the response and create a new view named Error to show the response message.
More details, you could refer to below codes:
Error Class:
public class APIError
{
public string Version { get; set; }
public string StatusCode { get; set; }
public string ErrorMessage { get; set; }
}
API:
[HttpGet]
public IActionResult Get()
{
try
{
throw new Exception("UserNotFound");
}
catch (Exception e)
{
return Ok(new APIError { Version="1.0", ErrorMessage=e.Message, StatusCode="500" });
}
}
Application:
var request = new HttpRequestMessage(HttpMethod.Get,
"https://localhost:44371/weatherforecast");
var client = _clientFactory.CreateClient();
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var responseStream = await response.Content.ReadAsStringAsync();
APIError re = JsonSerializer.Deserialize<APIError>(responseStream, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
});
if (re.StatusCode == "500")
{
return View("Error", new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier, Version = re.Version, StatusCode = re.StatusCode, ErrorMessage = re.ErrorMessage });
}
}
else
{
// Hanlde if request failed issue
}
Notice: I created a new Error view, you could create it by yourself or modify the default error view.
Error Viewmodel:
public class ErrorViewModel
{
public string RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public string Version { get; set; }
public string StatusCode { get; set; }
public string ErrorMessage { get; set; }
}
Error view:
#model ErrorViewModel
#{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
#if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>#Model.RequestId</code>
</p>
}
<h3>#Model.StatusCode</h3>
<p>
#Model.ErrorMessage
</p>
Result:
If you don't want to use exceptions in the backend, you could just send the http status code to the client. Here is an example of reaching out to an external api via service and returning that status to the backend controller. You would then just GET this result via client side. You could also just send over the full http response to the client, instead of solely the HttpStatusCode if needed.
A little more elaboration here: https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client
//Backend Service..
private const string baseUrl = "https://api/somecrazyapi/";
public async Task<HttpStatusCode> GetUserStatusAsync(string userId)
{
var httpResponse = await client.GetAsync(baseUrl + "userId");
return httpResponse.StatusCode;
}
//Backend Controller
[ApiController]
[Route("[controller]")]
public class UserController
{
private readonly IUserService service;
public UserController(IUserService service)
{
this.service = service;
}
......
[HttpGet("{userId}")]
public HttpStatusCode GetUserStatus(string userId)
{
return service.GetUserStatusAsync(userId).Result;
}
}

Asp.Net IdentityUser add custom List Property

I am fairly new to coding with asp.net so there might be an obvious answere to my question but I haven't found one yet.
So currently I am developing a site for project management and I want the users to get notified when an event happens, eg. they were added to a new project, a project has been updated etc.
For that I have expanded the IdentityUser Model with a new property List
public class CojectUser : IdentityUser
{
public List<Notification> Notifications { get; set; }
}
public class Notification
{
public int NotificationID { get; set; }
public string Message { get; set; }
public bool Seen { get; set; }
}
When an event happens I add them to the user's notification list and update the user via the userManager.
public class EventBroker<T> : IEventBroker<T>
{
private readonly UserManager<CojectUser> userManager;
public EventBroker(UserManager<CojectUser> userMgr, IUserValidator<CojectUser> userValid)
{
userManager = userMgr;
}
public async Task NotifyAsync(Message<T> message, List<UserRole> recipients)
{
foreach (var user in recipients)
{
var cojectUser = await userManager.FindByNameAsync(user.Name);
if (cojectUser != null)
{
if (cojectUser.Notifications == null)
{
cojectUser.Notifications = new List<Notification>();
}
cojectUser.Notifications.Add(new Notification
{
Message = message.Information,
Seen = false
});
IdentityResult result = await userManager.UpdateAsync(cojectUser);
if (!result.Succeeded)
{
throw new UserUpdateFailException();
}
}
}
}
}
}
I am able to save the custom data to the database, but I am unable to load it again from database.
When I want to display the user's notifications userManager retrieves an user object with null as notification list. Even though the data is stored in database.
public async Task<IActionResult> Index()
{
CojectUser user = await userManager.GetUserAsync(User);
if(user.Notifications == null)
{
user.Notifications = new List<Notification>();
}
return View(user);
}
Data in database:
Can anybody tell me what I am doing wrong?
UserManager don't eager load properties by default.
You should use DatabaseContext directly.
var user = _context.Users.Include(c => c.Notifications).Where(u => u.Id == user.Id).ToList();

SignalR list of object undefined

I am trying to display on the console a list of object But it doesn't show the objects...
Here is the javascript I use to display the object received from the server :
connection.on("ReceiveLog", function (chatMessages) {
console.log(chatMessages);
for (var item in chatMessages) {
// work with key and value
var encodedMsg = item.User + " says " + item.Message;
var li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("messagesList").appendChild(li);
} });
The server is sending a list of ChatMessage. Here is the ChatMessage class :
public class ChatMessage
{
string User { get; set; }
string Message { get; set; }
public ChatMessage(string user, string message)
{
this.User = user;
this.Message = message;
}
}
Why are my objects completely broken ? When I break the code on the server side, it really sends the list correctly. The problem seems to be from the javascript or maybe I need to serialize from the server side ?
I needed to set all the property of the object Public like so :
public class ChatMessage
{
public string User { get; set; }
public string Message { get; set; }
public ChatMessage(string user, string message)
{
this.User = user;
this.Message = message;
}
}
It works now.

Resources