I'm creating an application that should list contacts and contacts phones. The contact list I can do, but I am being unable to list the phone numbers associated with a particular contact.
I have been leaning across the network to find a workable solution to my problem but I am being unable to find the solution.
This is the code that reads and lists the contacts.
public List<Contato> ListaContato()
{
var uri = ContactsContract.Contacts.ContentUri;
string[] projection = { ContactsContract.Contacts.InterfaceConsts.Id, ContactsContract.Contacts.InterfaceConsts.DisplayName, ContactsContract.Contacts.InterfaceConsts.PhotoId };
var cursor = Context.ContentResolver.Query(uri, projection, null, null, null);
var contactList = new List<Contato>();
if (cursor.MoveToFirst())
{
do
{
Contato contato = new Contato();
Telefone telefone = new Telefone();
contato.Id = cursor.GetInt(cursor.GetColumnIndex(projection[0]));
contato.NomeContato = cursor.GetString(cursor.GetColumnIndex(projection[1]));
contato.FotoContato = cursor.GetString(cursor.GetColumnIndex(projection[2]));
contato.Telefone = CarregarTelefone(contato.Id.ToString());
contactList.Add(contato);
}
while (cursor.MoveToNext());
}
return contactList;
}
This other method is to make the listing of phone numbers associated with a contact.
public List<Telefone> CarregarTelefone(string contactId)
{
//ContactsContract.CommonDataKinds.Phone.SearchDisplayNameKey
var cursor = Context.ContentResolver.Query(Phone.ContentUri, new String[] { Phone.Number }, ContactsContract.CommonDataKinds.Identity.IdentityColumnId + "=" + contactId, null, null);
//var c = Context.ContentResolver.Query(Phone.ContentUri, new String[] { Phone.Number }, Phone.ContentItemType + "=" + Phone.TYPE_MOBILE + " and " + Phone.CONTACT_ID + "=" + contactId, null, null);
List<Telefone> litel = new List<Telefone>();
//if (cursor.MoveToNext())
//{
// Telefone tele = new Telefone();
// tele.NumeroTelefone = cursor.GetString(0);
// litel.Add(tele);
//}
while (cursor.MoveToNext())
{
Telefone tele = new Telefone();
tele.NumeroTelefone = cursor.GetString(0);
litel.Add(tele);
}
return litel;
}
I have used this code as a reference, but it does not serve me fully.
cursor = contentResolver.query(Phone.CONTENT_URI,
new String[]{Phone.NUMBER},
Phone.TYPE + "=" + Phone.TYPE_MOBILE+" and "+Phone.CONTACT_ID + "=" + contactId, null, null);
The code is contained in this link: ContentResolver.Query()
How do I, then, be able to list all the phone numbers of a contact in my xamarin application?
Good night people!
Regarding the issue of discovering the phone's label (mobile, home, work etc) I want to say that I have already found the solution and I am sharing here with you.
public List<Telefone> CarregarTelefone(string contactId)
{
var uri = ContactsContract.Contacts.ContentUri;
string[] projection = { Phone.Number, CommonColumns.Type };
var cursor = Context.ContentResolver.Query(Phone.ContentUri, projection, ContactsContract.RawContactsColumns.ContactId + "=" + contactId, null, null);
List<Telefone> litel = new List<Telefone>();
if (cursor != null)
{
while (cursor.MoveToNext())
{
Telefone tele = new Telefone();
tele.NumeroTelefone = cursor.GetString(0);
tele.Etiqueta = CarregarEtiqueta(int.Parse(cursor.GetString(1)));
litel.Add(tele);
}
}
cursor.Close();
return litel;
}
Now I still need help solving the issue of listing a contact's groups (Family, Work, Schoolmates, Teachers etc). I have looked at some things on the web, but I have not yet succeeded. Any tip is very welcome.
I'm creating an application that should list contacts and contacts phones. The contact list I can do, but I am being unable to list the phone numbers associated with a particular contact. I have been leaning across the network to find a workable solution to my problem but I am being unable to find the solution.
You can't retrieve the phone numbers according to contactId because you are using the wrong filter string:
ContactsContract.CommonDataKinds.Identity.IdentityColumnId + "=" + contactId
The correct filter looks like this:
ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId + "=" + contactId
So CarregarTelefone should looks like this:
public List<Telefone> CarregarTelefone(string contactId)
{
var cursor = this.ContentResolver.Query(ContactsContract.CommonDataKinds.Phone.ContentUri, new string[] { Phone.Number }, ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId + "=" + contactId, null, null);
List<Telefone> litel = new List<Telefone>();
while (cursor.MoveToNext())
{
Telefone tele = new Telefone();
tele.NumeroTelefone = cursor.GetString(0);
litel.Add(tele);
}
return litel;
}
Update:
For search of etiquette, you can add a ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type column to the search columns:
var cursor = this.ContentResolver.Query(ContactsContract.CommonDataKinds.Phone.ContentUri, new string[] { Phone.Number, Phone.InterfaceConsts.Type }, ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId + "=" + contactId, null, null);
It will give you an int value.You can compare the int with the type table to get the current type of phone.
Related
I have "Search by surname", where problem is: I have to search by surname in Klijent list -> get OIB from Klijent list that matches that surname (there could be few people with same surname and different "OIB - personal identification number") -> send OIB to PoliceOsiguranja list -> print out that/those policies which are assigned to OIB.
Again, OIB is the only thing that is connecting PoliceOsiguranja and Klijent lists.
I will insert code, but that code was designed for something bit different where datas are stored in Klijent and in PoliceOsiguranja.
Console.WriteLine("Search by surname (2)");
Console.WriteLine("Input surname (prezime):");
string pPrezime = Console.ReadLine();
List<PoliceOsiguranja> lPoliceOsiguranja = DohvatiPoliceOsiguranja();
List<Klijent> lKlijent = DohvatiKlijente();
int RedniBr = 1;
long pomocniOIB = 0;
foreach (var Klijent in lKlijent)
{
if (Klijent.prezime == pPrezime)
{
nPomocna = 1;
pomocniOIB = Klijent.OIB;
Console.WriteLine("Client by OIB: " + Klijent.OIB + " - " + Klijent.ime + " " + Klijent.prezime + " " + Klijent.grad);
}
}
Console.WriteLine("Created insurance policies:");
var tablica = new ConsoleTable("Order number (RedniBr). ", "Policy number", "Type of insurance", "Date", "Date", "Value");
foreach (var PoliceOsiguranja in lPoliceOsiguranja)
{
if (PoliceOsiguranja.OIB == pomocniOIB)
{
nPomocna = 1;
tablica.AddRow(RedniBr++ + ".", PoliceOsiguranja.BrojPolice, PoliceOsiguranja.VrstaOsiguranja, PoliceOsiguranja.DatumPocetka, PoliceOsiguranja.DatumIsteka, PoliceOsiguranja.Vrijednost);
}
}
if i understood correctly what you are asking :
1 - Get oib list that match pPrezime name
IEnumerable<long> oibList = lKlijent
.Where(lk => lk.Prezime.Equals(pPrezime, StringComparison.OrdinalIgnoreCase))
.Select(o => o.OIB);
2 - Print out policies
foreach (PoliceOsiguranja policeOsiguranja in lPoliceOsiguranja)
{
if (oibList.Contains(policeOsiguranja.OIB))
{
nPomocna = 1;
tablica.AddRow(RedniBr++ +".", policeOsiguranja.BrojPolice,
policeOsiguranja.VrstaOsiguranja, policeOsiguranja.DatumPocetka,
policeOsiguranja.DatumIsteka, policeOsiguranja.Vrijednost);
}
}
I'm trying to pull some information from our VSTS hosted evironment that I need to present as report. What I observed that the API library is reporting there are no related items associated with that WorkItem even though I see related links from the VSTS web app.
Here is my code -
void Main()
{
string url = "https://[redacted].visualstudio.com";
string token = "[redacted]";
string project = "[redacted]";
string version = "[redacted]";
VssConnection conn = GetConnection(url, token);
WorkItemTrackingHttpClient witClient = conn.GetClient<WorkItemTrackingHttpClient>();
Wiql q = new Wiql();
q.Query = $"SELECT * FROM WorkItems WHERE [System.TeamProject] = '{project}' AND [System.Tags] CONTAINS '{version}' AND [System.WorkItemType] IN ('Product Backlog Item', 'Defect') ORDER BY [System.CreatedDate] desc";
var qi = witClient.QueryByWiqlAsync(q).Result;
var ids = qi.WorkItems.Select(x => x.Id);
var workitems = witClient.GetWorkItemsAsync(ids).Result.Select(r =>
{
return new
{
ItemId = r.Id,
ItemAssignedTo = r.Fields["System.AssignedTo"],
ItemCreatedBy = r.Fields["System.CreatedBy"],
ItemTitle = r.Fields["System.Title"],
ItemType = r.Fields["System.WorkItemType"],
State = r.Fields["System.State"],
ItemHasDescription = r.Fields.ContainsKey("System.Description") ? "Yes" : "No",
ItemHasAcceptanceCriteria = r.Fields.ContainsKey("Microsoft.VSTS.Common.AcceptanceCriteria") ? "Yes" : "No",
RelatedItems = r.Fields.ContainsKey("System.RelatedLinkCount") ? r.Fields["System.RelatedLinkCount"] : null //This line reports no related links,
Links = r.Links != null ? r.Links.Links : null //So does this line report null
};
});
workitems.Dump();
conn.Disconnect();
}
private static VssConnection GetConnection(string accountUri, string personalAccessToken)
{
var cred = new VssBasicCredential(string.Empty, personalAccessToken);
VssHttpMessageHandler vssHandler = new VssHttpMessageHandler(cred, VssClientHttpRequestSettings.Default.Clone());
return new VssConnection(
new Uri(accountUri),
vssHandler,
new DelegatingHandler[] { new SuppressHandler() });
}
public class SuppressHandler : DelegatingHandler
{
}
Also I'm getting these console logging which I'd like to avoid.
Web method running: [https://[redacted].visualstudio.com/_apis/wit/wiql] (POST)wiql[wit]
Is there a way I can remove these console logging?
Cannot figure out the problem based on your code.
However you can use below code sample to retrieve the work item information from VSTS, it works on my side:
To avoid getting these console logging, you can disable the Program output :
Right-click in the Output Window --> deselect the option Program output, then try it again.
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.Common;
using System;
using System.Collections.Generic;
using System.Linq;
namespace QueryWorkitems0619
{
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("https://{account}.visualstudio.com");
string PAT = "TokenHere";
string project = "ProjectName";
VssBasicCredential credentials = new VssBasicCredential("", PAT);
//create a wiql object and build our query
Wiql wiql = new Wiql()
{
Query = "Select * " +
"From WorkItems " +
"Where [Work Item Type] IN ('Product Backlog Item', 'Task') " +
"And [System.TeamProject] = '" + project + "' " +
"And [System.State] <> 'Closed' " +
"And [System.RelatedLinkCount] > '0'" +
"Order By [State] Asc, [Changed Date] Desc"
};
//create instance of work item tracking http client
using (WorkItemTrackingHttpClient workItemTrackingHttpClient = new WorkItemTrackingHttpClient(uri, credentials))
{
//execute the query to get the list of work items in the results
WorkItemQueryResult workItemQueryResult = workItemTrackingHttpClient.QueryByWiqlAsync(wiql).Result;
//some error handling
if (workItemQueryResult.WorkItems.Count() != 0)
{
//need to get the list of our work item ids and put them into an array
List<int> list = new List<int>();
foreach (var item in workItemQueryResult.WorkItems)
{
list.Add(item.Id);
}
int[] arr = list.ToArray();
//build a list of the fields we want to see
string[] fields = new string[3];
fields[0] = "System.Id";
fields[1] = "System.Title";
fields[2] = "System.RelatedLinkCount";
//get work items for the ids found in query
var workItems = workItemTrackingHttpClient.GetWorkItemsAsync(arr, fields, workItemQueryResult.AsOf).Result;
Console.WriteLine("Query Results: {0} items found", workItems.Count);
//loop though work items and write to console
foreach (var workItem in workItems)
{
Console.WriteLine("ID:{0} Title:{1} RelatedLinkCount:{2}", workItem.Id, workItem.Fields["System.Title"], workItem.Fields["System.RelatedLinkCount"]);
}
Console.ReadLine();
}
}
}
}
}
I just had a similar problem, what you have to do is use the WorkItemExpand parameter of GetWorkItemAsync method like below:
var item = client.GetWorkItemAsync(c_projectName, id, null, null, WorkItemExpand.Relations).Result;
If not used the Relations property is null, which is quite misleading. If used it stores the proper information about related work.
I am trying to write a query in neo4jclient to add/update all parts of a hierarchy tree into the database in 1 hit.
I am having trouble when it comes to using merge on collections though.
I see the foreach function but haven't been successful getting it to work.
So far I've tried the below
I've tried writing it as a full string but keep getting an exception of 'Neo4jClient.NeoException: SyntaxException: Invalid input '.': expected an identifier character, whitespace, '}' or ':' (line 6, column 90 (offset: 266))'
Below the string is how I imagine the code to work if the foreach function worked like c# but don't know the correct syntax.
Any help would be really appreciated.
public void Save(CypherAspirationsViewModel aspirations, string emailAddress)
{
var query = graphClient.Cypher
.Match("(user:User)")
.Where((CypherUser user) => user.EmailAddress == emailAddress)
// Aspirations
.Merge("user" + CypherRelationships.Aspirations + ">(aspirations:Aspirations {Guid: {aspirationsGuid}})")
.OnCreate()
.Set("aspirations = {aspirations}")
.WithParams(new
{
aspirationsGuid = aspirations.CypherAspirations.Guid,
aspirations = aspirations.CypherAspirations
});
// Permanent Remuneration
if (aspirations.CypherPermanentRemuneration != null) {
query = query.Merge("aspirations" + CypherRelationships.PermanentRemuneration + ">(permanentRemuneration:Remuneration {Guid: {permanentRemunerationGuid}})")
.OnCreate()
.Set("permanentRemuneration = {permanentRemuneration}")
.WithParams(new
{
permanentRemunerationGuid = aspirations.CypherPermanentRemuneration.Guid,
permanentRemuneration = aspirations.CypherPermanentRemuneration
});
}
// Contract Remuneration
if (aspirations.CypherContractRemuneration != null) {
query = query.Merge("aspirations" + CypherRelationships.ContractRemuneration + ">(contractRemuneration:Remuneration {Guid: {contractRemunerationGuid}})")
.OnCreate()
.Set("contractRemuneration = {contractRemuneration}")
.WithParams(new
{
contractRemunerationGuid = aspirations.CypherContractRemuneration.Guid,
contractRemuneration = aspirations.CypherContractRemuneration
});
}
// Consultant Remuneration
if(aspirations.CypherConsultantRemuneration != null)
{
query = query.Merge("aspirations" + CypherRelationships.ConsultantRemuneration + ">(consultantRemuneration:Remuneration {Guid: {consultantRemunerationGuid}})")
.OnCreate()
.Set("consultantRemuneration = {consultantRemuneration}")
.WithParams(new
{
consultantRemunerationGuid = aspirations.CypherConsultantRemuneration.Guid,
consultantRemuneration = aspirations.CypherConsultantRemuneration
});
}
// Locations
if (aspirations.CypherLocations != null)
{
//string forEachString = "(n in {locations} | merge (aspirations " + CypherRelationships.Location + ">(location:Location {Guid: {n.Guid}})) on create set location.Name = n.Name, location.Longitude = n.Longitude, location.Latitude = n.Latitude)";
//query = query
// .ForEach(forEachString)
// .WithParam("locations", aspirations.CypherLocations);
query = query.ForEach("CypherLocation location in aspirations.CypherLocations")
.Merge("aspirations" + CypherRelationships.Location + ">(location:Location {Guid: {locationGuid}})")
.OnCreate()
.Set("location = {location}")
.WithParams(new
{
locationGuid = location.Guid,
location = location
});
}
query.ExecuteWithoutResults();
}
Cypher Query:
MATCH (user:User)
WHERE (user.EmailAddress = "email")
MERGE user-[:ASPIRATIONS]->(aspirations:Aspirations {Guid: "0d700793-4702-41ee-99f1-685472e65e51"})
ON CREATE
SET aspirations = {
"FullTime": true,
"PartTime": false,
"Permanent": false,
"Contract": false,
"Consultant": false,
"WillingToRelocate": false,
"CommuteEnum": 40,
"Guid": "0d700793-4702-41ee-99f1-685472e65e51"
}
FOREACH (n in [
{
"Name": "Location1",
"Longitude": 10.0,
"Latitude": 1.0,
"Guid": "a9f25fda-9559-4723-80ec-d8711a260adc"
}
] |
merge (aspirations -[:LOCATION]->(location:Location {Guid: {n.Guid}}))
on create set location.Name = n.Name, location.Longitude = n.Longitude, location.Latitude = n.Latitude)
Ok, I think I've got it nailed. There are a few Cypher changes needed (depending on server version)
First off, the original error is from the final Merge in the ForEach - you have {Guid: {n.Guid}} but you don't need the extra {} - so it should be: {Guid: n.Guid}.
Once you've got that, if you're going against a 3.0 DB, you'll need to add some parentheses in your merge methods, for example:
.Merge("user" + CypherRelationships.Aspirations + ">(aspirations:Aspirations {Guid: {aspirationsGuid}})")
should become:
.Merge("user" + CypherRelationships.AspirationsWithClosingParentheses + ">(aspirations:Aspirations {Guid: {aspirationsGuid}})")
where AspirationsWithClosingParentheses is something like:
var AspirationsWithClosingParentheses = "Aspirations)--"
You'll need to do that for every merge, as 3.0 requires the identifiers to be surrounded!
Per iteration, this query creates an EmailRecipient for each populated address. Can it be done without the multiple iteration?
var addedRecipients = (from oldRecip in oldEmailRecipients
where !string.IsNullOrWhiteSpace(oldRecip.EmailAddress1)
select new EmailRecipient
{
UserName = oldRecip.UserName,
EmailAddress = oldRecip.EmailAddress1
}
).Union(from oldRecip in oldEmailRecipients
where !string.IsNullOrWhiteSpace(oldRecip.EmailAddress2)
select new EmailRecipient
{
UserName = oldRecip.UserName,
EmailAddress = oldRecip.EmailAddress2
});
You can use SelectMany extension method:
var addedRecipients = oldEmailRecipients.SelectMany(e=>
{
var result= new List<EmailRecipient>();
if(!string.IsNullOrWhiteSpace(e.EmailAddress1))
{
result.Add(new EmailRecipient
{
UserName = e.UserName,
EmailAddress = e.EmailAddress1
});
}
if(!string.IsNullOrWhiteSpace(e.EmailAddress2))
{
result.Add(new EmailRecipient
{
UserName = e.UserName,
EmailAddress = e.EmailAddress2
});
}
return result;
});
Update
The solution that I show above only works in Linq to Objects. Your comment suggest me you are using EF. A simple solution could be call AsEnumerable method before SelectMany to make the switch to Linq to Objects, but that could end harming your performance if you are not filtering your recipients first.
Another solution could be selecting only data that you need first from you server before of call SelectMany to not load other columns you don't need in this case:
...Where(...)
.Select(r=>new{UserName=r.UserName,
EmailAddress1=r.EmailAddress1,
EmailAddress2=r.EmailAddress2 })
.AsEnumerable()
.SelectMany(...);
Sticking with query syntax, and making sure to only process oldEmailRecipients items who have either a non-null/whitespace EmailAddress1 or a non-null/whitespace EmailAddress2:
var addedRecipients =
from oldEmail in oldEmailRecipients
let hasEmail1 = !string.IsNullOrWhiteSpace(oldEmail.EmailAddress1)
let hasEmail2 = !string.IsNullOrWhiteSpace(oldEmail.EmailAddress2)
where hasEmail1 || hasEmail2
let emailUserNameCombos = hasEmail1 && hasEmail2
? new[]
{
new {Email = oldEmail.EmailAddress1, oldEmail.UserName},
new {Email = oldEmail.EmailAddress2, oldEmail.UserName}
}
: hasEmail1
? new[] {new {Email = oldEmail.EmailAddress1, oldEmail.UserName}}
: new[] {new {Email = oldEmail.EmailAddress2, oldEmail.UserName}}
from emailUsername in emailUserNameCombos
select new EmailRecipient
{
UserName = emailUsername.UserName,
EmailAddress = emailUsername.Email
};
You can build an inline array to add both emails and flatten them out using SelectMany.
var addedRecipients = from oldRecip in oldEmailRecipients
let emails =
new[] {oldRecip.EmailAddress1, oldRecip.EmailAddress2}.Where(e => !string.IsNullOrWhiteSpace(e))
from email in emails
where emails.Any()
select new EmailRecipient
{
UserName = oldRecip.UserName,
EmailAddress = email
};
When your EmailRecipient has more than two email address then you could do this:
// Just building a pseudo dataclass
List<Recipient> oldEmailRecipients = Enumerable.Range(1, 10).Select(item => new Recipient()
{
Name = "Recipient" + item,
EmailAddress1 = "pseudo" + item + "#gmail.com",
EmailAddress2 = "pseudo" + (item + 1) + "#gmail.com",
//EmailAddress3 = "pseudo" + (item + 2) + "#gmail.com",
EmailAddress3 = "",
EmailAddress4 = "pseudo" + (item + 3) + "#gmail.com",
} ).ToList( )
// create anonymous object for each recipient and a list of valid adresses
var query = from mailRecipients in oldEmailRecipients
select new
{
Name = mailRecipients.Name,
Addresses = new List<string>()
{
mailRecipients.EmailAddress1,
mailRecipients.EmailAddress2,
mailRecipients.EmailAddress3,
mailRecipients.EmailAddress4
}.Where(item => string.IsNullOrEmpty( item ) == false )
};
// create an EmailRecipient for each valid combination
var final = from item in query
from address in item.Addresses
select new EmailRecipient
{
Name = item.Name,
Address = address
};
How can I get all friends' last statuses in one batched request? I tried the following but it is not working:
FacebookClient _FacebookClient = new FacebookClient ( Settings.AccessToken );
FacebookClient.PostCompleted += new EventHandler<FacebookApiEventArgs> ( _FacebookClient_PostCompleted );
FacebookClient.BatchAsync
(
new FacebookBatchParameter [ ]
{
new FacebookBatchParameter( HttpMethod.Get , "/me/friends" , new Dictionary<string , object> { { "fields" , "id , name , picture" } } ) { Data = new { name = "one-friend", omit_response_on_success = false } } ,
new FacebookBatchParameter{ Parameters = new { ids = "{result=one-friend:$.data.0.id}" } },
new FacebookBatchParameter("{result=one-friend:$.data.0.id}/statuses", new Dictionary<string , object> { { "limit" , "1" } , { "data" , "0" } , { "fields" , "message" } } )
}
);
I can answer your question using FQL, which is on my opinion much simplier. I used FacebookWebclient, but FacebookClient should work the same way.
FacebookWebClient fb = new FacebookWebClient();
string query0 = "SELECT uid2 FROM friend WHERE uid1 = me()"; //here you get the friends list
string query1 = "SELECT uid, message, status_id FROM status WHERE uid IN (SELECT uid2 FROM #query0)"; //here you get the last statuse of each friend (max 50, or max from the last 30 days)
string query2 = "SELECT uid, name FROM user WHERE uid IN (SELECT uid FROM #query1)"; //here you get the user data (in this case the name only)
dynamic result = fb.Query(query0, query1, query2); //all results
dynamic status = result[1][1]; //results of query1
dynamic friend = result[2][1]; //results of query2
for (int i = 0; i < result[1][1].Count; i++)
{
litFeedback.Text += "" + friend[i].name + " : "
+ status[i].message + "<br/>" + Environment.NewLine;
}
//if not using .net 4.0:
//var result = (IList<object>)fb.Query(query1, query2);
//var result0 = ((IDictionary<string, object>)result[0])["fql_result_set"];
//var result1 = ((IDictionary<string, object>)result[1])["fql_result_set"];
Note:
http://developers.facebook.com/docs/reference/fql/status/
"The status table is limited to the last 30 days or 50 posts, whichever is greater."
And of course you need the permissions for: friends_status