/// <summary> /// This endpoint logs an individual out by disabling all of their active access tokens. /// </summary> /// <return>Returns the void response from the API call</return> public async Task UpdateLogoutIndividualAsync() { //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/identity/logout"); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(true, true); //prepare the API call request to fetch the response var request = ClientInstance.Put(queryUrl, headers, null); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); }
public void Run() { Handlers.ForEach(x => { Context = x(Context); }); }
/// <summary> /// Deletes the round-up goal associated with an account if one exists /// </summary> /// <param name="accountUid">Required parameter: Example: </param> /// <return>Returns the void response from the API call</return> public async Task DeleteStopRoundUpGoalAsync(Guid accountUid) { //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/feed/account/{accountUid}/round-up"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "accountUid", accountUid } }); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(true, true); //prepare the API call request to fetch the response var request = ClientInstance.Delete(queryUrl, headers, null); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); }
/// <summary> /// TODO: type endpoint description here /// </summary> /// <param name="body">Optional parameter: Example: </param> /// <return>Returns the void response from the API call</return> public async Task CreateDispatchWebhookAsync(DefaultWebhookPayloadModel body = null) { //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/yourdomain.com/your/registered/web-hook/address"); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetContentRequestHeaders(); //append body params var serializedBody = APIHelper.JsonSerialize(body); //prepare the API call request to fetch the response var request = ClientInstance.PostBody(queryUrl, headers, serializedBody); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors defined at the API level ValidateResponse(response, context); }
/// <summary> /// преобразуем строку вида Game/f1/ttt в объект HTTPContext - просто распихиваем всё по полочкам, чтобы не работать со строкой или массивом /// </summary> /// <param name="URL"></param> /// <returns></returns> private static HTTPContext GetContext(String URL) { // создаём наш контекст HTTPContext c = new HTTPContext(); // разбиваем строку на части String[] s = URL.Split('/'); // если там одна часть, то это имя контроллера if (s.Length > 0) { // заполняем его c.Controller = s[0]; } // если там две части if (s.Length > 1) { // то заполняем вторую - Action c.Action = s[1]; } // если есть ещё и третья, то пользователь передал параметр, кладём его пока просто в одну переменную if (s.Length > 2) { c.Params = s[2]; } // возвращаем готовый заполненный объект HTTPContext return(c); }
void ListenerCallback(IAsyncResult result) { HTTPContext context = new HTTPContext(listener.EndGetContext(result)); HandleRequest(context); listener.BeginGetContext(new AsyncCallback(ListenerCallback), null); }
/// <summary> /// Submit a receipt for a feed item /// </summary> /// <param name="accountUid">Required parameter: Account uid</param> /// <param name="categoryUid">Required parameter: Category uid</param> /// <param name="feedItemUid">Required parameter: Feed item uid</param> /// <param name="body">Required parameter: Receipt</param> /// <return>Returns the Models.ReceiptCreationResponse response from the API call</return> public async Task <ReceiptCreationResponse> CreateOrUpdateReceiptAsync( Guid accountUid, Guid categoryUid, Guid feedItemUid, Receipt body) { //validating required parameters if (null == body) { throw new ArgumentNullException(nameof(body), "The parameter \"body\" is a required parameter and cannot be null."); } //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/feed/account/{accountUid}/category/{categoryUid}/{feedItemUid}/receipt"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "accountUid", accountUid }, { "categoryUid", categoryUid }, { "feedItemUid", feedItemUid } }); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetContentRequestHeaders(true, true); //append body params var serializedBody = APIHelper.JsonSerialize(body); //prepare the API call request to fetch the response var request = ClientInstance.PutBody(queryUrl, headers, serializedBody); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); try { return(APIHelper.JsonDeserialize <ReceiptCreationResponse>(response.Body)); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
/// <summary> /// Categories are subdivisions within an account. /// The `defaultCategory` from [`/api/v2/accounts`](#operations-tag-Accounts) is where the main balance and transactions are held. /// Other categories are used for Savings Goals. /// </summary> /// <param name="accountUid">Required parameter: Account uid</param> /// <param name="categoryUid">Required parameter: Category uid</param> /// <param name="minTransactionTimestamp">Required parameter: Minimum transaction timestamp</param> /// <param name="maxTransactionTimestamp">Required parameter: Maximum transaction timestamp</param> /// <return>Returns the Models.FeedItems response from the API call</return> public async Task <FeedItems> GetQueryFeedItemsWithTransactionTimesBetweenAsync( Guid accountUid, Guid categoryUid, DateTime minTransactionTimestamp, DateTime maxTransactionTimestamp) { //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/feed/account/{accountUid}/category/{categoryUid}/transactions-between"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "accountUid", accountUid }, { "categoryUid", categoryUid } }); //process optional query parameters APIHelper.AppendUrlWithQueryParameters(queryBuilder, new Dictionary <string, object> { // ReSharper disable StringLiteralTypo { "minTransactionTimestamp", minTransactionTimestamp.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK") }, { "maxTransactionTimestamp", maxTransactionTimestamp.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK") } // ReSharper restore StringLiteralTypo }, ArrayDeserializationFormat, ParameterSeparator); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(); //prepare the API call request to fetch the response var request = ClientInstance.Get(queryUrl, headers); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); try { return(APIHelper.JsonDeserialize <FeedItems>(response.Body)); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
/// <summary> /// Get the spending insights grouped by counter party /// </summary> /// <param name="accountUid">Required parameter: Account uid</param> /// <param name="year">Required parameter: Year</param> /// <param name="month">Required parameter: Month</param> /// <return>Returns the Models.SpendingCounterPartySummary response from the API call</return> public async Task <SpendingCounterPartySummary> GetQuerySpendingInsightsByCounterpartyAsync(Guid accountUid, string year, MonthEnum month) { //validating required parameters if (null == year) { throw new ArgumentNullException(nameof(year), "The parameter \"year\" is a required parameter and cannot be null."); } //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/accounts/{accountUid}/spending-insights/counter-party"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "accountUid", accountUid } }); //process optional query parameters APIHelper.AppendUrlWithQueryParameters(queryBuilder, new Dictionary <string, object> { { "year", year }, { "month", MonthEnumHelper.ToValue(month) } }, ArrayDeserializationFormat, ParameterSeparator); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(); //prepare the API call request to fetch the response var request = ClientInstance.Get(queryUrl, headers); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); try { return(APIHelper.JsonDeserialize <SpendingCounterPartySummary>(response.Body)); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
/// <summary> /// To choose a file format, set the Accept header to either 'application/pdf' or 'text/csv' /// </summary> /// <param name="accountUid">Required parameter: Example: </param> /// <param name="yearMonth">Required parameter: Example: </param> /// <return>Returns the Stream response from the API call</return> public async Task <Stream> GetDownloadCsvStatementAsync(Guid accountUid, string yearMonth) { //validating required parameters if (null == yearMonth) { throw new ArgumentNullException(nameof(yearMonth), "The parameter \"yearMonth\" is a required parameter and cannot be null."); } //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/accounts/{accountUid}/statement/download"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "accountUid", accountUid } }); //process optional query parameters APIHelper.AppendUrlWithQueryParameters(queryBuilder, new Dictionary <string, object> { { "yearMonth", yearMonth } }, ArrayDeserializationFormat, ParameterSeparator); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(true, true); //prepare the API call request to fetch the response var request = ClientInstance.Get(queryUrl, headers); //invoke request and get response var response = await ClientInstance.ExecuteAsBinaryAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); try { return(response.RawBody); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
/// <summary> /// N.B. if you're looking for only the next payment date, this is also returned when getting a standing order in the `StandingOrder` response from the field `nextDate`. /// Categories are subdivisions within an account. /// The `defaultCategory` from [`/api/v2/accounts`](#operations-tag-Accounts) is where the main balance and transactions are held. /// Other categories are used for Savings Goals. /// </summary> /// <param name="accountUid">Required parameter: Account uid</param> /// <param name="categoryUid">Required parameter: Category uid</param> /// <param name="paymentOrderUid">Required parameter: Payment Order uid</param> /// <param name="count">Optional parameter: Number of next payment dates to retrieve, between 1 and 100. If count is greater than the number of future payments all future payments will be returned. Defaults to 10.</param> /// <return>Returns the Models.NextPaymentDatesResponse response from the API call</return> public async Task <NextPaymentDatesResponse> ListNextPaymentDatesAsync( Guid accountUid, Guid categoryUid, Guid paymentOrderUid, int?count = null) { //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/payments/local/account/{accountUid}/category/{categoryUid}/standing-orders/{paymentOrderUid}/upcoming-payments"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "accountUid", accountUid }, { "categoryUid", categoryUid }, { "paymentOrderUid", paymentOrderUid } }); //process optional query parameters APIHelper.AppendUrlWithQueryParameters(queryBuilder, new Dictionary <string, object> { { "count", count } }, ArrayDeserializationFormat, ParameterSeparator); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(); //prepare the API call request to fetch the response var request = ClientInstance.Get(queryUrl, headers); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); try { return(APIHelper.JsonDeserialize <NextPaymentDatesResponse>(response.Body)); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
/// <summary> /// Update a profile image if one already exists /// </summary> /// <param name="accountHolderUid">Required parameter: Unique identifier of an account holder</param> /// <param name="contentType">Required parameter: Example: </param> /// <param name="body">Required parameter: Attachment input stream</param> /// <return>Returns the void response from the API call</return> public async Task UpdateProfileImageAsync(Guid accountHolderUid, string contentType, object body) { //validating required parameters if (null == contentType) { throw new ArgumentNullException(nameof(contentType), "The parameter \"contentType\" is a required parameter and cannot be null."); } if (null == body) { throw new ArgumentNullException(nameof(body), "The parameter \"body\" is a required parameter and cannot be null."); } //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/account-holder/{accountHolderUid}/profile-image"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "accountHolderUid", accountHolderUid } }); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = new Dictionary <string, string> { { "user-agent", "StarlingBankClient" }, { "Content-Type", contentType }, { "Authorization", $"Bearer {Configuration.OAuthAccessToken}" } }; //append body params var serializedBody = APIHelper.JsonSerialize(body); //prepare the API call request to fetch the response var request = ClientInstance.PutBody(queryUrl, headers, serializedBody); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); }
/// <summary> /// Categories are subdivisions within an account. /// The `defaultCategory` from [`/api/v2/accounts`](#operations-tag-Accounts) is where the main balance and transactions are held. /// Other categories are used for Savings Goals. /// </summary> /// <param name="accountUid">Required parameter: Account uid</param> /// <param name="categoryUid">Required parameter: Category uid</param> /// <param name="feedItemUid">Required parameter: Feed item uid</param> /// <param name="feedItemAttachmentUid">Required parameter: Feed item attachment uid</param> /// <return>Returns the Stream response from the API call</return> public async Task <Stream> GetDownloadFeedItemAttachmentAsync( Guid accountUid, Guid categoryUid, Guid feedItemUid, Guid feedItemAttachmentUid) { //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/feed/account/{accountUid}/category/{categoryUid}/{feedItemUid}/attachments/{feedItemAttachmentUid}"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "accountUid", accountUid }, { "categoryUid", categoryUid }, { "feedItemUid", feedItemUid }, { "feedItemAttachmentUid", feedItemAttachmentUid } }); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(true, true); //prepare the API call request to fetch the response var request = ClientInstance.Get(queryUrl, headers); //invoke request and get response var response = await ClientInstance.ExecuteAsBinaryAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); try { return(response.RawBody); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
/// <summary> /// To choose a file format, set the Accept header to either 'application/pdf' or 'text/csv' /// </summary> /// <param name="accountUid">Required parameter: Example: </param> /// <param name="start">Required parameter: Example: </param> /// <param name="end">Optional parameter: Example: </param> /// <return>Returns the Stream response from the API call</return> public async Task <Stream> GetDownloadCsvStatementForDateRangeAsync(Guid accountUid, DateTime start, DateTime?end = null) { //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/accounts/{accountUid}/statement/downloadForDateRange"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "accountUid", accountUid } }); //process optional query parameters APIHelper.AppendUrlWithQueryParameters(queryBuilder, new Dictionary <string, object> { { "start", start.ToString("yyyy'-'MM'-'dd") }, { "end", end?.ToString("yyyy'-'MM'-'dd") } }, ArrayDeserializationFormat, ParameterSeparator); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(true, true); //prepare the API call request to fetch the response var request = ClientInstance.Get(queryUrl, headers); //invoke request and get response var response = await ClientInstance.ExecuteAsBinaryAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); try { return(response.RawBody); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
/// <summary> /// Get whether there are available funds for a requested amount /// </summary> /// <param name="accountUid">Required parameter: Account uid</param> /// <param name="targetAmountInMinorUnits">Required parameter: Target amount in minor units</param> /// <return>Returns the Models.ConfirmationOfFundsResponse response from the API call</return> public async Task <ConfirmationOfFundsResponse> GetConfirmationOfFundsAsync(Guid accountUid, long targetAmountInMinorUnits) { //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/accounts/{accountUid}/confirmation-of-funds"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "accountUid", accountUid } }); //process optional query parameters APIHelper.AppendUrlWithQueryParameters(queryBuilder, new Dictionary <string, object> { { "targetAmountInMinorUnits", targetAmountInMinorUnits } }, ArrayDeserializationFormat, ParameterSeparator); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(); //prepare the API call request to fetch the response var request = ClientInstance.Get(queryUrl, headers); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); try { return(APIHelper.JsonDeserialize <ConfirmationOfFundsResponse>(response.Body)); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
/// <summary> /// Get a transaction history for a direct debit /// </summary> /// <param name="mandateUid">Required parameter: Unique identifier of the mandate.</param> /// <param name="since">Required parameter: Start date for a transaction history</param> /// <return>Returns the Models.DirectDebitPaymentsResponse response from the API call</return> public async Task <DirectDebitPaymentsResponse> ListPaymentsForMandateAsync(Guid mandateUid, DateTime since) { //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/direct-debit/mandates/{mandateUid}/payments"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "mandateUid", mandateUid } }); //process optional query parameters APIHelper.AppendUrlWithQueryParameters(queryBuilder, new Dictionary <string, object> { { "since", since.ToString("yyyy'-'MM'-'dd") } }, ArrayDeserializationFormat, ParameterSeparator); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(); //prepare the API call request to fetch the response var request = ClientInstance.Get(queryUrl, headers); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); try { return(APIHelper.JsonDeserialize <DirectDebitPaymentsResponse>(response.Body)); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
void HandleRequest(HTTPContext context) { // Debug.LogError("HANDLE " + context.Request.HttpMethod); // Debug.LogError("HANDLE " + context.path); bool foundCommand = false; switch (context.Command) { case "/NewLogs": { foundCommand = true; if (logs.Count > 0) { string response = ""; // foreach(QueuedLog cLog in logs) for (int i = 0; i < logs.Count; i++) { QueuedLog cLog = logs[i]; response += "::::" + cLog.type; response += "||||" + cLog.message; response += ">>>>" + cLog.stackTrace + ">>>>"; } context.RespondWithString(response); logs.Clear(); } else { context.RespondWithString(""); } break; } } if (!foundCommand) { context.Response.StatusCode = (int)HttpStatusCode.NotFound; context.Response.StatusDescription = "Not Found"; } context.Response.OutputStream.Close(); }
/// <summary> /// Onboard an account /// </summary> /// <param name="body">Required parameter: Account onboarding request</param> /// <return>Returns the Models.OnboardingResponse response from the API call</return> public async Task <OnboardingResponse> UpdateOnboardAsync(OnboardingRequest body) { //validating required parameters if (null == body) { throw new ArgumentNullException(nameof(body), "The parameter \"body\" is a required parameter and cannot be null."); } //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/onboarding"); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetContentRequestHeaders(true, true); //append body params var serializedBody = APIHelper.JsonSerialize(body); //prepare the API call request to fetch the response var request = ClientInstance.PutBody(queryUrl, headers, serializedBody); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); try { return(APIHelper.JsonDeserialize <OnboardingResponse>(response.Body)); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
/// <summary> /// Get the recurring transfer of a savings goal /// </summary> /// <param name="accountUid">Required parameter: Account uid</param> /// <param name="savingsGoalUid">Required parameter: Savings goal uid</param> /// <return>Returns the Models.ScheduledSavingsPaymentV2 response from the API call</return> public async Task <ScheduledSavingsPaymentV2> GetRecurringTransferAsync(Guid accountUid, Guid savingsGoalUid) { //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/account/{accountUid}/savings-goals/{savingsGoalUid}/recurring-transfer"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "accountUid", accountUid }, { "savingsGoalUid", savingsGoalUid } }); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(); //prepare the API call request to fetch the response var request = ClientInstance.Get(queryUrl, headers); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); try { return(APIHelper.JsonDeserialize <ScheduledSavingsPaymentV2>(response.Body)); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
/// <summary> /// Activates transaction round-up and adds remainder to savings goal /// </summary> /// <param name="accountUid">Required parameter: Account uid</param> /// <param name="body">Required parameter: Round-up goal</param> /// <return>Returns the void response from the API call</return> public async Task UpdateActivateRoundUpGoalAsync(Guid accountUid, RoundUpGoalPayload body) { //validating required parameters if (null == body) { throw new ArgumentNullException(nameof(body), "The parameter \"body\" is a required parameter and cannot be null."); } //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/feed/account/{accountUid}/round-up"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "accountUid", accountUid } }); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetContentRequestHeaders(); //append body params var serializedBody = APIHelper.JsonSerialize(body); //prepare the API call request to fetch the response var request = ClientInstance.PutBody(queryUrl, headers, serializedBody); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); }
/// <summary> /// Serves the image for the payee /// </summary> /// <param name="payeeUid">Required parameter: Unique identifier of the payee</param> /// <return>Returns the dynamic response from the API call</return> public async Task <dynamic> GetServePayeeImageFileAsync(Guid payeeUid) { //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/payees/{payeeUid}/image"); //process optional template parameters APIHelper.AppendUrlWithTemplateParameters(queryBuilder, new Dictionary <string, object> { { "payeeUid", payeeUid } }); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(); //prepare the API call request to fetch the response var request = ClientInstance.Get(queryUrl, headers); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); try { return(APIHelper.JsonDeserialize <dynamic>(response.Body)); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
/// <summary> /// Initialization constructor /// </summary> /// <param name="reason"> The reason for throwing exception </param> /// <param name="context"> The HTTP context that encapsulates request and response objects </param> public APIException(string reason, HTTPContext context) : base(reason) { HttpContext = context; //if a derived exception class is used, then perform deserialization of response body if ((GetType().Name.Equals("APIException", StringComparison.OrdinalIgnoreCase)) || context?.Response?.RawBody == null || (!context.Response.RawBody.CanRead)) { return; } using (var reader = new StreamReader(context.Response.RawBody)) { var responseBody = reader.ReadToEnd(); if (!string.IsNullOrWhiteSpace(responseBody)) { try { JsonConvert.PopulateObject(responseBody, this); } catch {} //ignoring response body from deserailization } } }
/// <summary> /// Fetch product subscription details for an account holder /// </summary> /// <return>Returns the Models.AccountHolderSubscription response from the API call</return> public async Task <AccountHolderSubscription> GetAccountHolderSubscriptionAsync() { //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/subscriptions"); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetRequestHeaders(); //prepare the API call request to fetch the response var request = ClientInstance.Get(queryUrl, headers); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors defined at the API level ValidateResponse(response, context); try { return(APIHelper.JsonDeserialize <AccountHolderSubscription>(response.Body)); } catch (Exception ex) { throw new APIException("Failed to parse the response: " + ex.Message, context); } }
/// <summary> /// Update an individual account holder's email address /// </summary> /// <param name="body">Required parameter: Example: </param> /// <return>Returns the void response from the API call</return> public async Task UpdateEmailAsync(UpdateEmailRequest body) { //validating required parameters if (null == body) { throw new ArgumentNullException(nameof(body), "The parameter \"body\" is a required parameter and cannot be null."); } //the base uri for api requests var baseUri = Configuration.GetBaseURI(); //prepare query string for API call var queryBuilder = new StringBuilder(baseUri); queryBuilder.Append("/api/v2/account-holder/individual/email"); //validate and preprocess url var queryUrl = APIHelper.CleanUrl(queryBuilder); //append request with appropriate headers and parameters var headers = APIHelper.GetContentRequestHeaders(); //append body params var serializedBody = APIHelper.JsonSerialize(body); //prepare the API call request to fetch the response var request = ClientInstance.PutBody(queryUrl, headers, serializedBody); //invoke request and get response var response = (HttpStringResponse)await ClientInstance.ExecuteAsStringAsync(request).ConfigureAwait(false); var context = new HTTPContext(request, response); //handle errors ValidateResponse(response, context); }
static void Main(string[] args) { App.Add(x => { return(new HTTPContext { RawURL = "" }); }); App.Add(x => { return(new HTTPContext { RawURL = x.RawURL.TrimStart('/') }); }); App.Add(x => { return(HTTPContext.CreateContext(x.RawURL)); }); HTMLRenderer r = new HTMLRenderer(); game = new GoGame(r); HttpListener listener = new HttpListener(); listener.Prefixes.Add("http://*:55555/"); listener.Start(); Console.WriteLine("listening"); game.Init(10, 5); while (true) { HttpListenerContext context = listener.GetContext(); HttpListenerRequest request = context.Request; String rawurl = request.RawUrl; App.Init(rawurl); String responsestring = ""; App.Run(); if (!rawurl.Contains('.')) { HTTPContext ct = App.GetContext(); if (ct != null) { Assembly asm = Assembly.GetCallingAssembly(); List <TypeInfo> Controllers = asm.DefinedTypes.Where(x => x.BaseType == typeof(Controller)).ToList(); AssemblyName an = asm.GetName(); String ClassName = Controllers .Where(x => x.Name == ct.Controller) .SingleOrDefault()? .FullName; ObjectHandle tclass = Activator.CreateInstance(an.Name, ClassName); Type type = asm.GetType(ClassName); object unwc = tclass.Unwrap(); ((Controller)unwc).Context = ct; if (ct.Action != null) { responsestring = type.GetMethod(ct.Action).Invoke(unwc, null).ToString(); } } } else { game.MoveUser(App.GetContext().RawURL); String GameField = game.RenderField(); String tfile = GetFileContent("Game"); tfile = tfile.Replace("<game />", GameField); responsestring = tfile; } HttpListenerResponse response = context.Response; byte[] buffer = Encoding.UTF8.GetBytes(responsestring); response.ContentLength64 = buffer.Length; Stream output = response.OutputStream; output.Write(buffer, 0, buffer.Length); output.Close(); Console.WriteLine($"String {responsestring} sent to client"); } }
void ListenerCallback(IAsyncResult result) { HTTPContext context = new HTTPContext(listener.EndGetContext(result)); HandleRequest(context); listener.BeginGetContext(new AsyncCallback(ListenerCallback), null); }
void HandleRequest(HTTPContext context) { // Debug.LogError("HANDLE " + context.Request.HttpMethod); // Debug.LogError("HANDLE " + context.path); bool foundCommand = false; switch(context.Command) { case "/NewLogs": { foundCommand = true; if(logs.Count > 0) { // Debug.LogError("CPIGNORE: Handling new logs request"); string response = ""; foreach(QueuedLog cLog in logs) { response += "::::" + cLog.type; response += "||||" + cLog.message; response += ">>>>" + cLog.stackTrace + ">>>>"; } context.RespondWithString(response); logs.Clear(); } break; } } if(!foundCommand) { context.Response.StatusCode = (int)HttpStatusCode.NotFound; context.Response.StatusDescription = "Not Found"; } context.Response.OutputStream.Close(); }
public WebSocketPacketStream(HTTPContext context) { try { String ConnectionHeader = context.GetRequestHeader("Connection"); //can be comma-separated list Boolean ConnectionUpgrade = ConnectionHeader != null && ConnectionHeader.Contains("Upgrade"); Boolean UpgradeWebsocket = "WebSocket".Equals(context.GetRequestHeader("Upgrade"), StringComparison.OrdinalIgnoreCase); String SecWebSocketKey = context.GetRequestHeader("Sec-WebSocket-Key"); String SecWebSocketKey1 = context.GetRequestHeader("Sec-WebSocket-Key1"); String SecWebSocketKey2 = context.GetRequestHeader("Sec-WebSocket-Key2"); String SecWebSocketProtocol = context.GetRequestHeader("Sec-WebSocket-Protocol"); String[] SecWebSocketProtocols = SecWebSocketProtocol == null ? null : SecWebSocketProtocol.Split(','); if (!ConnectionUpgrade || !UpgradeWebsocket) { throw new InvalidOperationException("The HTTP context does not contain a WebSocket request"); } if (SecWebSocketProtocols != null) { SecWebSocketProtocols = Array.ConvertAll(SecWebSocketProtocols, s => s.Trim().ToLowerInvariant()); } binaryProtocol = SecWebSocketProtocols != null && Array.IndexOf(SecWebSocketProtocols, "binary") != -1; if (SecWebSocketKey != null) { wsProtocol = 13; String hashedKey; using (SHA1 sha1 = SHA1Managed.Create()) { Byte[] hashable = Encoding.ASCII.GetBytes(SecWebSocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); Byte[] hash = sha1.ComputeHash(hashable); hashedKey = Convert.ToBase64String(hash, Base64FormattingOptions.None); } context.SendStatus(101); context.SetResponseHeader("Connection", "Upgrade"); context.SetResponseHeader("Upgrade", "websocket"); context.SetResponseHeader("Sec-WebSocket-Accept", hashedKey); if (SecWebSocketProtocols != null) { context.SetResponseHeader("Sec-WebSocket-Protocol", binaryProtocol ? "binary" : "base64"); } Stream rawstream = context.GetDirectStream(); baseStream = rawstream as PrebufferingStream ?? new PrebufferingStream(rawstream); } else if (SecWebSocketKey1 != null && SecWebSocketKey2 != null) { wsProtocol = 100; Byte[] key = new Byte[4 + 4 + 8]; CalculateHybi00MagicNumber(SecWebSocketKey1, key, 0); CalculateHybi00MagicNumber(SecWebSocketKey2, key, 4); context.SendStatus(101); context.SetResponseHeader("Connection", "Upgrade"); context.SetResponseHeader("Upgrade", "websocket"); if (SecWebSocketProtocols != null) { context.SetResponseHeader("Sec-WebSocket-Protocol", binaryProtocol ? "binary" : "base64"); } context.SendHeader("Sec-WebSocket-Origin", context.GetRequestHeader("Origin")); context.SendHeader("Sec-WebSocket-Location", (context.IsSecure ? "wss://" : "ws://") + context.GetRequestHeader("Host") + context.RequestPath); Stream rawstream = context.GetDirectStream(); baseStream = rawstream as PrebufferingStream ?? new PrebufferingStream(rawstream); baseStream.ReadAll(key, 8, 8); using (MD5 md5 = MD5.Create()) key = md5.ComputeHash(key); baseStream.Write(key, 0, key.Length); } else { throw new InvalidOperationException("Unsupported WebSocket request"); } } catch (Exception) { closed = true; if (baseStream != null) { baseStream.Close(); } throw; } }
/// <summary> /// Initialization constructor /// </summary> /// <param name="reason"> The reason for throwing exception </param> /// <param name="context"> The HTTP context that encapsulates request and response objects </param> public ErrorResponseException(string reason, HTTPContext context) : base(reason, context) { }
/// <summary> /// Validates the response against HTTP errors defined at the API level /// </summary> /// <param name="response">The response received</param> /// <param name="context">Context of the request and the received response</param> internal void ValidateResponse(HTTPResponse response, HTTPContext context) { if ((response.StatusCode >= 200) && (response.StatusCode <= 208)) { return; //[200,208] = HTTP OK } // ReSharper disable once RedundantAssignment var errorHeader = "HTTP Response Not OK"; if ((response.StatusCode >= 300) && (response.StatusCode < 400)) { errorHeader = "HTTP Redirection Error " + response.StatusCode + " - "; switch (response.StatusCode) { case 300: errorHeader = errorHeader + " Multiple Choices" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 301: errorHeader = errorHeader + " Moved Permanently" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 302: errorHeader = errorHeader + " Found" + ParseBody(response) + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 303: errorHeader = errorHeader + " See Other" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 304: errorHeader = errorHeader + " Not Modified" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 305: errorHeader = errorHeader + " Use Proxy" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 307: errorHeader = errorHeader + " Temporary Redirect" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 308: errorHeader = errorHeader + " Permanent Redirect" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); default: throw new ErrorResponseException(errorHeader, context); } } if ((response.StatusCode >= 400) && (response.StatusCode < 500)) { errorHeader = "HTTP Client Error " + response.StatusCode + " - "; switch (response.StatusCode) { case 400: errorHeader = errorHeader + "Bad Request" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 401: errorHeader = errorHeader + " Unauthorized" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 402: errorHeader = errorHeader + " Payment Required" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 403: errorHeader = errorHeader + " Forbidden" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 404: errorHeader = errorHeader + " Not Found" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 405: errorHeader = errorHeader + " Method Not Allowed" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 406: errorHeader = errorHeader + " Not Acceptable" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 407: errorHeader = errorHeader + " Proxy Authentication Required" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 408: errorHeader = errorHeader + " Request Timeout" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 409: errorHeader = errorHeader + " Conflict" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 410: errorHeader = errorHeader + " Gone" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 411: errorHeader = errorHeader + " Length Required" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 412: errorHeader = errorHeader + " Precondition Failed" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 413: errorHeader = errorHeader + " Payload Too Large" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 414: errorHeader = errorHeader + " Request - URI Too Long" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 415: errorHeader = errorHeader + " Unsupported Media Type" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 416: errorHeader = errorHeader + " Requested Range Not Satisfiable" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 417: errorHeader = errorHeader + " Expectation Failed" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 421: errorHeader = errorHeader + " Misdirected Request" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 422: errorHeader = errorHeader + " Unprocessable Entity" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 423: errorHeader = errorHeader + " Locked" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 424: errorHeader = errorHeader + " Failed Dependency" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 426: errorHeader = errorHeader + " Upgrade Required" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 428: errorHeader = errorHeader + " Precondition Required" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 429: errorHeader = errorHeader + " Too Many Requests" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 431: errorHeader = errorHeader + " Request Header Fields Too Large" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 444: errorHeader = errorHeader + " Connection Closed Without Response" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 451: errorHeader = errorHeader + " Unavailable For Legal Reasons" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); case 499: errorHeader = errorHeader + " Client Closed Request" + ParseBody(response); throw new ErrorResponseException(errorHeader, context); default: throw new ErrorResponseException(errorHeader, context); } } if ((response.StatusCode >= 500) && (response.StatusCode < 600)) { errorHeader = "HTTP Server Error " + response.StatusCode + " - "; switch (response.StatusCode) { case 500: errorHeader = errorHeader + " Internal Server Error" + ParseBody(response); throw new APIException(errorHeader, context); case 501: errorHeader = errorHeader + " Not Implemented" + ParseBody(response); throw new APIException(errorHeader, context); case 502: errorHeader = errorHeader + " Bad Gateway" + ParseBody(response); throw new APIException(errorHeader, context); case 503: errorHeader = errorHeader + " Service Unavailable" + ParseBody(response); throw new APIException(errorHeader, context); case 504: errorHeader = errorHeader + " Gateway Timeout" + ParseBody(response); throw new APIException(errorHeader, context); case 505: errorHeader = errorHeader + " HTTP Version Not Supported" + ParseBody(response); throw new APIException(errorHeader, context); case 506: errorHeader = errorHeader + " Variant Also Negotiates" + ParseBody(response); throw new APIException(errorHeader, context); case 507: errorHeader = errorHeader + " Insufficient Storage" + ParseBody(response); throw new APIException(errorHeader, context); case 508: errorHeader = errorHeader + " Loop Detected" + ParseBody(response); throw new APIException(errorHeader, context); case 510: errorHeader = errorHeader + " Not Extended" + ParseBody(response); throw new APIException(errorHeader, context); case 511: errorHeader = errorHeader + " Network Authentication Required" + ParseBody(response); throw new APIException(errorHeader, context); case 599: errorHeader = errorHeader + " Network Connect Timeout Error" + ParseBody(response); throw new APIException(errorHeader, context); default: throw new APIException(errorHeader, context); } } }
static void Main(string[] args) { // создаём HTML версию рендерера HTMLRenderer r = new HTMLRenderer(); // создаём объект игры и пробрасываем ему рендерер (внедрение через конструктор) game = new GoGame(r); // создаём слушатель HTTP запросов HttpListener listener = new HttpListener(); // настраиваем его чтобы он слушал на определённом порту listener.Prefixes.Add("http://*:55555/"); // стартуем его listener.Start(); // на всякий случай выводим в консоль чтобы мы знали что сервер слушает Console.WriteLine("listening"); // инициализируем игру (ToDo: потом нужно это убрать в контроллер) game.Init(10, 5); // создаём бесконечный цикл чтобы слушать запросы с клиента while (true) { // контекст - это кто, что спросил, с какого IP, какой браузер итд - сопутствующие запросу данные // чтобы мы не парились с тем как нам возвращать данные на клиент по этому запросу, уже всё сделано за нас: // поскольку контекст содержит запрос (Request) и ответ (Response) мы можем просто положить чтото в response и это пойдёт на клиент // получаем контекст из слушателя - это происходит при любом запросе с клиента // (всмысле в этой точке программа ждёт запроса, цикл просто так не гоняется без дела) // когда запрос получен, выполняется эта строка: получаем контекст из слушателя HttpListenerContext context = listener.GetContext(); // получаем запрос из контекста HttpListenerRequest request = context.Request; // чтобы не бегать по сложному объекту контекст, искать там запрос, доставать оттуда URL который пользователь ввёл в браузер, просто извлекаем его в переменную String rawurl = request.RawUrl; // сюда мы будем класть ответ сервера, неважно какая подсистема его сформирует String responsestring = ""; // убираем / вначале, чтобы переиспользовать эту строку в нескольких местах String TrimmedURL = rawurl.TrimStart('/'); // дальше идёт ветвление на MVC и просто файлы: если запрошен какойто файл, отдаём его. если нет точки в строке (признак расширения файла) то идём на MVC if (!rawurl.Contains('.')) { ///MVC веточка // что такое HTTPContext? поставьте туда мышку и нажмите F12 (или RMB -> Go To Definition) // тупо три переменные сформированные в одну кучку - класс // что делает функция GetContext - тоже можно посмотреть через F12: // она URL вида Controller/Action/Parameters разбирает на части по разделителю '/' и складывает в нужные части с проверками есть они или нет // не хотим париться как она это делает - выносим в отдельную функцию HTTPContext ct = GetContext(TrimmedURL); // если контекст удалось заполнить (хоть чтото)... if (ct != null) { // ...начинаем изучать Reflection // Reflection это способность среды исполнения CLR отвечать на вопросы программы о самой себе. // получаем ссылку на ту сборку которая запрашивает информацию о самой этой сборке Assembly asm = Assembly.GetCallingAssembly(); // ещё одна новая тема - лямбда-выражения. // их особенность в том, что в качестве параметра им передаются не переменные, а алгоритмы (упакованные в анонимные функции) // например: // список (List) типов TypeInfo // тут будет список всех типов из сборки, унаследованных от Controller List <TypeInfo> Controllers = // получается так: // мы просим сборку (asm) asm // дать нам все определённые типы (defined types) .DefinedTypes // дальше одно и то же объяснение разными словами - каждая строчка объясняет одноитоже // где (кагбэ функция без имени, которая принимает параметр и возвращает значение) // Where (то что пришло => а это я верну) // где (какойто входной аргумент типа TypeInfo (потому что List<TypeInfo>)) стрелка лямбды (=>) выражение которое возвращает да или нет (фильтр по которому ищем) // где (инфа_о_типе => унаследован ли инфа_о_типе от класса Controller?).преобразовать к списку // где (TypeInfo => является ли элемент BaseType переданного TypeInfo типом "Controller" приведённым к типу Type?).к списку .Where(x => x.BaseType == typeof(Controller)).ToList(); // фух! сложно! // вот так правильно, на уроке не получалось потому что подход мы использовали слишком простой // вот так сложнее но эффективнее - можно класть типы в любую папочку и использовать для них любой namespace, // Reflection через методы сборки подберёт их из самой сборки и правильно настроит // вот магия Reflection! // получаем имя сборки - как мы называемся? AssemblyName an = asm.GetName(); // получаем полное имя класса вместе с namespace чтобы проблема папочек решалась автоматически // имя класса с неймспейсом = кого имя совпадает с тем что считается именем контроллера, пришедшим из браузера String ClassName = Controllers // список контроллеров, отфильтруй нам контроллеры по имени, которое совпадает с тем что в ct.Controller, .Where(x => x.Name == ct.Controller) // и проконтролируй чтобы он там был, а если его там нет верни null .SingleOrDefault()? // внимание, ? означает что дальше идём только если тут чтото есть, если нет то следующая строка не будет выполняться. (сокращённая запись if != null) // если в предыдущей строке не был результат null то берём из того что получили FullName - это и будет имя класса (fully-qualified name), например assembly.namespace.classname, или к примеру Server.MVC.Home .FullName; // из имени класса и имени сборки создаём наш класс, завёрнутый в обслуживающую обёртку ObjectHandle tclass = Activator.CreateInstance(an.Name, ClassName); // получаем его тип (класс это сам класс например "Home" или "Game", а Type - это объект, который описывает этот класс, через него можно получить информацию об этом классе) Type type = asm.GetType(ClassName); // разворачиваем обёртку - получаем объект, созданный активатором из имени сборки и имени класса object unwc = tclass.Unwrap(); //приводим развёрнутый объект к типу Controller чтобы иметь доступ к контексту, и чтобы компилятор мог проконтролировать это до исполнения ((Controller)unwc).Context = ct; // если указан какойто метод, который нужно выполнить, то выполняем его (он поумолчанию Index) if (ct.Action != null) { // заполняем наш ответ тем, что вернёт метод контроллера (функция класса) // просим тип вызвать (invoke) заданный метод для заданного объекта класса // это так, потому что метод берётся из класса, а вызывается для объекта, // поэтому методу Invoke нужно передать объект, для которого вызвать этот метод // в конце приводим это всё к строке, потому что иначе компилятор не сможет проконтролировать тип responsestring = type.GetMethod(ct.Action).Invoke(unwc, null).ToString(); } } } else { // веточка не MVC, старый тип запуска игр // идём игроком (выполняем команду с клиента) game.MoveUser(TrimmedURL); // рендерим поле String GameField = game.RenderField(); //получаем файл-шаблон для нашей игры String tfile = GetFileContent("Game"); //заменяем там тэг "<game /> на отрендеренное игровое поле tfile = tfile.Replace("<game />", GameField); //заполняем строку вывода на клиент responsestring = tfile; } // получаем ответ клиенту из контекста HttpListenerResponse response = context.Response; // буфер - чтобы можно было обрабатывать по частям, кодируем всё в UTF8 byte[] buffer = Encoding.UTF8.GetBytes(responsestring); // сколько там букаф? осилим? response.ContentLength64 = buffer.Length; // получаем поток из ответа Stream output = response.OutputStream; // пишем в поток содержимое буфера output.Write(buffer, 0, buffer.Length); // закрываем поток output.Close(); // выводим в консоль на всякий случай чтобы если на клиенте чтото пойдёт не так мы в консоли видели проблему Console.WriteLine($"String {responsestring} sent to client"); } }