Graeme_Grant
Я собрал для вас тестовое решение, чтобы продемонстрировать, как делать клиентские связи с помощью сервиса WebAPI rest.
Пример консольного клиента демонстрирует:
* Как отправить запрос
* как читать код ответа и данные
* как разместить многослойная форма отправки данных
Пример серверного контроллера Web Api демонстрирует:
* как обрабатывать полученную почту из нескольких частей формы
* как вернуть ответ вызывающему клиенту
Клиентские приложения консоль :
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)
{
// post data
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; // Get Response
}
}
catch (Exception ex)
{
// error occured
Debug.WriteLine($"! Resp::Exception: {ex.Message}");
}
return response;
}
private static string BuldPostData(Dictionary<string, string> parameters, HttpWebRequest clientRequest)
{
// unique for each call...
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();
}
}
Контроллер: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;
}
}
Пример Вывода:
-- 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 --
Да, это не делает загрузку двоичных файлов, но это хорошая база для вас, чтобы лучше понять, как это работает. Как только вы поймете этот пример, затем посмотрите на эту ссылку, чтобы узнать, как выполнять загрузку файлов и обработку контроллера веб-API:
Отправка данных HTML-формы в ASP.NET веб-API: загрузка файлов и многострочный MIME | Microsoft Docs[
^]