I need to do a post from a console app, It will be fire and forget. I do not need to wait for the response since the posting end point is middleware and it is doing all sorts of logging. The console app just need to fire the post with a data and its job is complete. Is my approach correct and that should i use #1 or #2?
I have a sample console app which is posting to free online testing service https://httpbin.org/post
I have a List that i am posting
Test#1: In this case i am just looping through List and calling CallProcess function. CallProcess function is is using Task.Run. I have commented the response code here since this kinds of end up not being truly async. To make it truly async, should i would need to use .GetResponseAsync and .ReadToEndAsync
foreach (var person in persons)
{
Console.WriteLine($"Processing {person.Id}");
CallProcess(person);
}
and then function
private static void CallProcess(Person person)
{
Console.WriteLine($"CallProcess called for {person.ToString()}");
var endPoint = GetConfigValue("TargetEndpoint", "https://httpbin.org/post");
Task.Run(() =>
{
try
{
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; // SecurityProtocolType.Tls12
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endPoint);
var data = Encoding.ASCII.GetBytes(FillMessage(person));
request.Method = GetConfigValue("TargetMethod", "POST");
request.ContentType = GetConfigValue("TargetContentType", applicationjson);
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
Console.WriteLine($"Push Complete for {person.Id}");
using(var response = (HttpWebResponse)request.GetResponse())
{
/*
var responseValue = "";
using (var reader = new StreamReader(response.GetResponseStream()))
{
responseValue = reader.ReadToEnd();
}
Console.WriteLine($"Person {person.Id} response : {responseValue}");
*/
}
}
catch(Exception ex)
{
Console.WriteLine($"ID {person.Id} has error: {ex.ToString()}");
}
});
}
Test#2: In this case i have put Task.Run in the loop and then inside it i am calling the CallProcess2 function. Again, i have commented the response code.
foreach (var person in persons)
{
Task.Run(() =>
{
try
{
Console.WriteLine($"Processing {person.Id}");
CallProcess2(person);
}
catch (Exception ex)
{
Console.WriteLine($"{ex.ToString()}");
}
});
}
and CallProcess2 function
private static void CallProcess2(Person person)
{
Console.WriteLine($"CallProcess called for {person.ToString()}");
var endPoint = GetConfigValue("TargetEndpoint", "https://httpbin.org/post");
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; // SecurityProtocolType.Tls12
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endPoint);
var data = Encoding.ASCII.GetBytes(FillMessage(person));
request.Method = GetConfigValue("TargetMethod", "POST");
request.ContentType = GetConfigValue("TargetContentType", applicationjson);
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
Console.WriteLine($"Push Complete for {person.Id}");
using(var response = (HttpWebResponse)request.GetResponse())
{
/*
var responseValue = "";
using (var reader = new StreamReader(response.GetResponseStream()))
{
responseValue = reader.ReadToEnd();
}
Console.WriteLine($"Person {person.Id} response : {responseValue}");
*/
}
}
Here is the full code if you want to test it locally. .Net version is 4.5.1
Program.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
//testing fire and forget
namespace WebRequestTest
{
//using the free online testing service https://httpbin.org/post
class Program
{
private const string applicationXml = "application/xml";
private const string applicationjson = "application/json";
static void Main(string[] args)
{
var persons = new List<Person>()
{
new Person(){ Id = 1, Name = "John Doe", Occupation = "Gardner"},
new Person(){ Id = 2, Name = "John Smith", Occupation = "Tiles"},
new Person(){ Id = 3, Name = "John Graham", Occupation = "Kitchen"}
};
Console.WriteLine("Data Order in List<T> Loop");
Console.WriteLine("====================");
foreach (var person in persons)
{
Console.WriteLine(person.ToString());
}
Console.WriteLine("********************");
Console.WriteLine("");
Console.WriteLine("Calling Process Loop");
Console.WriteLine("====================");
//Testing #1
foreach (var person in persons)
{
Console.WriteLine($"Processing {person.Id}");
CallProcess(person);
}
//Testing #2
foreach (var person in persons)
{
Task.Run(() =>
{
try
{
Console.WriteLine($"Processing {person.Id}");
CallProcess2(person);
}
catch (Exception ex)
{
Console.WriteLine($"{ex.ToString()}");
}
});
}
Console.ReadKey();
}
private static void CallProcess(Person person)
{
Console.WriteLine($"CallProcess called for {person.ToString()}");
var endPoint = GetConfigValue("TargetEndpoint", "https://httpbin.org/post");
Task.Run(() =>
{
try
{
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; // SecurityProtocolType.Tls12
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endPoint);
var data = Encoding.ASCII.GetBytes(FillMessage(person));
request.Method = GetConfigValue("TargetMethod", "POST");
request.ContentType = GetConfigValue("TargetContentType", applicationjson);
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
Console.WriteLine($"Push Complete for {person.Id}");
using(var response = (HttpWebResponse)request.GetResponse())
{
/*
var responseValue = "";
using (var reader = new StreamReader(response.GetResponseStream()))
{
responseValue = reader.ReadToEnd();
}
Console.WriteLine($"Person {person.Id} response : {responseValue}");
*/
}
}
catch(Exception ex)
{
Console.WriteLine($"ID {person.Id} has error: {ex.ToString()}");
}
});
}
private static void CallProcess2(Person person)
{
Console.WriteLine($"CallProcess called for {person.ToString()}");
var endPoint = GetConfigValue("TargetEndpoint", "https://httpbin.org/post");
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; // SecurityProtocolType.Tls12
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endPoint);
var data = Encoding.ASCII.GetBytes(FillMessage(person));
request.Method = GetConfigValue("TargetMethod", "POST");
request.ContentType = GetConfigValue("TargetContentType", applicationjson);
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
Console.WriteLine($"Push Complete for {person.Id}");
using(var response = (HttpWebResponse)request.GetResponse())
{
/*
var responseValue = "";
using (var reader = new StreamReader(response.GetResponseStream()))
{
responseValue = reader.ReadToEnd();
}
Console.WriteLine($"Person {person.Id} response : {responseValue}");
*/
}
}
private static string FillMessage(Person person)
{
if (GetConfigValue("TargetContentType", applicationjson) == applicationXml)
{
var xmlData = ToXML(person);
Console.WriteLine($"ID {person.Id} data: {xmlData}");
return xmlData;
}
else if (GetConfigValue("TargetContentType", applicationjson) == applicationjson)
{
var jsonData = ToJSON(person);
Console.WriteLine($"ID {person.Id} data: {jsonData}");
return jsonData;
}
return string.Empty;
}
private static string ToXML(object person)
{
var xmlSerializer = new XmlSerializer(person.GetType());
string result = string.Empty;
using (StringWriter writer = new StringWriterBase())
{
xmlSerializer.Serialize(writer, person);
result = writer.ToString();
}
return result;
}
private static string ToJSON(object person)
{
return JsonConvert.SerializeObject(person);
}
private static string GetConfigValue(string key, string defaultValue = null)
{
return ConfigurationManager.AppSettings[key] ?? defaultValue;
}
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Occupation { get; set; }
public override string ToString()
{
return $"{Name} ({Id}): {Occupation}";
}
}
public class StringWriterBase : StringWriter
{
public override Encoding Encoding => Encoding.UTF8;
}
}