jamesmontemagno / Xamarin.Plugins

Cross-platform Native API Access from Shared Code!
MIT License
1.3k stars 380 forks source link

Contacts - Problem with example Code #272

Closed CR4567 closed 7 years ago

CR4567 commented 8 years ago

Please take a moment to fill out the following (change to preview to check or place x in []):

This is a

Which plugin does this impact:

Version Number of Plugin: 2.0.2 beta1 Device Tested On: Simulator Tested On: iOS 9.3

Expected Behavior

Gets all contacts in a list

Actual Behavior

Throws an error "Expression of type 'System.Collections.Generic.IEnumerable1[Plugin.Contacts.Abstractions.Contact]' cannot be used for return type 'System.Linq.IQueryable1[Plugin.Contacts.Abstractions.Contact]'" when trying to parse the result to a List of Contacts.

Steps to reproduce the Behavior

Just doing your example code

nolazybits commented 8 years ago

Hi there,

I am trying to use your plugin and I have encountered the same error, Would you mind sharing what the solution is as this bug has been marked closed.

I'm using the 2.0.2-beta1 from NuGet

Thank you.

NiklasRaab commented 8 years ago

Me too, pleas help, or give infos!

Thank you very much.

edgargonzalez17 commented 8 years ago

Hi,

Any news on this?

Im using the sample query.

rahul-bigreco commented 8 years ago

Help pls. Same issue.

NiklasRaab commented 8 years ago

Hi,

this code works. But its a workaroud: CrossContacts.Current.PreferContactAggregation = false; var hasPermission = CrossContacts.Current.RequestPermission().Result; if (!hasPermission) return; Contact[] nameList = CrossContacts.Current.Contacts.ToArray(); Contacts = nameList.Select(contact => contact.FirstName + " " + contact.LastName);

edgargonzalez17 commented 8 years ago

@NiklasRaab doesn't work for me, nameList is null;

casamia918 commented 8 years ago

Hey. I have the same error. I thought that I found the solution but I'm not authorized to push branch, so I state the idea in this comment.

Not all xamarin developers uses .form project. It is hard to learn and the learning curve is very stiff. So, lots of developers uses xamarin.ios project and make PCL or sharing project to share the same business logic with android, and so do I.

But, as the PCL and .iOS project runs in a different assembly space, non-public methods are not run on .iOS project. This is stated at MSDN https://msdn.microsoft.com/en-us/library/ms173121.aspx.

So, the desirable solution is, change the scope to public of these methods. https://github.com/jamesmontemagno/Xamarin.Plugins/blob/master/Contacts/Contacts/Contacts.Plugin.iOS/ContactQueryProvider.cs

public IQueryable CreateQuery(Expression expression)
    {
      throw new NotImplementedException();
    }

public object Execute(Expression expression)
    {
      IQueryable<Contact> q = GetContacts().AsQueryable();

      expression = ReplaceQueryable(expression, q);

      if (expression.Type.IsGenericType && expression.Type.GetGenericTypeDefinition() == typeof(IOrderedQueryable<>))
        return q.Provider.CreateQuery(expression);
      else
        return q.Provider.Execute(expression);
    }

public    IQueryable<TElement> CreateQuery<TElement>(Expression expression)
    {
      return new Query<TElement>(this, expression);
    }

public    TResult   Execute<TResult>(Expression expression)
    {
      return (TResult)((IQueryProvider)this).Execute(expression);
    }

So.... Why change these methods? By googling the error message, it is related with the toList() of IQueryable. If you carefully debugging, the

 (CrossContacts.Current.Contacts .Where(c => !string.IsNullOrWhiteSpace(c.LastName) && c.Phones.Count > 0))

did not return IEnumerable object. It returns Plugin.Contacts.Query! This mean, the execute() is not called when the .Where() method called. If you search with keyword "IQueryable to IEnumerable", you can find lots of articles.

jamesmontemagno commented 7 years ago

Moved to: https://github.com/jamesmontemagno/ContactsPlugin/issues/2

flolovebit commented 7 years ago

My workaroud with : 2.1.0 beta 9 first as a list -> contactsList = CrossContacts.Current.Contacts.ToList (); second performe the query -> contactsList = contactsList.Where (cont => !string.IsNullOrWhiteSpace (cont.LastName) && cont.Phones.Count > 0).ToList ();

ghost commented 7 years ago
                contacts = CrossContacts.Current.Contacts.ToList();
                  //.Where(c => !string.IsNullOrWhiteSpace(c.LastName) && c.Phones.Count > 0)
                 // .ToList();
devpedrofranco commented 7 years ago

I got the same issue..... on this code: foreach (Contact contact in book.OrderBy(c => c.DisplayName)) { // Note: on certain android device(Htc for example) it show name in DisplayName Field contacts.Add(new Domain.Model.Contacts() { FirstName = contact.DisplayName, LastName = contact.LastName }); }

zanesc commented 7 years ago

Thank you @flolovebit. Your solution has worked for me on 2.2.0.29-beta on Android.