Search code examples
c#uwpcontacts

UWP - Exceptions thrown when Updating Or Deleting existing contact


I am working on a app to maintain contacts, but I haven't found a way to successfully retrieve a contact I have created and perform an update or delete on that contact. I have boiled it down to a simple example:

public async Task TestContact()  
{
    try
    {
        //Make a list
        ContactStore store = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AppContactsReadWrite);
        var lists = await store.FindContactListsAsync();
        ContactList list = lists.FirstOrDefault((x) => x.DisplayName == "Test List");
        if (list == null)
        {
            list = await store.CreateContactListAsync("Test List");
            list.OtherAppReadAccess = ContactListOtherAppReadAccess.Full;
            list.OtherAppWriteAccess = ContactListOtherAppWriteAccess.SystemOnly;
            await list.SaveAsync();
        }

        //Make a contact and save it
        Contact contact = new Contact();
        contact.FirstName = "Test";
        contact.LastName = "Contact";
        await list.SaveContactAsync(contact);

        //Modify the existing one just to show that saving again works
        ContactEmail email = new ContactEmail();
        email.Address = "[email protected]";
        contact.Emails.Add(email);
        await list.SaveContactAsync(contact);  //This line updates existing contact as desired.

        //Now simulate finding that contact, modify it, and save it
        store = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AppContactsReadWrite);
        var contacts = await store.FindContactsAsync("Test Contact");
        contact = contacts[0];

        contact.Emails[0].Address = "[email protected]"; //Change a value

        lists = await store.FindContactListsAsync();
        list = lists.FirstOrDefault((x) => x.DisplayName == "Test List");

        if (list != null)
        {
            await list.SaveContactAsync(contact);   //This line throws "The operation identifier is not valid"
            await list.DeleteContactAsync(contact);  //This line throws "Value does not fall within the expected range"
        }
    }
    catch (Exception ex)
    {
        //exception thrown!
    }
}

The code creates a new list as needed, adds a contact to it, and updates that contact in place. It then tries to retrieve that contact by searching for it and calling save (or delete). Both save and delete throw exceptions as noted in the comments.

Has anyone been able to update a contact after finding it through a search? Ultimately I really want to be able to update a contact in place. I'm only trying delete as work around for not being able to save (UPDATE = DELETE + ADD)

Note that I want an IN PLACE update - I am not interested in creating a second contact that is linked to the first when I save changes. Thanks in advance!


Solution

  • The problem here is that the contacts returned from FindContactsAsync(String) method are "aggregate contacts" (even though they are not linked in People app). As they are not the raw contacts created by your app, you are not able to change or delete them directly and that's why you got errors when calling SaveContactAsync or DeleteContactAsync method.

    To solve this issue, we need to get the raw contact according to the "aggregate contact" with using FindRawContactsAsync(Contact) method and then modify, save or delete the the raw contact. For example:

    //Now simulate finding that contact, modify it, and save it
    var store = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AppContactsReadWrite);
    
    var contacts = await store.FindContactsAsync("Test Contact");
    //This contact is a "aggregate contact"
    var contact = contacts[0];
    
    //Get the raw contacts according to the "aggregate contact"
    var allStore = await ContactManager.RequestStoreAsync(ContactStoreAccessType.AllContactsReadOnly);
    var rawContacts = await allStore.AggregateContactManager.FindRawContactsAsync(contact);
    
    foreach (var rawContact in rawContacts)
    {
        var contactList = await store.GetContactListAsync(rawContact.ContactListId);
    
        if (contactList != null && contactList.DisplayName == "Test List")
        {
            rawContact.Emails[0].Address = "[email protected]"; //Change a value
    
            await contactList.SaveContactAsync(rawContact);
            //await contactList.DeleteContactAsync(rawContact);
        }
    }