Reputation: 1054
None of the suggested solutions relate to my current issue.
This is a continuation of my thread yesterday:
How to format the layout of email notifications in Console Application using C#
In the above thread, I got the app to work in monitoring servers and apps running on them with some great help.
However, it turns out that some of the servers do not allow pingings.
To work around it, I attempted to rewrite the code to monitor URLs instead of servers.
Right now, I have some errors that I am struggling to resolve.
Cannot implicitly convert type '
System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task>
' to 'System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task<bool>>
'. An explicit conversion exists (are you missing a cast?)
The error is on line 22 which is this line:
IEnumerable < Task<bool> > tasks = args.Select(async url =>
Any ideas what changes I need to make to resolve this error?
using System;
using System.IO;
using System.Net;
using System.Net.Mail;
using System.Net.NetworkInformation;
using System.Text;
using System.Configuration;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Net.Http;
using System.Linq;
namespace showserverstatus
{
class Program
{
static async Task<int> Main(string[] args)
{
System.Collections.Concurrent.ConcurrentDictionary<string, string> urlToStatus = new();
//IEnumerable<Task<bool>> tasks = (IEnumerable<Task<bool>>)args.Select(async url =>
IEnumerable < Task<bool> > tasks = args.Select(async url =>
{
bool result = await ServerStatusByAsync(url);
urlToStatus.TryAdd(url, result ? "UP" : "DOWN");
});
bool[] results = await Task.WhenAll(tasks);
StringBuilder body = new("Please find the status of the servers below:");
foreach (var kvp in urlToStatus)
{
body.AppendLine();
body.AppendFormat("{0}: {1}", kvp.Key, kvp.Value);
}
await SendEmailAsync("Server Status", body.ToString());
await Task.Delay(3000);
// Return the number of servers which were down:
return results.Count(result => !result);
}
static async Task<bool> ServerStatusByAsync(string url)
{
HttpClient http = new();
using (HttpResponseMessage response = await http.GetAsync(url))
{
Console.WriteLine("GET {0}: {1}", url, response.StatusCode);
if (response.IsSuccessStatusCode)
{
await SendEmailAsync($"{url} WORKING", $"GET {url} returned {response.StatusCode}");
return true;
}
await SendEmailAsync($"{url} DOWN", $"GET {url} returned {response.StatusCode}");
return false;
}
}
static async Task SendEmailAsync(string subject, string body)
{
using MailMessage mm = new(ConfigurationManager.AppSettings["FromEmail"], "[email protected]");
mm.To.Add("[email protected]");
mm.CC.Add("[email protected]");
mm.Subject = subject;
mm.Body = body;
mm.IsBodyHtml = false;
SmtpClient smtp = new()
{
Host = ConfigurationManager.AppSettings["Host"],
Port = int.Parse(ConfigurationManager.AppSettings["Port"]),
EnableSsl = true,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(ConfigurationManager.AppSettings["Username"], ConfigurationManager.AppSettings["Password"]),
};
await smtp.SendMailAsync(mm);
}
}
}
Upvotes: 1
Views: 2927
Reputation: 3466
(Note that I have no way to test this right now, this is from intuition and documentation). I think you forgot the return in your lambda, which leads to the confusing error message as the types are erased but the compiler still manages to yell.
I assume this is what you wanted
IEnumerable <Task<bool>> tasks = args.Select(async url => {
bool result = await ServerStatusByAsync(url);
return urlToStatus.TryAdd(url, result ? "UP" : "DOWN");
});
Upvotes: 2
Reputation: 218808
Take a look at what's happening in this operation:
IEnumerable<Task<bool>> tasks = args.Select(async url =>
{
bool result = await ServerStatusByAsync(url);
urlToStatus.TryAdd(url, result ? "UP" : "DOWN");
});
The variable is expecting a list of tasks, and you are indeed returning a list of tasks. However, it's specifically requesting a list of Task<bool>
, which would be a task which resolves to a bool
. But the tasks you're supplying don't resolve to any value at all.
Either change the expected type to match what's being returned:
IEnumerable<Task> tasks = args.Select(async url =>
{
bool result = await ServerStatusByAsync(url);
urlToStatus.TryAdd(url, result ? "UP" : "DOWN");
});
Or change what's being returned to match the expected type:
IEnumerable<Task<bool>> tasks = args.Select(async url =>
{
bool result = await ServerStatusByAsync(url);
urlToStatus.TryAdd(url, result ? "UP" : "DOWN");
return result;
// or return whatever bool value you want to return
});
Upvotes: 2