I have the below (simplified) model to display and return Chats. On the UI I want to show New Chats and Existing chats separately. When I first load the chats, it works, but if I update a Chat object, the UI doesn't update.
In the Xamarin Forms UI I have a 1) CollectionView binding to NewChats and 2) CollectionView binding to Existing Chats.
I update the IsNew flag programmatically, but that is not reflecting in the UI.
Any thoughts on how to approach this?
public class Chat
{
public string UserId {get;set;}
public bool IsNew {get;set;}
}
private ObservableCollection<Chat> _chats;
public ObservableCollection<Chat> Chats
{
get
{
return _chats;
}
set
{
this._chats= value;
OnPropertyChanged(nameof(Chats));
OnPropertyChanged(nameof(NewChats));
OnPropertyChanged(nameof(ExistingChats));
}
}
public ObservableCollection<Chat> NewChats
{
get
{
if (_chats!= null)
{
return new ObservableCollection<Chat>(_chats.Where(x => x.isNew);
}
return new ObservableCollection<Chat>();
}
}
public ObservableCollection<Chat> ExistingChats
{
get
{
if (_chat!= null)
{
return new ObservableCollection<Chat>(_chats.Where(x => !x.isNew);
}
return new ObservableCollection<Chat>();
}
}
As the comment above says For change notification to occur in a binding between a bound client and a data source, your bound type should either:
Implement the INotifyPropertyChanged interface (preferred).
Provide a change event for each property of the bound type.
you can check here to get offical sample:https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.inotifypropertychanged?view=net-6.0#definition
I'm moving my steps to OpenIDDict and I made my application based on Velusia example.
Everything works fine but I have a question: My access token doesn't include roles.
There's a way to automate the retrieving of .NET Core identity user roles and append them to the User property as Claim before accessing the action in my controller?
The purpose of all is being able to use (for example)
User.IsInRole("MyRole");
Thanks to everyone!
Reading this post gets me in the right direction: Is there a way to dynamically load claims in OpenIddict?
public class MyClaimTransformation : IClaimsTransformation
{
private readonly UserManager<UserInfo> _userManager;
public MyClaimTransformation(UserManager<UserInfo> userManager)
{
_userManager = userManager;
}
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity();
//claimsIdentity.RoleClaimType = OpenIddict.Abstractions.OpenIddictConstants.Claims.Role;
//claimsIdentity.NameClaimType = OpenIddict.Abstractions.OpenIddictConstants.Claims.Name;
var claimType = ClaimTypes.Role;
if (principal.Identity != null && principal.Identity.IsAuthenticated)
{
//Do I already have roles in the claim?
var roleClaimsAvailable = principal.Claims.Any(x => x.Type == claimType);
if (!roleClaimsAvailable)
{
//Roles not found, adding:
var userProfile = await _userManager.GetUserAsync(principal);
if (userProfile != null)
{
var roles = await _userManager.GetRolesAsync(userProfile);
foreach (var role in roles)
{
claimsIdentity.AddClaim(new Claim(claimType, role));
}
principal.AddIdentity(claimsIdentity);
}
}
}
return principal;
}
}
Than we need to register in the Startup.cs as a service:
//Adding roles on access token incoming
builder.Services.AddTransient<IClaimsTransformation, MyClaimTransformation>();
At localhost in the emulator, as soon as I connect to the bot I get the sign in card but in the azure registered channel web chat I don't get the sign in card instead I need to type something then I get it twice. webchat screenshot
How do I get the sign in card without the need to type something in chat.
I've turned the always on option and it still didn't help.
The sign in card come from the community auth middleware Link here
and i use the following code in the onTurn's bot class:
public async Task OnTurn(ITurnContext turnContext)
{
if (turnContext.Activity.UserHasJustJoinedConversation() || turnContext.Activity.UserHasJustSentMessage())
{
var state = turnContext.GetConversationState<Dictionary<string, object>>();
var dialogCtx = dialogs.CreateContext(turnContext, state);
await dialogCtx.Continue();
if (!turnContext.Responded)
{
await dialogCtx.Begin("mainDialog", new Dictionary<string, object>
{
["Value"] = turnContext.Activity.Text
});
}
}
}
and i also use the following two functions
public static bool UserHasJustSentMessage(this Activity activity)
{
return activity.Type == ActivityTypes.Message;
}
public static bool UserHasJustJoinedConversation(this Activity activity)
{
return activity.Type == ActivityTypes.ConversationUpdate && activity.MembersAdded.FirstOrDefault().Id != activity.Recipient.Id;
}
There are two ConversationUpdates that get emitted when a conversation starts: one for the user joining the conversation and one for the bot joining the conversation so you need filter out the bot's one:
public static bool UserHasJustJoinedConversation(this Activity activity)
{
return activity.Type == ActivityTypes.ConversationUpdate
&& activity.MembersAdded.Any(channelAccount => channelAccount.Id != "YourBotName");
}
I am trying to show 10,000 contacts on listview in xamarin forms using realm. But whenever user traverse to contact listing screen
it gets freezed and loads after a while.
Moreover , i have provided an option to search from list as well and that too gets stuck as search if performing on UI thread.
Following is the code to load data from realm
public override async Task Initialize(Object data )
{
private Realm _realmInstance = getRealm();
if (contactList != null)
{
contactList.Clear();
}
contactList = _realmInstance.All<Contact>().OrderByDescending(d => d.contactId).ToList();
// here the binding happens with realm data
contacts = new ObservableCollectionFast<Contact>(contactList);
}
public ObservableCollectionFast<Contact> contacts
{
get { return items; }
set
{
items = value;
OnPropertyChanged("contacts");
}
}
as it was taking time in loading i thought to fetch realm data in background and bind it on UI thread as follows
but that is throwing error
realm accessed from incorrect thread
await Task.Run(() => {
contactList = _realmInstance.All<Contact>().OrderByDescending(d => d.contactId).ToList();
});
if (contactList.Count() > 0)
{
ContactListView = true;
AddContactMsg = false;
}
else
{
AddContactMsg = true;
}
Device.BeginInvokeOnMainThread(() =>
{
contacts = new ObservableCollectionFast<Contact>(contactList);
});
i wanted to try limiting the results by using TAKE function of LINQ but unfortunately its not supported by realm yet. not sure how i can smoothly load records from realm to listview.
EDIT
as per the SushiHangover i have changed things from IList to IQueryable
public IQueryable<Contact> contacts
{
get { return items; }
set
{
items = value;
OnPropertyChanged("contacts");
}
}
public override async Task Initialize(Object data )
{
_realmInstance = getRealm();
contacts = dbContactList= _realmInstance.All<Contact>();
}
so far search is working pretty smoothly but IQueryable change leads to another issue. on repeatedly performing following steps results in app crash
tap on list item
detail page gets open then press back
scroll down to few records
perform step 1 and repeat
this results into stackoverflow error
04-19 06:05:13.980 F/art ( 3943): art/runtime/runtime.cc:289]
Pending exception java.lang.StackOverflowError thrown by 'void
md5b60ffeb829f638581ab2bb9b1a7f4f3f.CellAdapter.n_onItemClick(android.widget.AdapterView,
android.view.View, int, long):-2' 04-19 06:05:13.980 F/art (
3943): art/runtime/runtime.cc:289] java.lang.StackOverflowError: stack
size 8MB
Link to entire log file
code to fire item click command is
public ICommand OnContactSelectCommand => new Command<Contact>(OnContactSelect);
following code will open ups a detail page
private async void OnContactSelect(Contact contact)
{
if (contact != null)
{
await NavigationService.NavigateToAsync<ContactDetailViewModel>(contact.mContactId);
}
}
Note:
when i replace IQueryable with List i do not face any error
somehow my issue is related to realm github thread where user is getting exception on listView.SelectedItem = null while using IQueryable
here is my code of list view item tap
private static void ListViewOnItemTapped(object sender, ItemTappedEventArgs e)
{
var listView = sender as ListView;
if (listView != null && listView.IsEnabled && !listView.IsRefreshing)
{
// have commented this line because it was crashing the app
//listView.SelectedItem = null;
var command = GetItemTappedCommand(listView);
if (command != null && command.CanExecute(e.Item))
{
command.Execute(e.Item);
}
}
}
It sounds naive on hearing but how different are web application and Web API when someone mentions it in their paper?
How different are they from their functionalities?
Very short: web application, it's a web site, which you see in your browser, and web api, it's a service, which you use in a web application.
See also Difference between ASP.NET MVC and ASP.NET Web API:
Asp.Net MVC is used to create web applications that returns both views
and data but Asp.Net Web API is used to create full blown HTTP
services with easy and simple way that returns only data not view.
Web Applications are meant for their human interactions through views whereas Web API aka Web Services are meant for system-to-system interactions (information exchange programatically ). They exchange data.
Web Application:
It is an end-to-end solution for a user. Which means, User can:
Open it using a browser
Interact with it. He can click on something and after some processing, its result will be reflected in the browser screen. Human-System interaction
Web API
With Web APIs alone, a user can not interact with it, because it only returns data, not views.
It is a system which interacts with another system
It does not return views, it returns data
It has an endpoint set, which can be hit by other systems to get data which it provides.
Explanation using an ANALOGY
Web Application:
Suppose we have a cook. We can ask him to cook us anything, anytime!Suppose we ask our cook to cook us a burger. He'll process our request and will provide us a burger. ( This is like a Web Application; a complete solution. )
Web API
Now if we ask him to make us 'McDonalds' burger, can he cook and bring us that? No!
Here comes the concept of APIs! (for this example, lets suppose McDonalds only give takeaways to cooks only)
McDonalds-Takeaways is like an API. Which allows other systems (cooks) to hit it and bring back desired data. So we can ask our solution (our cook) to
go to McDonalds Takeaway
Buy the burger and bring us that
So what happened is, we asked our "System" to talk to this McDonalds-takeaways (API System) and bring back the result we desired.
Web app is a website that is running in your browser and web Api is service
Web API is back-end application(server side) where actual functionality to call service/database call is happening to store and retrieve the data.
Web Application is front end application(client side)which is calling web API to present the data retrieved from back-end.
eg: To check the account balance in your mobile banking app, you are able to see your account details in front end. But all the calculations of interest /balance is happening in the back end.
In simplest word, a web application's response to requests are html, css, javascript and anything that a browser can render (graphical), whereas a web api returns non-graphical "data". Having said that, I think we can make a web api work like a web application because html is still data.
Create :
public IHttpActionResult GetAllProduct()
{
IList<product> pro = null;
using (var ctx = new TestMVCEntities())
{
pro = ctx.products.ToList();
}
if (pro.Count == 0)
{
return NotFound();
}
return Ok(pro);
}
public IHttpActionResult PostNewProduct(product pro)
{
using (var ctx = new TestMVCEntities())
{
ctx.InUPProduct(pro.pid,pro.pname,pro.pprice);
ctx.SaveChanges();
}
return Ok();
}
public IHttpActionResult PutOldProduct(product pro)
{
using (var ctx = new TestMVCEntities())
{
product c = (from x in ctx.products
where x.pid == pro.pid
select x).First();
if (c != null)
{
c.pname = pro.pname;
c.pprice = pro.pprice;
ctx.SaveChanges();
}
else
{
return NotFound();
}
}
return Ok();
}
public IHttpActionResult Delete(int id)
{
using (var ctx = new TestMVCEntities())
{
var pro = ctx.products
.Where(s => s.pid == id)
.FirstOrDefault();
ctx.Entry(pro).State = System.Data.Entity.EntityState.Deleted;
ctx.SaveChanges();
}
return Ok();
}
Consume :
public JsonResult GetProductsData()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:44350/api/");
//HTTP GET
var responseTask = client.GetAsync("product");
responseTask.Wait();
var result = responseTask.Result;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadAsAsync<IList<product>>();
readTask.Wait();
var alldata = readTask.Result;
var rsproduct = from x in alldata
select new[]
{
Convert.ToString(x.pid),
Convert.ToString(x.pname),
Convert.ToString(x.pprice),
Convert.ToString(x.pimage),
Convert.ToString(x.pisdemand),
Convert.ToString(x.pcname),
Convert.ToString(x.psupply)
};
return Json(new
{
aaData = rsproduct
},
JsonRequestBehavior.AllowGet);
}
else //web api sent error response
{
var pro = Enumerable.Empty<product>();
return Json(new
{
aaData = pro
},
JsonRequestBehavior.AllowGet);
}
}
}
public JsonResult InupProduct(string id,string pname, string pprice)
{
try
{
product obj = new product
{
pid = Convert.ToInt32(id),
pname = pname,
pprice = Convert.ToDecimal(pprice)
};
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:44350/api/product");
//HTTP POST
var postTask = client.PostAsJsonAsync<product>("product", obj);
postTask.Wait();
var result = postTask.Result;
if (result.IsSuccessStatusCode)
{
return Json(1, JsonRequestBehavior.AllowGet);
}
else
{
return Json(0, JsonRequestBehavior.AllowGet);
}
}
/*context.InUPProduct(Convert.ToInt32(id),pname,Convert.ToDecimal(pprice));
return Json(1, JsonRequestBehavior.AllowGet);*/
}
catch (Exception ex)
{
return Json(0, JsonRequestBehavior.AllowGet);
}
}
public JsonResult deleteRecord(int ID)
{
try
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:44350/api/product");
//HTTP DELETE
var deleteTask = client.DeleteAsync("product/" + ID);
deleteTask.Wait();
var result = deleteTask.Result;
if (result.IsSuccessStatusCode)
{
return Json(1, JsonRequestBehavior.AllowGet);
}
else
{
return Json(0, JsonRequestBehavior.AllowGet);
}
}
/* var data = context.products.Where(x => x.pid == ID).FirstOrDefault();
context.products.Remove(data);
context.SaveChanges();
return Json(1, JsonRequestBehavior.AllowGet);*/
}
catch (Exception ex)
{
return Json(0, JsonRequestBehavior.AllowGet);
}
}