Q:

System Threading Tasks String To String Conversion Error

I am trying to have photos that are on Firebase downloaded into a listview depending on the CandidateID. 
I have a task list linked as the datasource of the listview and a function to retrieve the URL from firebase. 
I have tried to add a string in the task list in order to retrieve the URL but I am getting an error message saying I cannot convert system.threading.tasks String to string. 
    public async Task<string> GetFile(string fileName)
    {      
        return await GlobalVar.firebaseStorage
            .Child("ProfilePhotos")
            .Child(fileName)
            .GetDownloadUrlAsync();
    }

    public async Task<List<JobApplication>> GetApplications()
    {
        var canInfo = await GetCandidates();
        return (await GlobalVar.firebaseClient
          .Child("JobApplication")
          .OnceAsync<JobApplication>()).Select(item => new JobApplication
          {

              CandidateID = item. Object. CandidateID,
              ApplicationDate = item. Object. ApplicationDate,
              ApplicationTime = item. Object. ApplicationTime,
              CandidateName = canInfo. Find(a => a.CandidateId == item. Object. CandidateID).Name + " " + canInfo. Find(a => a.CandidateId == item. Object. CandidateID).LastName,
              NewCanID = item. Object. CandidateID.Substring(1),
              ImageURL = GetFile(item. Object. CandidateID.Substring(1) + "-One.jpg")
          }).ToList();
    }

I've used the Eval expression in the Image Source, but there is a red line under 'GetFile(item. Object. CandidateID.Substring(1) + "-One.jpg")'.  Is there anyway I can convert this into a valid string so it can work? 

A:

I am getting an error message saying I cannot convert system.threading.tasks String to string. 

Visual Studio gives you this error because you are trying to assign a Task<string> to a string, and it's can't find a conversion.  Task<T> wraps a T, and you need to unwrap the T. The proper way to unwrap a T from a Task<T> is by using await. 
In this case, I think it's easier to break up that huge return statement and then you can see what you need to do more clearly:
public async Task<List<JobApplication>> GetApplications()
{
  var canInfo = await GetCandidates();
  var jobApplication = await GlobalVar.firebaseClient
          .Child("JobApplication")
          .OnceAsync<JobApplication>();
  return jobApplication. Select(item => new JobApplication
  {
    CandidateID = item. Object. CandidateID,
    ApplicationDate = item. Object. ApplicationDate,
    ApplicationTime = item. Object. ApplicationTime,
    CandidateName = canInfo. Find(a => a.CandidateId == item. Object. CandidateID).Name + " " + canInfo. Find(a => a.CandidateId == item. Object. CandidateID).LastName,
    NewCanID = item. Object. CandidateID.Substring(1),
    ImageURL = GetFile(item. Object. CandidateID.Substring(1) + "-One.jpg") // error
  }).ToList();
}

You need to use await on the Task<string> returned from GetFile, and this requires the lambda passed to Select to be async. 
public async Task<List<JobApplication>> GetApplications()
{
  var canInfo = await GetCandidates();
  var jobApplication = await GlobalVar.firebaseClient
          .Child("JobApplication")
          .OnceAsync<JobApplication>();
  return jobApplication. Select(async item => new JobApplication
  {
    CandidateID = item. Object. CandidateID,
    ApplicationDate = item. Object. ApplicationDate,
    ApplicationTime = item. Object. ApplicationTime,
    CandidateName = canInfo. Find(a => a.CandidateId == item. Object. CandidateID).Name + " " + canInfo. Find(a => a.CandidateId == item. Object. CandidateID).LastName,
    NewCanID = item. Object. CandidateID.Substring(1),
    ImageURL = await GetFile(item. Object. CandidateID.Substring(1) + "-One.jpg")
  }).ToList();
  // error: the code is now trying to return Task<List<Task<JobApplication>>>
}

Now, you have a sequence of tasks returned from Select.  You can either (asynchronously) wait for them to complete one at a time:
public async Task<List<JobApplication>> GetApplications()
{
  var canInfo = await GetCandidates();
  var jobApplication = await GlobalVar.firebaseClient
          .Child("JobApplication")
          .OnceAsync<JobApplication>();
  var result = new List<JobApplication>();
  foreach (var item in jobApplication)
  {
    result. Add(new JobApplication
    {
      CandidateID = item. Object. CandidateID,
      ApplicationDate = item. Object. ApplicationDate,
      ApplicationTime = item. Object. ApplicationTime,
      CandidateName = canInfo. Find(a => a.CandidateId == item. Object. CandidateID).Name + " " + canInfo. Find(a => a.CandidateId == item. Object. CandidateID).LastName,
      NewCanID = item. Object. CandidateID.Substring(1),
      ImageURL = await GetFile(item. Object. CandidateID.Substring(1) + "-One.jpg")
    });
  }
  return result;
}

Or, you can start them all simultaneously and then wait for them all to complete:
public async Task<List<JobApplication>> GetApplications()
{
  var canInfo = await GetCandidates();
  var jobApplication = await GlobalVar.firebaseClient
          .Child("JobApplication")
          .OnceAsync<JobApplication>();
  var tasks = jobApplication. Select(async item => new JobApplication
  {
    CandidateID = item. Object. CandidateID,
    ApplicationDate = item. Object. ApplicationDate,
    ApplicationTime = item. Object. ApplicationTime,
    CandidateName = canInfo. Find(a => a.CandidateId == item. Object. CandidateID).Name + " " + canInfo. Find(a => a.CandidateId == item. Object. CandidateID).LastName,
    NewCanID = item. Object. CandidateID.Substring(1),
    ImageURL = await GetFile(item. Object. CandidateID.Substring(1) + "-One.jpg")
  }).ToList();
  var result = await Task. WhenAll(tasks);
  return result. ToList();
}

