Skip to content
Document DB v12 - Improved Interceptors with Soft Delete Integration, AI protections, & Admin UI with Aspire Integration!How!?

Contact Store Releases

BREAKINGFeature
Query() is now a fluent async builder. IContactStore.Query() returns a ContactQuery instead of an IQueryable<Contact>: configure it with Where(ContactField, value, ContactFilterOperation) / Where(Func<Contact,bool>) / Search(text) / Match / OrderBy / ThenBy / Skip / Take, then run it with ToListAsync(ct), FirstOrDefaultAsync(ct) or CountAsync(ct). The native read is awaited off the calling thread, so it is safe to call from the UI thread, and it finally takes a CancellationToken. Rewrite contactStore.Query().Where(c => c.GivenName.Contains("John")).ToList() as await contactStore.Query().Where(ContactField.GivenName, "John").ToListAsync(ct). See Querying.
Feature
Search(text) — one call that matches given name, family name, display name, phone numbers and email addresses (OR), which is what most contact-picker search boxes actually want. The equivalent LINQ || predicate was never translated natively.
Feature
Filtering on organization fieldsContactField.Company, JobTitle and Department are now honoured. Previously an Organization filter was extracted from the expression tree but silently dropped on Android, so it returned unfiltered results.
Enhancement
Field filters are always re-applied in-memory after the native fetch, so a filter a platform can’t translate narrows the result correctly instead of being ignored. Comparisons are consistently case-insensitive across platforms.
FixiOS
A Contains/EndsWith name filter is no longer pushed into the CNContact predicate. That predicate matches on a name-token prefix, so Contains was silently dropping valid matches; iOS now only pushes down StartsWith/Equals, and never when the query is in Match.Any mode.
Chore
The LINQ expression visitor, provider and interpreter are gone — no expression trees are built or walked at query time any more, which is a meaningful win under AOT/trimming.
BREAKINGEnhancement
Shiny.Contacts.Extensions.AI registration moved to the Shiny namespace. AddContactsAITools() now lives on Shiny.ContactsAiServiceCollectionExtensions instead of Shiny.Contacts.Extensions.AI.ServiceCollectionExtensions, so the using Shiny.Contacts.Extensions.AI; in your MauiProgram is no longer needed — Shiny is a global using from Shiny.Core. The builder/capability types (ContactAICapabilities, ContactAITools) stay where they are; only the registration entry point moved.
BREAKINGFeature
Shiny.Maui.ContactStore is now Shiny.Contacts
BREAKINGFeature
Contacts now has a dependency on Shiny.Core which allows it to work without MAUI
Feature
Shiny.Contacts.Extensions.AI — new package exposing IContactStore as Microsoft.Extensions.AI tool functions for LLM agents. Opt-in read/write allow-list via AddContactsAITools(b => b.AddContacts(ContactAICapabilities.ReadWrite)); generates search_contacts, get_contact, create_contact, update_contact, and delete_contact. AOT-compatible. See AI Tools.
Fix
Bulk reads no longer load full-resolution photosGetAll() and Query() now populate only Thumbnail; decoding every contact’s full Photo into memory at once could OOM/jetsam-kill the app on a real device with many photo contacts. The full Photo is still available per-contact via GetById(). See Photos vs Thumbnails.
Feature
IContactStore interface — full CRUD operations for device contacts: GetAll, GetById, Create, Update, Delete
Feature
LINQ query supportIQueryable<Contact> with native translation for Contains, StartsWith, EndsWith, Equals on name, phone, and email fields
Feature
MAUI permissionsContactPermission class wrapping both READ_CONTACTS and WRITE_CONTACTS with Granted, Limited, and Denied states on Android
Feature
Permission extensionsRequestPermissionsAsync() and CheckPermissionStatusAsync() extension methods on IContactStore
FeatureAndroid
PermissionStatus.Limited — returned when only one of read/write is granted, enabling read-only or write-only scenarios
Feature
GetFamilyNameFirstLetters — extension method returning sorted, distinct first letters of family names for alphabetical index UIs
Feature
Comprehensive contact model — phones, emails, addresses, dates, relationships, websites, organization, photos, and thumbnails
FeatureiOS
Notes entitlement auto-detection — gracefully handles missing com.apple.developer.contacts.notes entitlement at runtime
Feature
DI registrationbuilder.Services.AddContactStore() registers IContactStore as singleton
Feature
AOT and trimmer compatibleIsAotCompatible and EnableTrimAnalyzer enabled