protected async Task <StaytusResponseModel <TResponseData> > InternalPostAsync <TContentData, TResponseData>(String servicePath, TContentData data = default(TContentData), Func <TContentData, String> serializeContentData = null, Func <String, JObject, StaytusResponseModel <TResponseData> > okParseResponse = null, CancellationToken cancelToken = default(CancellationToken)) { if (!servicePath.StartsWith("/")) { servicePath = "/" + servicePath; } if (serializeContentData == null) { serializeContentData = (contentData) => JsonNetExtensions.SerializeObject(contentData); } using (var httpReq = new HttpRequestMessage(HttpMethod.Post, BaseApiUrl + servicePath)) { httpReq.Content = new StringContent(serializeContentData(data), Encoding.UTF8, "application/json"); // if the ;charset is appended to content-type I noticed certain calls just failing (??) httpReq.Content.Headers.ContentType.CharSet = null; return(await InternalSendAsync(httpReq, (responseStr) => ParseResponse(responseStr, okParseResponse, null), cancelToken)); } }
/// <summary> /// The core delivery method for all other API methods. /// </summary> /// <typeparam name="TRequestBody"></typeparam> /// <typeparam name="TResponse"></typeparam> /// <param name="apiPath"></param> /// <param name="verb"></param> /// <param name="message"></param> /// <returns></returns> /// <exception cref="System.Exception"></exception> protected async Task <TResponse> ProcessRequestAsync <TRequestBody, TResponse>(string apiPath, HttpMethod verb, TRequestBody message = null) where TRequestBody : class { TResponse retval = default(TResponse); using (var client = ClientFactory()) { var request = new HttpRequestMessage(verb, baseUri + apiPath.TrimStart('/')); //if the message is not a string, or the message is a non-empty string, //set a body for this request. if (message != null) { var content = new JsonContent <TRequestBody>(message); request.Content = content; } request.Headers.Add("Accept", "application/json"); request.Headers.Add(AuthHeaderName, _authToken); request.Headers.Add("User-Agent", _agent); client.Timeout = TimeSpan.FromSeconds(this._requestTimeout); var result = await client.SendAsync(request); var body = await result.Content.ReadAsStringAsync(); if (!JsonNetExtensions.TryDeserializeObject <TResponse>(body, out retval) || result.StatusCode != HttpStatusCode.OK) { PostmarkResponse error; if (JsonNetExtensions.TryDeserializeObject <PostmarkResponse>(body, out error)) { switch ((int)result.StatusCode) { case 422: error.Status = PostmarkStatus.UserError; break; case 500: error.Status = PostmarkStatus.ServerError; break; default: error.Status = PostmarkStatus.Unknown; break; } throw new PostmarkValidationException(error); } else { throw new Exception("The response from the API could not be parsed."); } } } return(retval); }
// allow custom deserialization delegate functions to handle odd differences protected StaytusResponseModel <TResponseData> ParseResponse <TResponseData>(String responseStr, Func <String, JObject, StaytusResponseModel <TResponseData> > okParseResponse = null, Func <String, JObject, StaytusResponseModel <TResponseData> > errorParseResponse = null) { var responseJObject = JObject.Parse(responseStr); var statusToken = responseJObject["status"]; if (statusToken == null || statusToken.Type != JTokenType.String) { // no status prop, should mean this is an error // invalid json Logger.LogWarning("Invalid Api Response. Status property is null or not a string. Response: {0}", responseStr); // check if value prop is there for error message, pretty much we have an error response though return(new StaytusResponseModel <TResponseData>(SystemMessages.ERROR, GetErrorMessage(responseStr, responseJObject), default(TResponseData))); } String statusStr = statusToken.ToObject <String>(); if (String.Equals(statusStr, SystemMessages.SUCCESS, StringComparison.CurrentCultureIgnoreCase)) { // we should be fine at this point, we have a status that definitely says OK, attempt deserialization if (okParseResponse != null) { return(okParseResponse(responseStr, responseJObject)); } else { // default deserialization return(JsonNetExtensions.DeserializeObject <StaytusResponseModel <TResponseData> >(responseStr)); } } else { if (errorParseResponse != null) { return(errorParseResponse(responseStr, responseJObject)); } else { // default create response object as whatever status is and try to get error value return(new StaytusResponseModel <TResponseData>(statusStr, GetErrorMessage(responseStr, responseJObject), default(TResponseData))); // TODO handle pulling out time/flags/headers when parsing as well? } } }