{"id":332883,"date":"2022-05-06T21:00:34","date_gmt":"2022-05-06T21:00:34","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=332883"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=332883","title":{"rendered":"<span>\u041e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0438 RazorPages \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u044b\u0445 \u0438 \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0418\u043d\u043e\u0433\u0434\u0430 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b, \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u043f\u043e\u043b\u0435\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044d\u0442\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432-\u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043a\u0430\u043a\u043e\u0433\u043e-\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043e\u0442\u0447\u0435\u0442\u044b \u0432 XML, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u043e\u0442\u044f \u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e, \u043d\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u0440\u0443\u0434\u043d\u044b\u0439 \u0434\u043b\u044f \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043a\u043e\u0434. \u041d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0442\u0435, \u043a\u0442\u043e \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0441\u044f \u0441 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c\u044e, \u0441\u043c\u043e\u0433\u0443\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u043f\u0438\u0441\u043e\u043a. \u041f\u0440\u0438\u0432\u0435\u0434\u0443 \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0437\u0430\u0434\u0430\u0447\u0443 \u0441 \u0445\u0435\u043b\u043f\u0435\u0440\u0430\u043c\u0438.<\/p>\n<h2>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/h2>\n<p>\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043a\u043b\u0438\u0435\u043d\u0442-\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0443 \u043d\u0430\u0441 \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f MVC ASP.NET, \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 &#8212; WPF, \u043d\u043e \u043d\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432  \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043a\u0430\u043a \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435, \u0442\u0430\u043a \u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439, \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043a\u043b\u0438\u0435\u043d\u0442-\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0443\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0432\u044b\u0437\u043e\u0432\u0443 \u0442\u0430\u043a\u043e\u0433\u043e \u0436\u0435 (\u043f\u043e\u0447\u0442\u0438) \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.<\/p>\n<p>\u0421\u0430\u043c\u0430 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u0432\u0430\u0436\u043d\u0430, \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u0447\u0442\u043e \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432 \u043f\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430. \u0414\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u043e\u0436\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0435\u0434\u043e\u0440\u043e\u0433\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c Contract First \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u044b.<\/p>\n<p>\u041f\u0443\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<pre><code class=\"cs\">using Net.Leksi.RestContract; using System.Collections.ObjectModel;  namespace DtoKit.Demo;  public interface IConnector {     [RoutePath(\"\/shipCalls\/{filter}\/{amount:double}\/{date}\")]     [HttpMethodGet]     [Authorization(Roles = \"1, 2, 3\")]     Task GetShipCalls(DateTime date, double amount, ShipCallsFilter filter,                        ObservableCollection&lt;IShipCallForList> list);      [RoutePath(\"\/form\")]     [HttpMethodPost]     Task Commit([Body] IShipCall shipCall);  } <\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0432\u043e\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432 \u043a\u043b\u0438\u0435\u043d\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u0442 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b ASP.NET, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0432 \u0440\u043e\u0443\u0442\u0438\u043d\u0433 \u0438\u043b\u0438 \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0442\u0435\u043b\u043e\u043c POST-\u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b ASP.NET \u0438 \u043f\u0435\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438\u0437 \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435. \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b &#171;\u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435&#187;. \u0412\u0441\u0451 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0434\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f\/\u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<p>\u041c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 \u0441\u0431\u043e\u0440\u043a\u0438, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0439 <code>IConnector<\/code>, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u044b\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0438\u0441\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">\/\/------------------------------ \/\/ Connector base \/\/ DtoKit.Demo.DemoConnectorBase \/\/ (Generated automatically) \/\/------------------------------ using Microsoft.Extensions.DependencyInjection; using Net.Leksi.Dto; using Net.Leksi.RestContract; using System.Net.Http.Json; using System.Text.Json; using System.Web;  namespace DtoKit.Demo;  public class DemoConnectorBase {     private readonly HttpConnector _httpConnector;     public DemoConnectorBase(HttpConnector httpConnector)     {         _httpConnector = httpConnector;     }      public Task&lt;HttpResponseMessage> GetShipCalls(DateTime date, Double amount,                                                    ShipCallsFilter filter)     {         DtoJsonConverterFactory getConverter = _httpConnector.Services           .GetRequiredService&lt;DtoJsonConverterFactory>();         getConverter.KeysProcessing = KeysProcessing.OnlyKeys;         JsonSerializerOptions getOptions = new();         getOptions.Converters.Add(getConverter);         string _date = HttpUtility.UrlEncode(           JsonSerializer.Serialize(date, getOptions));         string _amount = HttpUtility.UrlEncode(           JsonSerializer.Serialize(amount, getOptions));         string _filter = HttpUtility.UrlEncode(           JsonSerializer.Serialize(filter, getOptions));         string route = $\"\/shipCalls\/{_filter}\/{_amount}\/{_date}\";         HttpRequestMessage httpRequest = new(HttpMethod.Get, route);          return _httpConnector.SendAsync(httpRequest);      }      public Task&lt;HttpResponseMessage> Commit(IShipCall shipCall)     {         string route = $\"\/form\";         HttpRequestMessage httpRequest = new(HttpMethod.Post, route);          DtoJsonConverterFactory postConverter = _httpConnector.Services           .GetRequiredService&lt;DtoJsonConverterFactory>();         JsonSerializerOptions postOptions = new();         postOptions.Converters.Add(postConverter);         httpRequest.Content = JsonContent.Create(shipCall, typeof(IShipCall),                                                  default, postOptions);         return _httpConnector.SendAsync(httpRequest);      }  } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0430\u043c\u043e\u043c <\/p>\n<details class=\"spoiler\">\n<summary>\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0435:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">using Net.Leksi.RestContract; using System.Collections.ObjectModel;  namespace DtoKit.Demo;  public class Connector : DemoConnectorBase,  IConnector {     public Connector(HttpConnector httpConnector) : base(httpConnector) { }     public async Task GetShipCalls(DateTime date, double amount,      ShipCallsFilter filter, ObservableCollection&lt;IShipCallForList> list)     {     \/\/ \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0434\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430         HttpResponseMessage response = await base.GetShipCalls(date, amount,          filter);         Console.WriteLine(response.StatusCode);     \/\/ \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0442\u0432\u0435\u0442\u0430, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0432      \/\/ ObservableCollection&lt;IShipCallForList> list \u0434\u043b\u044f \u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 UI     \/\/ (\u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d)     }      public async Task Commit(IShipCall shipCall)     {         HttpResponseMessage response = await base.Commit(shipCall);         Console.WriteLine(response.StatusCode);     } } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0432 <\/p>\n<details class=\"spoiler\">\n<summary>\u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u044c:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">\/\/------------------------------ \/\/ MVC Controller proxy  \/\/ DtoKit.Demo.DemoControllerProxy \/\/ (Generated automatically) \/\/------------------------------ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Net.Leksi.Dto; using System.Text.Json;  namespace DtoKit.Demo;  public class DemoControllerProxy : Controller {      [Route(\"\/shipCalls\/{filter}\/{amount:double}\/{date}\")]     [HttpGet]     [Authorize(Roles = \"1, 2, 3\")]     public async Task GetShipCalls(String date, Double amount, String filter)     {         DtoJsonConverterFactory converter = HttpContext.RequestServices         .GetRequiredService&lt;DtoJsonConverterFactory>();         JsonSerializerOptions options = new();         options.Converters.Add(converter);         DateTime _date = JsonSerializer.Deserialize&lt;DateTime>(date, options);         ShipCallsFilter _filter = JsonSerializer.Deserialize&lt;ShipCallsFilter>(         filter, options);         Controller controller = (Controller)HttpContext.RequestServices         .GetRequiredService&lt;IDemoController>();         controller.ControllerContext = ControllerContext;         await ((IDemoController)controller).GetShipCalls(_date, amount, _filter);     }      [Route(\"\/form\")]     [HttpPost]     public async Task Commit()     {         DtoJsonConverterFactory converter = HttpContext.RequestServices         .GetRequiredService&lt;DtoJsonConverterFactory>();         JsonSerializerOptions options = new();         options.Converters.Add(converter);         IShipCall shipCall = await HttpContext.Request         .ReadFromJsonAsync&lt;IShipCall>(options);         Controller controller = (Controller)HttpContext.RequestServices         .GetRequiredService&lt;IDemoController>();         controller.ControllerContext = ControllerContext;         await ((IDemoController)controller).Commit(shipCall);     }  } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u043b\u043e\u0433\u0438\u043a\u0443:<\/p>\n<details class=\"spoiler\">\n<summary>\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u043b\u043e\u0433\u0438\u043a\u0443:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">\/\/------------------------------ \/\/ MVC Controller interface  \/\/ DtoKit.Demo.IDemoController \/\/ (Generated automatically) \/\/------------------------------  namespace DtoKit.Demo;  public interface IDemoController {     Task GetShipCalls(DateTime date, Double amount, ShipCallsFilter filter);     Task Commit(IShipCall shipCall); } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h2>\u041d\u0430\u043c \u0431\u044b \u043c\u043e\u0433\u043b\u0430 \u043f\u043e\u0434\u043e\u0439\u0442\u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 RazorPages<\/h2>\n<p>\u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0451 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438, \u043c\u044b \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0446\u0435\u043b\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b.<\/p>\n<details class=\"spoiler\">\n<summary>\u0428\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">@page @using Net.Leksi.RestContract @model Net.Leksi.RestContract.Pages.ConnectorBaseModel \/\/------------------------------ \/\/ Connector base \/\/ @string.Join(\".\", new string[] { Model.NamespaceValue, Model.ClassName}) \/\/ (Generated automatically) \/\/------------------------------ @foreach(string usng in Model.Usings) {     &lt;text>using @usng; &lt;\/text> }  namespace @Model.NamespaceValue;  public class @Model.ClassName {     private readonly HttpConnector _httpConnector;     public @Model.ClassName@{&lt;text\/>}(HttpConnector httpConnector)     {         _httpConnector = httpConnector;     }     @foreach (MethodModel mm in Model.Methods)     { &lt;text>     public Task&lt;HttpResponseMessage> @mm.Name@{&lt;text\/>}(@for(int i = 0; i &lt; mm.Parameters.Count; ++i)         {                 if(i > 0){&lt;text>, &lt;\/text>}                 &lt;text>@mm.Parameters[i].Type @mm.Parameters[i].Name&lt;\/text>         })     {@if(mm.HasSerialized)         { &lt;text>         DtoJsonConverterFactory @mm.GetConverterVariable = _httpConnector.Services.GetRequiredService&lt;DtoJsonConverterFactory>();         @mm.GetConverterVariable@{&lt;text\/>}.KeysProcessing = KeysProcessing.OnlyKeys;         JsonSerializerOptions @mm.GetOptionsVariable = new();         @mm.GetOptionsVariable@{&lt;text\/>}.Converters.Add(@mm.GetConverterVariable);&lt;\/text>             foreach(Tuple&lt;string, string, string> tuple in mm.Deserializing)             { &lt;text>         @tuple.Item1 @tuple.Item2 = HttpUtility.UrlEncode(JsonSerializer.Serialize(@tuple.Item3, @mm.GetOptionsVariable));&lt;\/text>             }         } @* @if(mm.HasSerialized) *@                  string @mm.RouteVariable = @Html.Raw($\"$\\\"{@mm.RouteValue}\\\"\");         HttpRequestMessage @mm.HttpRequestVariable = new(HttpMethod.@mm.HttpMethod, @mm.RouteVariable);         @if(mm.PostConverterVariable is { })         { &lt;text>         DtoJsonConverterFactory @mm.PostConverterVariable = _httpConnector.Services.GetRequiredService&lt;DtoJsonConverterFactory>();         JsonSerializerOptions @mm.PostOptionsVariable = new();         @mm.PostOptionsVariable@{&lt;text\/>}.Converters.Add(@mm.PostConverterVariable);         @mm.HttpRequestVariable@{&lt;text\/>}.Content = JsonContent.Create(@mm.BodyVariable, typeof(@mm.BodyType), default, @mm.PostOptionsVariable);&lt;\/text>         }          return _httpConnector.SendAsync(@mm.HttpRequestVariable);          }@* public async ... *@ &lt;\/text>     }@* @foreach (MethodModel mm in Model.Methods) *@ }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u0428\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f \u043f\u0440\u043e\u043a\u0441\u0438-\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">@page @using Net.Leksi.RestContract @model Net.Leksi.RestContract.Pages.ControllerProxyModel \/\/------------------------------ \/\/ MVC Controller proxy  \/\/ @string.Join(\".\", new string[] { Model.NamespaceValue, Model.ClassName}) \/\/ (Generated automatically) \/\/------------------------------ @foreach(string usng in Model.Usings) {     &lt;text>using @usng; &lt;\/text> }  namespace @Model.NamespaceValue;  public class @Model.ClassName: Controller {     @foreach (MethodModel mm in Model.Methods)     {         foreach(AttributeModel am in mm.Attributes)         { &lt;text>         [@am.Name@if (am.Properties.Count > 0) {&lt;text>(&lt;\/text>             string[] keys = am.Properties.Keys.ToArray();             for(int i = 0; i &lt; keys.Length; ++i)             {                 if(i > 0){&lt;text>, &lt;\/text>}                 if(!string.IsNullOrEmpty(keys[i])){&lt;text>@keys[i] = &lt;\/text>}&lt;text>@Html.Raw(am.Properties[keys[i]])&lt;\/text>             }             &lt;text>)&lt;\/text> }]&lt;\/text>         } &lt;text>     public async @mm.Type @mm.Name@{&lt;text\/>}(@for(int i = 0; i &lt; mm.Parameters.Count; ++i)         {                 if(i > 0){&lt;text>, &lt;\/text>}                 &lt;text>@mm.Parameters[i].Type @mm.Parameters[i].Name&lt;\/text>         })     {@if(mm.HasSerialized)         { &lt;text>         DtoJsonConverterFactory @mm.GetConverterVariable = HttpContext.RequestServices.GetRequiredService&lt;DtoJsonConverterFactory>();         JsonSerializerOptions @mm.GetOptionsVariable = new();         @mm.GetOptionsVariable@{&lt;text\/>}.Converters.Add(@mm.GetConverterVariable);&lt;\/text>             foreach(Tuple&lt;string, string, string> tuple in mm.Deserializing)             {                 if(tuple.Item3 is null)                 { &lt;text>         @tuple.Item1 @tuple.Item2 = await HttpContext.Request.ReadFromJsonAsync&lt;@tuple.Item1>(@mm.GetOptionsVariable);&lt;\/text>                 }                 else                 { &lt;text>         @tuple.Item1 @tuple.Item2 = JsonSerializer.Deserialize&lt;@tuple.Item1>(@tuple.Item3, @mm.GetOptionsVariable);&lt;\/text>                 }             }         } @* @if(mm.HasSerialized) *@                  Controller @mm.ControllerVariable = (Controller)HttpContext.RequestServices.GetRequiredService&lt;@mm.ControllerInterfaceClassName>();         @mm.ControllerVariable@{&lt;text\/>}.ControllerContext = ControllerContext;         await ((@mm.ControllerInterfaceClassName)@mm.ControllerVariable).@mm.Name@{&lt;text\/>}(@for(int i = 0; i &lt; mm.ControllerParameters.Count; ++i)         {             if(i > 0){&lt;text>, &lt;\/text>}             &lt;text>@mm.ControllerParameters[i]&lt;\/text>         });     }@* public async ... *@ &lt;\/text>     }@* @foreach (MethodModel mm in Model.Methods) *@ }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u0428\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">@page @using Net.Leksi.RestContract @model Net.Leksi.RestContract.Pages.ControllerInterfaceModel \/\/------------------------------ \/\/ MVC Controller interface  \/\/ @string.Join(\".\", new string[] { Model.NamespaceValue, Model.ClassName}) \/\/ (Generated automatically) \/\/------------------------------ @foreach(string usng in Model.Usings) {     &lt;text>using @usng; &lt;\/text> }  namespace @Model.NamespaceValue;  public interface @Model.ClassName  {     @foreach (MethodModel mm in Model.Methods)     {         &lt;text>    @mm.Type @mm.Name&lt;\/text>&lt;text>(&lt;\/text>         @for(int i = 0; i &lt; mm.Parameters.Count; ++i)         {             if(i > 0)             {                 &lt;text>, &lt;\/text>             }             &lt;text>@mm.Parameters[i].Type @mm.Parameters[i].Name&lt;\/text>         }         &lt;text>); &lt;\/text>     } } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h2>\u0418\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u044f\u0446\u0438\u044f RazorPages \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/h2>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u0431\u0435\u0437 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435.<\/p>\n<pre><code class=\"cs\">public static class Generator { ...            public static async IAsyncEnumerable&lt;KeyValuePair&lt;string, object>>        Generate(IEnumerable&lt;object> requisite, IEnumerable&lt;string> requests)     {       ...     }<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c <code>IEnumerable&lt;object> requisite<\/code> &#8212; \u0432\u0441\u0451, \u0447\u0442\u043e \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438. \u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e <code>object<\/code> \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c:<\/p>\n<ul>\n<li>\n<p>\u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440  \u043a\u043b\u0430\u0441\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u043b\u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0439 \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438. \u042d\u0442\u043e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0432 \u0441\u043b\u0443\u0436\u0431\u0430\u0445 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043a\u0430\u043a <code>ServiceLifetime.Singleton<\/code> \u043f\u043e\u0434 \u0441\u0432\u043e\u0438\u043c \u0442\u0438\u043f\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p><code>KeyValuePair&lt;Type, object><\/code>, \u0433\u0434\u0435 <code>Value<\/code>&#8212; \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440, \u043a\u0430\u043a \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c \u043f\u0443\u043d\u043a\u0442\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u043a\u0430\u043a <code>ServiceLifetime.Singleton<\/code> \u043f\u043e\u0434 \u0442\u0438\u043f\u043e\u043c <code>Key<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>Type<\/code> &#8212; \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u043a\u0430\u043a <code>ServiceLifetime.Transient<\/code> .<\/p>\n<\/li>\n<li>\n<p><code>KeyValuePair&lt;Type, Type><\/code> &#8212; <code>Value<\/code> \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u043a\u0430\u043a <code>ServiceLifetime.Transient<\/code> \u043f\u043e\u0434 \u0442\u0438\u043f\u043e\u043c <code>Key<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>Assembly<\/code> &#8212; \u0441\u0431\u043e\u0440\u043a\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f \u0432 \u043f\u0430\u043f\u043a\u0435 Pages \u0441\u0430\u043c\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0441 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438. \u0415\u0441\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u043f\u0443\u043d\u043a\u0442\u043e\u0432 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0432 \u044d\u0442\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0435, \u0442\u043e \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c.<\/p>\n<\/li>\n<\/ul>\n<p><code>IEnumerable&lt;string> requests<\/code> &#8212; \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c, \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u043f\u0443\u0442\u0438. \u041c\u043e\u0436\u043d\u043e \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043b\u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u0440\u0435\u0448\u0430\u0442\u044c, \u043a\u0430\u043a\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441. \u0418\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0437\u0434\u0435\u0441\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u0438\u043b\u0438 \u043c\u0430\u0441\u0441\u0438\u0432. \u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0441 \u0440\u0435\u043a\u0432\u0438\u0437\u0438\u0442\u043e\u043c, \u043d\u043e \u043e\u043d \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0442\u0430\u043a \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0432\u0438\u0441\u0435\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>IAsyncEnumerable&lt;KeyValuePair&lt;string, object>><\/code> &#8212; \u043f\u0430\u0440\u044b, \u0433\u0434\u0435 <code>Key<\/code> &#8212; \u0441\u0442\u0440\u043e\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0430 <code>Value<\/code> &#8212; \u043b\u0438\u0431\u043e \u0441\u0442\u0440\u043e\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043e\u0442\u0432\u0435\u0442\u0430, \u043b\u0438\u0431\u043e <code>Exception<\/code>, \u0435\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u043f\u043e\u0448\u043b\u043e \u043d\u0435 \u0442\u0430\u043a \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u0421\u0430\u043c \u043c\u0435\u0442\u043e\u0434 \u043d\u0435 \u043f\u0430\u0434\u0430\u0435\u0442, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u0440\u0435\u0448\u0430\u0435\u0442, \u0447\u0442\u043e \u0441 \u044d\u0442\u0438\u043c \u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0434\u0435\u0441\u044c<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">using Microsoft.AspNetCore.Diagnostics; using System.Net.NetworkInformation; using System.Reflection;  namespace Net.Leksi.DocsRazorator;  public static class Generator {     private const string SecretWordHeader = \"X-Secret-Word\";     private const int MaxTcpPort = 65535;     private const int StartTcpPort = 5000;      public static async IAsyncEnumerable&lt;KeyValuePair&lt;string, object>> Generate(IEnumerable&lt;object> requisite,          IEnumerable&lt;string> requests)     {         ManualResetEventSlim appStartedGate = new();         WebApplication app = null!;         HttpClient client = null!;         string secretWord = Guid.NewGuid().ToString();          Exception? razorPageException = null;          appStartedGate.Reset();          Task loadTask = Task.Run(() =>         {             int port = MaxTcpPort + 1;             List&lt;Assembly> assemblies = new();             List&lt;object> services = new();             foreach (object obj in requisite)             {                 if (obj is Assembly asm)                 {                     if (!assemblies.Contains(asm))                     {                         assemblies.Add(asm);                     }                  }                 else if (obj is KeyValuePair&lt;Type, Type> typeTypePair)                 {                     Assembly assembly = typeTypePair.Value.Assembly;                     if (!assemblies.Contains(assembly))                     {                         assemblies.Add(assembly);                     }                     if (services.Find(v => v is KeyValuePair&lt;Type, object> p &amp;&amp; p.Key == typeTypePair.Key                          &amp;&amp; Object.ReferenceEquals(p.Value, typeTypePair.Value)) is null)                     {                         services.Add(obj);                     }                 }                 else if (obj is KeyValuePair&lt;Type, object> typeObjectPair)                 {                     Assembly assembly = typeObjectPair.Value.GetType().Assembly;                     if (!assemblies.Contains(assembly))                     {                         assemblies.Add(assembly);                     }                     if (services.Find(v => v is KeyValuePair&lt;Type, object> p &amp;&amp; p.Key == typeObjectPair.Key                          &amp;&amp; Object.ReferenceEquals(p.Value, typeObjectPair.Value)) is null)                     {                         services.Add(obj);                     }                 }                 else if (obj is Type type)                 {                     Assembly assembly = type.Assembly;                     if (!assemblies.Contains(assembly))                     {                         assemblies.Add(assembly);                     }                     if (!services.Contains(obj))                     {                         services.Add(obj);                     }                 }                 else                 {                     Assembly assembly = obj.GetType().Assembly;                     if (!assemblies.Contains(assembly))                     {                         assemblies.Add(assembly);                     }                     if (!services.Contains(obj))                     {                         services.Add(obj);                     }                 }             }             while (true)             {                 IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();                 int[] usedPorts = ipGlobalProperties.GetActiveTcpConnections()                         .Select(v => v.LocalEndPoint.Port).Where(v => v >= StartTcpPort).OrderBy(v => v).ToArray();                 for (int i = 1; i &lt; usedPorts.Length; ++i)                 {                     if (usedPorts[i] > usedPorts[i - 1] + 1)                     {                         port = usedPorts[i] - 1;                         break;                     }                 }                 if (port > MaxTcpPort)                 {                     try                     {                         throw new Exception(\"No TCP port is available.\");                     }                     finally                     {                         appStartedGate.Set();                     }                 }                  WebApplicationBuilder builder = WebApplication.CreateBuilder(new string[] { });                  builder.Logging.ClearProviders();                  builder.Services.AddRazorPages();                  IMvcBuilder mvcBuilder = builder.Services.AddControllersWithViews();                 foreach (Assembly assembly in assemblies)                 {                     mvcBuilder.AddApplicationPart(assembly);                 }                  foreach (object obj in services)                 {                     if(obj is KeyValuePair&lt;Type, Type> typeTypePair)                     {                             builder.Services.AddTransient(typeTypePair.Key, typeTypePair.Value);                     }                     else if (obj is KeyValuePair&lt;Type, object> typeObjectPair)                     {                         builder.Services.AddSingleton(typeObjectPair.Key, op =>                         {                             return typeObjectPair.Value;                         });                     }                     else if(obj is Type type)                     {                         builder.Services.AddTransient(type);                     }                     else                     {                                                  builder.Services.AddSingleton(obj.GetType(), op =>                         {                             return obj;                         });                     }                 }                  app = builder.Build();                  app.UseExceptionHandler(eapp =>                 {                     eapp.Run(async context =>                     {                         var exceptionHandlerPathFeature =                             context.Features.Get&lt;IExceptionHandlerPathFeature>();                          razorPageException = exceptionHandlerPathFeature?.Error;                         context.Response.StatusCode = StatusCodes.Status500InternalServerError;                     });                 });                  app.Use(async (context, next) =>                 {                     if (!context.Request.Headers.ContainsKey(SecretWordHeader) || !context.Request.Headers[SecretWordHeader].Contains(secretWord))                     {                         context.Response.StatusCode = StatusCodes.Status403Forbidden;                         await context.Response.WriteAsync(String.Empty);                     }                     else                     {                         await next.Invoke(context);                     }                 });                  app.MapRazorPages();                  app.Lifetime.ApplicationStarted.Register(() =>                 {                     appStartedGate.Set();                 });                  app.Urls.Clear();                 app.Urls.Add($\"http:\/\/localhost:{port}\");                 try                 {                     app.Run();                     break;                 }                 catch (IOException ex) { }             }         });          appStartedGate.Wait();          if (loadTask.IsFaulted)         {             throw loadTask.Exception;         }         client = new HttpClient();         client.BaseAddress = new Uri(app.Urls.First());         client.DefaultRequestHeaders.Add(SecretWordHeader, secretWord);         foreach (string request in requests)         {             razorPageException = null;              HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, request);              HttpResponseMessage response = await client.SendAsync(requestMessage);              if(razorPageException is { })             {                 yield return new KeyValuePair&lt;string, object>(request, razorPageException);             }             else if (response.IsSuccessStatusCode)             {                 yield return new KeyValuePair&lt;string, object>(request, await response.Content.ReadAsStringAsync());             }                      }         await app.StopAsync();      } } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442<\/p>\n<pre><code class=\"cs\">{     ManualResetEventSlim appStartedGate = new();     WebApplication app = null!;     HttpClient client = null!;     string secretWord = Guid.NewGuid().ToString();      Exception? razorPageException = null;      appStartedGate.Reset();      ... }<\/code><\/pre>\n<p>\u0412\u043e\u0440\u043e\u0442\u0430 <code>ManualResetEventSlim appStartedGate<\/code> \u043e\u0442\u043a\u0440\u043e\u044e\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0441\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 <code>WebApplication app<\/code>.  <code>HttpClient client<\/code> \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b. <code>string secretWord<\/code> \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445. \u0412 <code>Exception? razorPageException<\/code> \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043a\u0430\u0442\u044c <code>Exception<\/code>, \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0432\u043e\u0439 \u0432\u043e\u0437\u043d\u0438\u043a \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c <code>WebApplication app<\/code> &#8230;<\/p>\n<pre><code class=\"cs\">{         ...     \/\/ \u0417\u0430\u0434\u0430\u0447\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 WebApplication Task loadTask = Task.Run(() =>         {         int port = MaxTcpPort + 1;         List&lt;Assembly> assemblies = new();         List&lt;object> services = new();         foreach (object obj in requisite)         {           \/\/ \u0421\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u043a\u0432\u0438\u0437\u0438\u0442\u044b           ...         }         while (true)         {           \/\/ \u0418\u0449\u0435\u043c \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u044b\u0439 TCP \u043f\u043e\u0440\u0442             IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();             int[] usedPorts = ipGlobalProperties.GetActiveTcpConnections()                     .Select(v => v.LocalEndPoint.Port).Where(v => v >= StartTcpPort).OrderBy(v => v).ToArray();             for (int i = 1; i &lt; usedPorts.Length; ++i)             {                 if (usedPorts[i] > usedPorts[i - 1] + 1)                 {                     port = usedPorts[i] - 1;                     break;                 }             }             if (port > MaxTcpPort)             {                 try                 {                     throw new Exception(\"No TCP port is available.\");                 }                 finally                 {                     appStartedGate.Set();                 }             } \/\/ \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u0435\u043c WebApplication             WebApplicationBuilder builder = WebApplication.CreateBuilder(new string[] { });              builder.Logging.ClearProviders();              builder.Services.AddRazorPages();            \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0431\u043e\u0440\u043a\u0438 \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438             IMvcBuilder mvcBuilder = builder.Services.AddControllersWithViews();             foreach (Assembly assembly in assemblies)             {                 mvcBuilder.AddApplicationPart(assembly);             }              foreach (object obj in services)             {               \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438 \u0442\u0438\u043f\u044b               ...             }              app = builder.Build();              \/\/ \u041f\u0440\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u0437\u0430\u043d\u043e\u0441\u0438\u043c \u0435\u0433\u043e \u0432 razorPageException \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c           \/\/ StatusCodes.Status500InternalServerError           app.UseExceptionHandler(eapp =>             {                 eapp.Run(async context =>                 {                     var exceptionHandlerPathFeature =                         context.Features.Get&lt;IExceptionHandlerPathFeature>();                      razorPageException = exceptionHandlerPathFeature?.Error;                     context.Response.StatusCode = StatusCodes.Status500InternalServerError;                 });             });              \/\/ \u041e\u0442\u0441\u0435\u043a\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0435 \u043e\u0442 \u043d\u0430\u0441           app.Use(async (context, next) =>             {                 if (!context.Request.Headers.ContainsKey(SecretWordHeader) || !context.Request.Headers[SecretWordHeader].Contains(secretWord))                 {                     context.Response.StatusCode = StatusCodes.Status403Forbidden;                     await context.Response.WriteAsync(String.Empty);                 }                 else                 {                     await next.Invoke(context);                 }             });              app.MapRazorPages();            \/\/ \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0432\u043e\u0440\u043e\u0442\u0430 appStartedGate, \u043a\u043e\u0433\u0434\u0430 \u0433\u043e\u0442\u043e\u0432\u044b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b             app.Lifetime.ApplicationStarted.Register(() =>             {                 appStartedGate.Set();             });                      \/\/ \u041f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c \u043f\u043e\u0440\u0442\u0443,             \/\/ \u043d\u043e \u0435\u0441\u043b\u0438 \u0412\u0414\u0420\u0423\u0413 \u043e\u043d \u0443\u0436\u0435 \u0437\u0430\u043d\u044f\u0442, \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u043c \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c             app.Urls.Clear();             app.Urls.Add($\"http:\/\/localhost:{port}\");             try             {                 app.Run();                 break;             }             catch (IOException ex) { }         }     });  ... }<\/code><\/pre>\n<p>\u0418 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b<\/p>\n<pre><code class=\"cs\">{   ...     \/\/ \u0416\u0434\u0451\u043c \u0441\u0438\u0433\u043d\u0430\u043b \u043d\u0430 \u0441\u0442\u0430\u0440\u0442       appStartedGate.Wait();    \/\/ \u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u0441\u043c\u043e\u0433\u043b\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c\u0441\u044f, \u0432\u0430\u043b\u0438\u043c\u0441\u044f     if (loadTask.IsFaulted)     {       throw loadTask.Exception;     }   \/\/ \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0430     client = new HttpClient();     client.BaseAddress = new Uri(app.Urls.First());     client.DefaultRequestHeaders.Add(SecretWordHeader, secretWord);   \/\/ \u0428\u043b\u0451\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u044b     foreach (string request in requests)     {       \/\/ \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0440\u043e\u0448\u043b\u043e\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435       razorPageException = null;        HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, request);        HttpResponseMessage response = await client.SendAsync(requestMessage);        if(razorPageException is { })       {         \/\/ \u0415\u0441\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435         yield return new KeyValuePair&lt;string, object>(request, razorPageException);       }       else        {         \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442         yield return new KeyValuePair&lt;string, object>(request, await response.Content.ReadAsStringAsync());       }      }   \/\/ \u0417\u0430\u043f\u0440\u043e\u0441\u044b \u043a\u043e\u043d\u0447\u0438\u043b\u0438\u0441\u044c, \u0437\u0430\u043d\u0430\u0432\u0435\u0441     await app.StopAsync();  } <\/code><\/pre>\n<h2>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438<\/h2>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b86\/b12\/933\/b86b129331c0cf3132b2cfec7a849ab4.png\" width=\"537\" height=\"112\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b86\/b12\/933\/b86b129331c0cf3132b2cfec7a849ab4.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0423\u0434\u0430\u043b\u0438\u043c \u0432\u0441\u0451 \u043d\u0435\u043d\u0443\u0436\u043d\u043e\u0435, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0443\u0436\u043d\u043e\u0435:<\/p>\n<figure class=\"float\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/cc4\/281\/7a8\/cc42817a810b06652dce72c78122d112.png\" width=\"318\" height=\"511\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/cc4\/281\/7a8\/cc42817a810b06652dce72c78122d112.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041c\u043e\u0434\u0435\u043b\u0438 \u0443 \u043d\u0430\u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435, \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u043f\u043e \u0440\u0430\u0437\u043d\u043e\u043c\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0445 \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c \u043e\u0442 BasePageModel:<\/p>\n<pre><code class=\"cs\">using Microsoft.AspNetCore.Mvc.RazorPages;  namespace Net.Leksi.RestContract;  public class BasePageModel: PageModel {     internal string NamespaceValue { get; set; }     internal string ClassName { get; set; }     internal List&lt;string> Usings { get; set; }     internal List&lt;MethodModel> Methods { get; set; } } <\/code><\/pre>\n<p>\u0421\u0430\u043c\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0438\u0437\u0432\u043d\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u0438\u043b\u0434\u0435\u0440\u0430, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u0437  \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439.<\/p>\n<pre><code class=\"cs\">using Microsoft.AspNetCore.Mvc;  namespace Net.Leksi.RestContract.Pages;  public class ConnectorBaseModel : BasePageModel {     public void OnGet([FromServices] IConnectorBaseBuilder builder)     {         builder.BuildConnectorBase(this);     } } <\/code><\/pre>\n<pre><code class=\"cs\">using Microsoft.AspNetCore.Mvc;  namespace Net.Leksi.RestContract.Pages;  public class ControllerInterfaceModel : BasePageModel {     public void OnGet([FromServices] IControllerInterfaceBuilder builder)     {         builder.BuildControllerInterface(this);     } } <\/code><\/pre>\n<pre><code class=\"cs\">using Microsoft.AspNetCore.Mvc;  namespace Net.Leksi.RestContract.Pages {     public class ControllerProxyModel : BasePageModel     {         public void OnGet([FromServices] IControllerProxyBuilder builder)         {             builder.BuildControllerProxy(this);         }     } } <\/code><\/pre>\n<p>\u0422\u043e\u0447\u043a\u043e\u0439 \u0432\u0445\u043e\u0434\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430 HelpersBuilder, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0432\u0441\u0435 \u0442\u0440\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0436\u0434\u0443\u0442 \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0441\u0430\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u043a\u0432\u0438\u0437\u0438\u0442\u043e\u043c:<\/p>\n<pre><code class=\"cs\">public class HelpersBuilder : IControllerInterfaceBuilder, IControllerProxyBuilder, IConnectorBaseBuilder { ...     public async Task BuildHelpers&lt;TConnector>(string controllerInterfaceFullName, string controllerProxyFullName,         string connectorBaseFullName)     {         CollectRequisites&lt;TConnector>(controllerInterfaceFullName, controllerProxyFullName, connectorBaseFullName);         await foreach (KeyValuePair&lt;string, object> result in Generator.Generate(             new object[] {                 new KeyValuePair&lt;Type, object>(typeof(IConnectorBaseBuilder), this),                 new KeyValuePair&lt;Type, object>(typeof(IControllerInterfaceBuilder), this),                 new KeyValuePair&lt;Type, object>(typeof(IControllerProxyBuilder), this)             },             new string[] {                 \"ConnectorBase\",                 \"ControllerInterface\",                 \"ControllerProxy\",             }         ))         {             if (result.Value is Exception)             {                 Console.WriteLine($\"\/\/ {result.Key}\");             }             Console.WriteLine(result.Value);         }      } ...     public void BuildConnectorBase(ConnectorBaseModel model)     {     ... }     ...     public void BuildControllerProxy(ControllerProxyModel model)     { ...     }     ...     public void BuildControllerInterface(ControllerInterfaceModel model)     {     ...     }     ...     private void CollectRequisites&lt;TConnector>(string controllerFullName,      string proxyFullName, string connectorBaseFullName)     { ...     }    ... }<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u0432 \u0432\u0438\u0434\u0435 \u044e\u043d\u0438\u0442-\u0442\u0435\u0441\u0442\u0430 \u043e\u043f\u044f\u0442\u044c \u0436\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b<\/p>\n<pre><code class=\"cs\">public class RestContract {     private static IHost _host;      static RestContract()     {         _host = Host.CreateDefaultBuilder()             .ConfigureServices(serviceCollection =>             {                 ...                 serviceCollection.AddTransient&lt;HelpersBuilder>();             }).Build();         Trace.Listeners.Add(new ConsoleTraceListener());         Trace.AutoFlush = true;     }      [Test]     public async Task BuildRestHelpers()     {         HelpersBuilder codeGenerator = _host.Services.GetRequiredService&lt;HelpersBuilder>();          await codeGenerator.BuildHelpers&lt;IConnector>(           \"DtoKit.Demo.IDemoController\", \"DtoKit.Demo.DemoControllerProxy\",            \"DtoKit.Demo.DemoConnectorBase\");     } }<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/848\/1d4\/538\/8481d45384b1d36cfaeb15980deca004.png\" width=\"1031\" height=\"997\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/848\/1d4\/538\/8481d45384b1d36cfaeb15980deca004.png\"\/><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b99\/a97\/5c0\/b99a975c0987a4ab74156214effc8250.png\" width=\"1025\" height=\"989\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b99\/a97\/5c0\/b99a975c0987a4ab74156214effc8250.png\"\/><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0bf\/e55\/0a0\/0bfe550a08869a4fdad4d8985a8f9f61.png\" width=\"1113\" height=\"998\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0bf\/e55\/0a0\/0bfe550a08869a4fdad4d8985a8f9f61.png\"\/><figcaption><\/figcaption><\/figure>\n<figure class=\"float\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7a3\/b1a\/6a8\/7a3b1a6a841afbc8ecfa91c574147f00.png\" width=\"254\" height=\"209\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7a3\/b1a\/6a8\/7a3b1a6a841afbc8ecfa91c574147f00.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0420\u0430\u0437\u043b\u043e\u0436\u0438\u043c \u0442\u0438\u043f\u044b \u043f\u043e \u0444\u0430\u0439\u043b\u0430\u043c \u0438 \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u043c \u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0435<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d9c\/6fd\/407\/d9c6fd40778a7d0850ae51098160ac59.png\" width=\"230\" height=\"89\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d9c\/6fd\/407\/d9c6fd40778a7d0850ae51098160ac59.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412\u0441\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438:<\/p>\n<p><a href=\"https:\/\/github.com\/Leksiqq\/DocsRazorator\/tree\/v1.0.0\/Library\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/Leksiqq\/DocsRazorator\/tree\/v1.0.0\/Library<\/a><\/p>\n<p><a href=\"https:\/\/github.com\/Leksiqq\/RestContract\/tree\/v1.0.0\/HelpersBuilder\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/Leksiqq\/RestContract\/tree\/v1.0.0\/HelpersBuilder<\/a><\/p>\n<p><a href=\"https:\/\/github.com\/Leksiqq\/DtoRestDemo\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/Leksiqq\/DtoRestDemo<\/a><\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/664712\/\"> https:\/\/habr.com\/ru\/post\/664712\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0418\u043d\u043e\u0433\u0434\u0430 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b, \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u043f\u043e\u043b\u0435\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044d\u0442\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432-\u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043a\u0430\u043a\u043e\u0433\u043e-\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430, \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043e\u0442\u0447\u0435\u0442\u044b \u0432 XML, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u043e\u0442\u044f \u0438 \u043c\u043e\u0436\u043d\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e, \u043d\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u0440\u0443\u0434\u043d\u044b\u0439 \u0434\u043b\u044f \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043a\u043e\u0434. \u041d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u0442\u0435, \u043a\u0442\u043e \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0441\u044f \u0441 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c\u044e, \u0441\u043c\u043e\u0433\u0443\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u043f\u0438\u0441\u043e\u043a. \u041f\u0440\u0438\u0432\u0435\u0434\u0443 \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0437\u0430\u0434\u0430\u0447\u0443 \u0441 \u0445\u0435\u043b\u043f\u0435\u0440\u0430\u043c\u0438.<\/p>\n<h2>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/h2>\n<p>\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043a\u043b\u0438\u0435\u043d\u0442-\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0443 \u043d\u0430\u0441 \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f MVC ASP.NET, \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 &#8212; WPF, \u043d\u043e \u043d\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432  \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u043a\u0430\u043a \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435, \u0442\u0430\u043a \u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439, \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043a\u043b\u0438\u0435\u043d\u0442-\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0443\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0432\u044b\u0437\u043e\u0432\u0443 \u0442\u0430\u043a\u043e\u0433\u043e \u0436\u0435 (\u043f\u043e\u0447\u0442\u0438) \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.<\/p>\n<p>\u0421\u0430\u043c\u0430 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u0432\u0430\u0436\u043d\u0430, \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u0447\u0442\u043e \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0438\u0441\u044c \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u0445\u0435\u043b\u043f\u0435\u0440\u043e\u0432 \u043f\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430. \u0414\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u043e\u0436\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0435\u0434\u043e\u0440\u043e\u0433\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c Contract First \u043f\u0430\u0440\u0430\u0434\u0438\u0433\u043c\u044b.<\/p>\n<p>\u041f\u0443\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<pre><code class=\"cs\">using Net.Leksi.RestContract; using System.Collections.ObjectModel;  namespace DtoKit.Demo;  public interface IConnector {     [RoutePath(\"\/shipCalls\/{filter}\/{amount:double}\/{date}\")]     [HttpMethodGet]     [Authorization(Roles = \"1, 2, 3\")]     Task GetShipCalls(DateTime date, double amount, ShipCallsFilter filter,                        ObservableCollection&lt;IShipCallForList> list);      [RoutePath(\"\/form\")]     [HttpMethodPost]     Task Commit([Body] IShipCall shipCall);  } <\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0441\u0432\u043e\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0432 \u043a\u043b\u0438\u0435\u043d\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u0442 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b ASP.NET, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0432 \u0440\u043e\u0443\u0442\u0438\u043d\u0433 \u0438\u043b\u0438 \u044f\u0432\u043b\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0442\u0435\u043b\u043e\u043c POST-\u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b ASP.NET \u0438 \u043f\u0435\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438\u0437 \u0440\u043e\u0443\u0442\u0438\u043d\u0433\u0430 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0435. \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b &#171;\u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435&#187;. \u0412\u0441\u0451 \u0434\u043e\u043b\u0436\u043d\u043e \u043e\u0434\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f\/\u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<p>\u041c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 \u0441\u0431\u043e\u0440\u043a\u0438, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0439 <code>IConnector<\/code>, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u044b\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0438\u0441\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0447\u0430\u0441\u0442\u0438<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">\/\/------------------------------ \/\/ Connector base \/\/ DtoKit.Demo.DemoConnectorBase \/\/ (Generated automatically) \/\/------------------------------ using Microsoft.Extensions.DependencyInjection; using Net.Leksi.Dto; using Net.Leksi.RestContract; using System.Net.Http.Json; using System.Text.Json; using System.Web;  namespace DtoKit.Demo;  public class DemoConnectorBase {     private readonly HttpConnector _httpConnector;     public DemoConnectorBase(HttpConnector httpConnector)     {         _httpConnector = httpConnector;     }      public Task&lt;HttpResponseMessage> GetShipCalls(DateTime date, Double amount,                                                    ShipCallsFilter filter)     {         DtoJsonConverterFactory getConverter = _httpConnector.Services           .GetRequiredService&lt;DtoJsonConverterFactory>();         getConverter.KeysProcessing = KeysProcessing.OnlyKeys;         JsonSerializerOptions getOptions = new();         getOptions.Converters.Add(getConverter);         string _date = HttpUtility.UrlEncode(           JsonSerializer.Serialize(date, getOptions));         string _amount = HttpUtility.UrlEncode(           JsonSerializer.Serialize(amount, getOptions));         string _filter = HttpUtility.UrlEncode(           JsonSerializer.Serialize(filter, getOptions));         string route = $\"\/shipCalls\/{_filter}\/{_amount}\/{_date}\";         HttpRequestMessage httpRequest = new(HttpMethod.Get, route);          return _httpConnector.SendAsync(httpRequest);      }      public Task&lt;HttpResponseMessage> Commit(IShipCall shipCall)     {         string route = $\"\/form\";         HttpRequestMessage httpRequest = new(HttpMethod.Post, route);          DtoJsonConverterFactory postConverter = _httpConnector.Services           .GetRequiredService&lt;DtoJsonConverterFactory>();         JsonSerializerOptions postOptions = new();         postOptions.Converters.Add(postConverter);         httpRequest.Content = JsonContent.Create(shipCall, typeof(IShipCall),                                                  default, postOptions);         return _httpConnector.SendAsync(httpRequest);      }  } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0430\u043c\u043e\u043c <\/p>\n<details class=\"spoiler\">\n<summary>\u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0435:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">using Net.Leksi.RestContract; using System.Collections.ObjectModel;  namespace DtoKit.Demo;  public class Connector : DemoConnectorBase,  IConnector {     public Connector(HttpConnector httpConnector) : base(httpConnector) { }     public async Task GetShipCalls(DateTime date, double amount,      ShipCallsFilter filter, ObservableCollection&lt;IShipCallForList> list)     {     \/\/ \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0434\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430         HttpResponseMessage response = await base.GetShipCalls(date, amount,          filter);         Console.WriteLine(response.StatusCode);     \/\/ \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0442\u0432\u0435\u0442\u0430, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0432      \/\/ ObservableCollection&lt;IShipCallForList> list \u0434\u043b\u044f \u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 UI     \/\/ (\u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d)     }      public async Task Commit(IShipCall shipCall)     {         HttpResponseMessage response = await base.Commit(shipCall);         Console.WriteLine(response.StatusCode);     } } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0432 <\/p>\n<details class=\"spoiler\">\n<summary>\u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u044c:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">\/\/------------------------------ \/\/ MVC Controller proxy  \/\/ DtoKit.Demo.DemoControllerProxy \/\/ (Generated automatically) \/\/------------------------------ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Net.Leksi.Dto; using System.Text.Json;  namespace DtoKit.Demo;  public class DemoControllerProxy : Controller {      [Route(\"\/shipCalls\/{filter}\/{amount:double}\/{date}\")]     [HttpGet]     [Authorize(Roles = \"1, 2, 3\")]     public async Task GetShipCalls(String date, Double amount, String filter)     {         DtoJsonConverterFactory converter = HttpContext.RequestServices         .GetRequiredService&lt;DtoJsonConverterFactory>();         JsonSerializerOptions options = new();         options.Converters.Add(converter);         DateTime _date = JsonSerializer.Deserialize&lt;DateTime>(date, options);         ShipCallsFilter _filter = JsonSerializer.Deserialize&lt;ShipCallsFilter>(         filter, options);         Controller controller = (Controller)HttpContext.RequestServices         .GetRequiredService&lt;IDemoController>();         controller.ControllerContext = ControllerContext;         await ((IDemoController)controller).GetShipCalls(_date, amount, _filter);     }      [Route(\"\/form\")]     [HttpPost]     public async Task Commit()     {         DtoJsonConverterFactory converter = HttpContext.RequestServices         .GetRequiredService&lt;DtoJsonConverterFactory>();         JsonSerializerOptions options = new();         options.Converters.Add(converter);         IShipCall shipCall = await HttpContext.Request         .ReadFromJsonAsync&lt;IShipCall>(options);         Controller controller = (Controller)HttpContext.RequestServices         .GetRequiredService&lt;IDemoController>();         controller.ControllerContext = ControllerContext;         await ((IDemoController)controller).Commit(shipCall);     }  } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u043b\u043e\u0433\u0438\u043a\u0443:<\/p>\n<details class=\"spoiler\">\n<summary>\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u043b\u043e\u0433\u0438\u043a\u0443:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">\/\/------------------------------ \/\/ MVC Controller interface  \/\/ DtoKit.Demo.IDemoController \/\/ (Generated automatically) \/\/------------------------------  namespace DtoKit.Demo;  public interface IDemoController {     Task GetShipCalls(DateTime date, Double amount, ShipCallsFilter filter);     Task Commit(IShipCall shipCall); } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h2>\u041d\u0430\u043c \u0431\u044b \u043c\u043e\u0433\u043b\u0430 \u043f\u043e\u0434\u043e\u0439\u0442\u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 RazorPages<\/h2>\n<p>\u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0451 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438, \u043c\u044b \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0446\u0435\u043b\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b.<\/p>\n<details class=\"spoiler\">\n<summary>\u0428\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0440\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">@page @using Net.Leksi.RestContract @model Net.Leksi.RestContract.Pages.ConnectorBaseModel \/\/------------------------------ \/\/ Connector base \/\/ @string.Join(\".\", new string[] { Model.NamespaceValue, Model.ClassName}) \/\/ (Generated automatically) \/\/------------------------------ @foreach(string usng in Model.Usings) {     &lt;text>using @usng; &lt;\/text> }  namespace @Model.NamespaceValue;  public class @Model.ClassName {     private readonly HttpConnector _httpConnector;     public @Model.ClassName@{&lt;text\/>}(HttpConnector httpConnector)     {         _httpConnector = httpConnector;     }     @foreach (MethodModel mm in Model.Methods)     { &lt;text>     public Task&lt;HttpResponseMessage> @mm.Name@{&lt;text\/>}(@for(int i = 0; i &lt; mm.Parameters.Count; ++i)         {                 if(i > 0){&lt;text>, &lt;\/text>}                 &lt;text>@mm.Parameters[i].Type @mm.Parameters[i].Name&lt;\/text>         })     {@if(mm.HasSerialized)         { &lt;text>         DtoJsonConverterFactory @mm.GetConverterVariable = _httpConnector.Services.GetRequiredService&lt;DtoJsonConverterFactory>();         @mm.GetConverterVariable@{&lt;text\/>}.KeysProcessing = KeysProcessing.OnlyKeys;         JsonSerializerOptions @mm.GetOptionsVariable = new();         @mm.GetOptionsVariable@{&lt;text\/>}.Converters.Add(@mm.GetConverterVariable);&lt;\/text>             foreach(Tuple&lt;string, string, string> tuple in mm.Deserializing)             { &lt;text>         @tuple.Item1 @tuple.Item2 = HttpUtility.UrlEncode(JsonSerializer.Serialize(@tuple.Item3, @mm.GetOptionsVariable));&lt;\/text>             }         } @* @if(mm.HasSerialized) *@                  string @mm.RouteVariable = @Html.Raw($\"$\\\"{@mm.RouteValue}\\\"\");         HttpRequestMessage @mm.HttpRequestVariable = new(HttpMethod.@mm.HttpMethod, @mm.RouteVariable);         @if(mm.PostConverterVariable is { })         { &lt;text>         DtoJsonConverterFactory @mm.PostConverterVariable = _httpConnector.Services.GetRequiredService&lt;DtoJsonConverterFactory>();         JsonSerializerOptions @mm.PostOptionsVariable = new();         @mm.PostOptionsVariable@{&lt;text\/>}.Converters.Add(@mm.PostConverterVariable);<\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-332883","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/332883","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=332883"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/332883\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=332883"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=332883"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=332883"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}