Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Web Development
  3. ASP.NET
  4. I am having problem creating a script to monitor Rest/API services.

I am having problem creating a script to monitor Rest/API services.

Scheduled Pinned Locked Moved ASP.NET
csharpjsoncomsysadmin
21 Posts 3 Posters 2 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Richard DeemingR Richard Deeming

    1. It looks like you've already answered that one. :) 2. Yes, you'd set the application to be the full path to your .exe file, and the command-line arguments to be the list of domains you want to test. 3. You can pass as many domains to test as you want as command-line arguments.

    samflex wrote:

    if (reply.Status != IPStatus.Success)
    {
    Console.WriteLine("{0}: {1}", site, reply.Status);
    string statusMessage = "Shw message that Server is down"; //Dont know if I am doing this correctly.
    SendEmail(); // Send out email when server is down
    return false;

    }
    else
    statusMessage = "Shw message that Server is up"; //Dont know if I am doing this correctly.

    A couple of problems there: Within the if block, you've created a local variable called statusMessage, which hides the static field of the same name. The value you store in the local variable won't be visible to the SendEmail function. You don't need the else, since you've got a return within the if block.

    samflex wrote:

    Console.WriteLine("Email Sent.");
    System.Threading.Thread.Sleep(3000);
    Environment.Exit(0);

    You shouldn't call Environment.Exit within the SendEmail function, since that will terminate your app after the first message is sent. I'd avoid using a field, and pass the message subject and body as parameters to the SendEmail function instead.

    public static void SendEmail(string subject, string body)
    {
    using MailMessage mm = new(ConfigurationManager.AppSettings["FromEmail"], "joe.blow@yahoo.com");
    mm.To.Add("joesixpack@gmail.com");
    mm.CC.Add("jandoe@gmail.com");
    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"\]),
    };
    
    Console.WriteLine("Sending email...");
    smtp.Send(mm);
    Console.WriteLine("Email sent.");
    System.Threading.Thread.Sleep(3000);
    

    }

    S Offline
    S Offline
    samflex
    wrote on last edited by
    #12

    Man, looks like you were born with this I work hard and spend a lot of time learning this but still struggle mightily. Many, many thanks sir. I am so grateful as this solution comes in handy as they are demanding demo by 10am togay. Just need one more clarification, is this right?

    YourApp.exe site1.local codeproject.com google.com

    Richard DeemingR 1 Reply Last reply
    0
    • S samflex

      Man, looks like you were born with this I work hard and spend a lot of time learning this but still struggle mightily. Many, many thanks sir. I am so grateful as this solution comes in handy as they are demanding demo by 10am togay. Just need one more clarification, is this right?

      YourApp.exe site1.local codeproject.com google.com

      Richard DeemingR Offline
      Richard DeemingR Offline
      Richard Deeming
      wrote on last edited by
      #13

      samflex wrote:

      YourApp.exe site1.local codeproject.com google.com

      That's correct, if your compiled application is YourApp.exe, and you want to test three domains - site1.local, codeproject.com, and google.com. Obviously you'd need to use your real .exe name there, and pass in the actual domains / servers you wanted to test.


      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

      "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

      S 2 Replies Last reply
      0
      • Richard DeemingR Richard Deeming

        samflex wrote:

        YourApp.exe site1.local codeproject.com google.com

        That's correct, if your compiled application is YourApp.exe, and you want to test three domains - site1.local, codeproject.com, and google.com. Obviously you'd need to use your real .exe name there, and pass in the actual domains / servers you wanted to test.


        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

        S Offline
        S Offline
        samflex
        wrote on last edited by
        #14

        Oh ok. I was confused by site1 thinking it was meant to be site as per the argument in ServerStatusBy() method. Thank God my demo pushed to 1:30pm so i can test this to see what happens. Thank you so much. I can't say this enough.

        1 Reply Last reply
        0
        • Richard DeemingR Richard Deeming

          samflex wrote:

          YourApp.exe site1.local codeproject.com google.com

          That's correct, if your compiled application is YourApp.exe, and you want to test three domains - site1.local, codeproject.com, and google.com. Obviously you'd need to use your real .exe name there, and pass in the actual domains / servers you wanted to test.


          "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

          S Offline
          S Offline
          samflex
          wrote on last edited by
          #15

          I have run into a little problem here. Console app, at least the one I am building and compiling is not generating an .exe file. For instance, the project name is showserverstatus. When I go into the bin folder, debug, I see showserverstatus.dll but not .exe As a result, I am having problem testing the app. Any ideas sir?

          Richard DeemingR 1 Reply Last reply
          0
          • S samflex

            I have run into a little problem here. Console app, at least the one I am building and compiling is not generating an .exe file. For instance, the project name is showserverstatus. When I go into the bin folder, debug, I see showserverstatus.dll but not .exe As a result, I am having problem testing the app. Any ideas sir?

            Richard DeemingR Offline
            Richard DeemingR Offline
            Richard Deeming
            wrote on last edited by
            #16

            Looks like you've created a .NET Core / .NET 5 application. You would need to publish the application to generate an exe file: Build .NET Core console application to output an EXE - Stack Overflow[^] Otherwise, you would need run it using the dotnet command:

            dotnet showserverstatus.dll site1 site2 ...

            Or you could change the target framework to net472 to generate a .NET Framework exe instead. Double-click on the project file, find the line that looks like:

            <TargetFramework>net5.0<TargetFramework>

            and change it to:

            <TargetFramework>net472</TargetFramework>

            Target frameworks in SDK-style projects - .NET | Microsoft Docs[^]


            "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

            "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

            S 1 Reply Last reply
            0
            • Richard DeemingR Richard Deeming

              Looks like you've created a .NET Core / .NET 5 application. You would need to publish the application to generate an exe file: Build .NET Core console application to output an EXE - Stack Overflow[^] Otherwise, you would need run it using the dotnet command:

              dotnet showserverstatus.dll site1 site2 ...

              Or you could change the target framework to net472 to generate a .NET Framework exe instead. Double-click on the project file, find the line that looks like:

              <TargetFramework>net5.0<TargetFramework>

              and change it to:

              <TargetFramework>net472</TargetFramework>

              Target frameworks in SDK-style projects - .NET | Microsoft Docs[^]


              "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

              S Offline
              S Offline
              samflex
              wrote on last edited by
              #17

              Sorry for all the trouble sir. Please hang in there with me a little longer if you can. I chose the path of least resistance by publishing and like you correctly stated, it generated .exe file. I tried testing and ran into an error. Please see how I was testing and the error: C:\inetpub\wwwroot\showserverstatus\bin\publish>showserverstatus.exe google.com IP Address: 2607:f8b0:4000:819::200e RoundTrip time: 44 Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object. at showserverstatus.Program.ServerStatusBy(String site) in C:\inetpub\wwwroot\showserverstatus\Program.cs:line 41 at showserverstatus.Program.Main(String[] args) in C:\inetpub\wwwroot\showserverstatus\Program.cs:line 16 As you can see, it displayed status of two lines before the error. This is line 16:

                 foreach (string site in args)
              

              and this is line 41:

                 Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
              

              UPDATE: My demo went well for the mere fact that this app actually ran and sent email was considered a success even though the email did not contain anything. Here is why. Due to the error I was getting that I posted above, I removed all of those reply.stuff and then just left only DOWN or WORKING. They wanted them worded as those. Per the changes I made below, the app ran and sent the email but when I received the email, there was no message that site is WORKING or DOWN. Is it because of the changes by replacing Subject with hardcoded values and body with hardcoded values? They also brought up something that I overlooked. They wanted Subject to read: Server Status They wanted the body to read: Please find the status of the DMZ servers below: whatever site name is - working or Down (Whatever the status is). This is latest code. Please, please forgive me sir for all these troubles. Looks like we are almost there. I changed the code below to format them just as described above. The only issue now and it is a big one is that it works with pretty much any URL I tested with except anything that begins with gis. For instance, none of these worked: https://gis.massdot.state.ma.us/arcgis/rest gis.massdot.state.ma.us/arcgis/rest/ gis.massdot.state.ma.us/arcgis/rest

              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.Ge

              Richard DeemingR 1 Reply Last reply
              0
              • S samflex

                Sorry for all the trouble sir. Please hang in there with me a little longer if you can. I chose the path of least resistance by publishing and like you correctly stated, it generated .exe file. I tried testing and ran into an error. Please see how I was testing and the error: C:\inetpub\wwwroot\showserverstatus\bin\publish>showserverstatus.exe google.com IP Address: 2607:f8b0:4000:819::200e RoundTrip time: 44 Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object. at showserverstatus.Program.ServerStatusBy(String site) in C:\inetpub\wwwroot\showserverstatus\Program.cs:line 41 at showserverstatus.Program.Main(String[] args) in C:\inetpub\wwwroot\showserverstatus\Program.cs:line 16 As you can see, it displayed status of two lines before the error. This is line 16:

                   foreach (string site in args)
                

                and this is line 41:

                   Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
                

                UPDATE: My demo went well for the mere fact that this app actually ran and sent email was considered a success even though the email did not contain anything. Here is why. Due to the error I was getting that I posted above, I removed all of those reply.stuff and then just left only DOWN or WORKING. They wanted them worded as those. Per the changes I made below, the app ran and sent the email but when I received the email, there was no message that site is WORKING or DOWN. Is it because of the changes by replacing Subject with hardcoded values and body with hardcoded values? They also brought up something that I overlooked. They wanted Subject to read: Server Status They wanted the body to read: Please find the status of the DMZ servers below: whatever site name is - working or Down (Whatever the status is). This is latest code. Please, please forgive me sir for all these troubles. Looks like we are almost there. I changed the code below to format them just as described above. The only issue now and it is a big one is that it works with pretty much any URL I tested with except anything that begins with gis. For instance, none of these worked: https://gis.massdot.state.ma.us/arcgis/rest gis.massdot.state.ma.us/arcgis/rest/ gis.massdot.state.ma.us/arcgis/rest

                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.Ge

                Richard DeemingR Offline
                Richard DeemingR Offline
                Richard Deeming
                wrote on last edited by
                #18

                Looks like the reply.Options isn't set. You will need to test for null, or use a null-conditional operator:

                if (reply.Options != null)
                {
                Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
                Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
                }
                ...
                SendEmail($"{site} Up", $@"Ping {site}
                IP Address: {reply.Address}
                RoundTrip time: {reply.RoundtripTime}
                Time to live: {reply.Options?.Ttl}
                Don't fragment: {reply.Options?.DontFragment}
                Buffer size: {reply.Buffer?.Length}");

                samflex wrote:

                For instance, none of these worked: https://gis.massdot.state.ma.us/arcgis/rest gis.massdot.state.ma.us/arcgis/rest/ gis.massdot.state.ma.us/arcgis/rest

                You're pinging a server, not a URL. It looks like gis.massdot.state.ma.us either isn't up, or is blocking pings. If you actually want to test a URL, you'd need to use a different approach. For example:

                static async Task<int> Main(string[] args)
                {
                System.Collections.Concurrent.ConcurrentDictionary<string, string> urlToStatus = new();

                IEnumerable<Task<bool>> tasks = args.Select(async url =>
                {
                    bool result = await ServerStatusByAsync(url);
                    urlToStatus.TryAdd(url, result ? "UP" : "DOWN");
                });
                
                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);
                

                }

                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"], "joeblow@yahoo.com");
                mm.To.Add("johndoe@gmail.com");
                mm.CC

                "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                S 1 Reply Last reply
                0
                • Richard DeemingR Richard Deeming

                  Looks like the reply.Options isn't set. You will need to test for null, or use a null-conditional operator:

                  if (reply.Options != null)
                  {
                  Console.WriteLine("Time to live: {0}", reply.Options.Ttl);
                  Console.WriteLine("Don't fragment: {0}", reply.Options.DontFragment);
                  }
                  ...
                  SendEmail($"{site} Up", $@"Ping {site}
                  IP Address: {reply.Address}
                  RoundTrip time: {reply.RoundtripTime}
                  Time to live: {reply.Options?.Ttl}
                  Don't fragment: {reply.Options?.DontFragment}
                  Buffer size: {reply.Buffer?.Length}");

                  samflex wrote:

                  For instance, none of these worked: https://gis.massdot.state.ma.us/arcgis/rest gis.massdot.state.ma.us/arcgis/rest/ gis.massdot.state.ma.us/arcgis/rest

                  You're pinging a server, not a URL. It looks like gis.massdot.state.ma.us either isn't up, or is blocking pings. If you actually want to test a URL, you'd need to use a different approach. For example:

                  static async Task<int> Main(string[] args)
                  {
                  System.Collections.Concurrent.ConcurrentDictionary<string, string> urlToStatus = new();

                  IEnumerable<Task<bool>> tasks = args.Select(async url =>
                  {
                      bool result = await ServerStatusByAsync(url);
                      urlToStatus.TryAdd(url, result ? "UP" : "DOWN");
                  });
                  
                  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);
                  

                  }

                  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"], "joeblow@yahoo.com");
                  mm.To.Add("johndoe@gmail.com");
                  mm.CC

                  S Offline
                  S Offline
                  samflex
                  wrote on last edited by
                  #19

                  My goodness, how did you learn all of these? WOW. Just a couple of things sir, One, I got this error: Error CS0161 'Program.Main(string[])': not all code paths return a value I am assuming that all I needed to do was copy your latest code and replace from Main all the way down. Second, runing it is still the same? That is, showserverstatus.exe google.com yahoo.com gis..../rest/, etc? I am truly in awe and so sorry for continuing to ask questions about this.

                  Richard DeemingR 1 Reply Last reply
                  0
                  • S samflex

                    My goodness, how did you learn all of these? WOW. Just a couple of things sir, One, I got this error: Error CS0161 'Program.Main(string[])': not all code paths return a value I am assuming that all I needed to do was copy your latest code and replace from Main all the way down. Second, runing it is still the same? That is, showserverstatus.exe google.com yahoo.com gis..../rest/, etc? I am truly in awe and so sorry for continuing to ask questions about this.

                    Richard DeemingR Offline
                    Richard DeemingR Offline
                    Richard Deeming
                    wrote on last edited by
                    #20

                    Sorry, missed the return statement:

                    static async Task Main(string[] args)
                    {
                    System.Collections.Concurrent.ConcurrentDictionary urlToStatus = new();

                    IEnumerable\> 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);
                    

                    }

                    Running it is still the same, except you now need to pass a list of URLs to test, rather than a list of server names to ping.


                    "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                    "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                    S 1 Reply Last reply
                    0
                    • Richard DeemingR Richard Deeming

                      Sorry, missed the return statement:

                      static async Task Main(string[] args)
                      {
                      System.Collections.Concurrent.ConcurrentDictionary urlToStatus = new();

                      IEnumerable\> 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);
                      

                      }

                      Running it is still the same, except you now need to pass a list of URLs to test, rather than a list of server names to ping.


                      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                      S Offline
                      S Offline
                      samflex
                      wrote on last edited by
                      #21

                      Oh man! Getting the following error: Unhandled exception. System.InvalidCastException: Unable to cast object of type 'SelectArrayIterator`2[System.String,System.Threading.Tasks.Task]' to type 'System.Collections.Generic.IEnumerable`1[System.Threading.Tasks.Task`1[System.Boolean]]'. It says line 21 which is this line:

                      IEnumerable> tasks = (IEnumerable>)args.Select(async url =>

                      This is the second line in Main(). Just for clarity sir, this is your version:

                      IEnumerable < Task > tasks = args.Select(async url =>

                      However, when I ran it, I got: CS0266 Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'System.Collections.Generic.IEnumerable>'. An explicit conversion exists (are you missing a cast?) When I selected the suggested explicit cast option, the error went away but then I got the other error during testing. The error occurred when I tried passing one URL as an argument to test like: showserverstatus.exe google.com UPDATE: It's always something!!! I got the error worked out; just took me awhile to figure out what was missing - return... Now, email is not working. Not getting sent. UPDATE: Once again, I panicked and didn't calm down to look for solutions. Now, it is working. It turns out that I added myemail.com.net which obviously will make it hard to receive an email. After correcting it, everything is fine now. My Lord, it is impossible to express my most heartfelt gratitude for your patience, incredible ingenuity and most of all, you don't insult me. Thank you very much sir, THANK YOU!!!

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups