I've put together a test solution for you to demonstrate how to do client comms with a WebAPI rest service.
The sample console client demonstrates:
* How to send a request
* how to read the response code & data
* how to post multi-part form post data
The sample Web Api Server controller demonstrates:
* how to handle multi-part form post received
* how to return a response to the client caller
The client console app:
internal static class Program
{
private static void Main()
{
UserWaiting();
Console.WriteLine("Good TestGetMethod....");
TestGetMethod("api/values");
Console.WriteLine("Bad TestGetMethod....");
TestGetMethod("api/valuesx");
UserWaiting();
Console.WriteLine("Good TestPostMethod....");
TestPostMethod("api/values", new Dictionary<string, string> { ["valueField"] = "test post value" });
Console.WriteLine("Bad TestPostMethod....");
TestPostMethod("api/values", null);
Console.WriteLine("\n-- DONE --");
Console.ReadKey();
}
private const string host = "http://localhost:65189";
private static void TestGetMethod(string path)
{
var response = Request(new Uri($"{host}/{path}", UriKind.Absolute),
"GET");
var ms = GetResponseStream(response);
if (response.StatusCode == HttpStatusCode.OK)
{
string responseData = GetResponseString(ms);
ReportResponse(response, responseData);
}
else
{
ReportError(response, ms);
}
}
private static void TestPostMethod(string path, Dictionary<string, string> values)
{
var response = Request(new Uri($"{host}/{path}", UriKind.Absolute),
"POST",
values);
var ms = GetResponseStream(response);
if (response.StatusCode == HttpStatusCode.OK)
{
string responseData = GetResponseString(ms);
ReportResponse(response, responseData);
}
else
{
ReportError(response, ms);
}
}
private static void UserWaiting()
{
Console.WriteLine("\n-- Waiting to begin --\n");
Console.ReadKey();
}
private static void ReportError(HttpWebResponse response, MemoryStream ms)
{
if (ms != null)
{
string responseData = GetResponseString(ms);
ReportResponse(response, responseData);
}
else
{
Console.WriteLine("!! UNHANDLED ERROR ENCOUNTERED");
}
}
private static void ReportResponse(HttpWebResponse response, string responseData, bool isError = false)
{
Console.WriteLine();
Console.WriteLine($"{(isError ? "!!" : "**")} {(int)response.StatusCode} - {response.StatusDescription}\n[{responseData}]");
Console.WriteLine();
}
private static string GetResponseString(MemoryStream ms)
{
string responseData;
using (var reader = new StreamReader(ms, Encoding.ASCII))
responseData = reader.ReadToEnd();
return responseData;
}
private static MemoryStream GetResponseStream(HttpWebResponse response)
{
MemoryStream ms = null;
if (response != null)
{
using (var responseStream = response.GetResponseStream())
{
ms = new MemoryStream();
responseStream.CopyTo(ms);
ms.Position = 0;
}
}
return ms;
}
private const string seperatorLine = "--";
private const string terminateMarker = "--";
private static HttpWebResponse Request(Uri uri, string method = "GET", Dictionary<string, string> parameters = null)
{
HttpWebResponse response = null;
try
{
var clientRequest = WebRequest.Create(uri) as HttpWebRequest;
clientRequest.Method = method;
if (method == "POST" && parameters != null)
{
var postdata = BuldPostData(parameters, clientRequest);
using (var requestStream = clientRequest.GetRequestStream())
{
byte[] byte1 = (new UTF8Encoding()).GetBytes(postdata);
requestStream.Write(byte1, 0, byte1.Length);
}
}
response = clientRequest.GetResponse() as HttpWebResponse;
}
catch (WebException wex)
{
Debug.WriteLine($"! Resp::WebException: {wex.Message}");
if (wex.Response != null)
{
response = (HttpWebResponse)wex.Response;
}
}
catch (Exception ex)
{
Debug.WriteLine($"! Resp::Exception: {ex.Message}");
}
return response;
}
private static string BuldPostData(Dictionary<string, string> parameters, HttpWebRequest clientRequest)
{
var boundary = $"MIME_{Guid.NewGuid().ToString("N")}";
var boundaryMarker = $"{seperatorLine}{boundary}";
var boundaryTerminationMarker = $"{boundaryMarker}{terminateMarker}";
clientRequest.ContentType = $"multipart/form-data; boundary=\"{boundary}\"";
var sb = new StringBuilder();
foreach (var parameter in parameters)
{
sb.AppendLine(boundaryMarker)
.AppendLine("Content-Type: text/plain; charset=utf-8")
.Append("Content-Disposition: form-data; name=\"").Append(parameter.Key).AppendLine("\"")
.AppendLine()
.AppendLine(WebUtility.HtmlEncode(parameter.Value));
}
sb.AppendLine(boundaryTerminationMarker);
return sb.ToString();
}
}
The controller:
public class ValuesController : ApiController
{
[HttpGet]
public HttpResponseMessage GetValues()
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, "value");
response.Content = new StringContent("get hello", Encoding.ASCII);
response.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromMinutes(20)
};
return response;
}
[HttpPost]
public HttpResponseMessage PostValues()
{
if (!Request.Content.IsMimeMultipartContent())
throw new HttpResponseException(HttpStatusCode.BadRequest);
var valueField = "** not set **";
var reqParams = HttpContext.Current.Request.Params;
if (reqParams.AllKeys.Contains("valueField"))
valueField = reqParams["valueField"].TrimEnd(new[] { '\r', '\n' });
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, "value");
response.Content = new StringContent($"post hello: [{valueField}]", Encoding.ASCII);
response.Headers.CacheControl = new CacheControlHeaderValue { MaxAge = TimeSpan.FromMinutes(20) };
return response;
}
}
Sample Output:
-- Waiting to begin --
Good TestGetMethod....
** 200 - OK
[get hello]
Bad TestGetMethod....
** 404 - Not Found
[{"Message":"No HTTP resource was found that matches the request URI 'http://localhost:65189/api/valuesx'.","MessageDetail":"No type was found that matches the controller named 'valuesx'."}]
-- Waiting to begin --
Good TestPostMethod....
** 200 - OK
[post hello: [test post value]]
Bad TestPostMethod....
** 411 - Length Required
[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Length Required</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Length Required</h2>
<hr><p>HTTP Error 411. The request must be chunked or have a content length.</p>
</BODY></HTML>
]
-- DONE --
Yes, this does not do binary file uploads, but it is a sound base for you to better understand how it works. Once you understand this example, next have a look at this link for how to do File uploads & Web API controller handling:
Sending HTML Form Data in ASP.NET Web API: File Upload and Multipart MIME | Microsoft Docs[
^]