diff --git a/Source/Podio .NET/Exceptions/PodioException.cs b/Source/Podio .NET/Exceptions/PodioException.cs index d9a8c6d..9659d61 100644 --- a/Source/Podio .NET/Exceptions/PodioException.cs +++ b/Source/Podio .NET/Exceptions/PodioException.cs @@ -207,7 +207,18 @@ public PodioUnavailableException(SerializationInfo info, StreamingContext contex } #endif } - + public class PodioInvalidJsonException : PodioException + { + public PodioInvalidJsonException(int status, PodioError error) + : base(status, error) + { + } +#if !NETSTANDARD1_3 + public PodioInvalidJsonException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } +#endif + } /// /// Represent the error response from API /// diff --git a/Source/Podio .NET/Models/Task.cs b/Source/Podio .NET/Models/Task.cs index 2bb5cbe..f6bbffc 100644 --- a/Source/Podio .NET/Models/Task.cs +++ b/Source/Podio .NET/Models/Task.cs @@ -7,7 +7,7 @@ namespace PodioAPI.Models public class Task { [JsonProperty("task_id")] - public string TaskId { get; set; } + public int TaskId { get; set; } [JsonProperty("status")] public string Status { get; set; } diff --git a/Source/Podio .NET/Podio.cs b/Source/Podio .NET/Podio.cs index 5ed8501..9864947 100644 --- a/Source/Podio .NET/Podio.cs +++ b/Source/Podio .NET/Podio.cs @@ -1,4 +1,5 @@ -using PodioAPI.Exceptions; +using Newtonsoft.Json; +using PodioAPI.Exceptions; using PodioAPI.Models; using PodioAPI.Services; using PodioAPI.Utils; @@ -75,8 +76,11 @@ internal async Task Get(string url, Dictionary requestData } else { - var jsonString = JSONSerializer.Serilaize(requestData); - request.Content = new StringContent(jsonString, Encoding.UTF8, "application/json"); + if (requestData != null) + { + var jsonString = JSONSerializer.Serilaize(requestData); + request.Content = new StringContent(jsonString, Encoding.UTF8, "application/json"); + } } return await Request(request); @@ -159,31 +163,44 @@ internal async Task Get(string url, Dictionary requestData else { var responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - var podioError = JSONSerializer.Deserialize(responseBody); - - if (response.StatusCode == HttpStatusCode.Unauthorized) + try { - // If RefreshToken exists, refresh the access token and try the request again - if (OAuth is PodioOAuth podioOAuth && !string.IsNullOrEmpty(podioOAuth.RefreshToken) && podioError.ErrorDescription == "expired_token" || podioError.Error == "invalid_token") + var podioError = JSONSerializer.Deserialize(responseBody); + + if (response.StatusCode == HttpStatusCode.Unauthorized) { - var authInfo = await RefreshAccessToken().ConfigureAwait(false); - if (authInfo != null && !string.IsNullOrEmpty(authInfo.AccessToken)) + // If RefreshToken exists, refresh the access token and try the request again + if (OAuth is PodioOAuth podioOAuth && !string.IsNullOrEmpty(podioOAuth.RefreshToken) && podioError.ErrorDescription == "expired_token" || podioError.Error == "invalid_token") + { + var authInfo = await RefreshAccessToken().ConfigureAwait(false); + if (authInfo != null && !string.IsNullOrEmpty(authInfo.AccessToken)) + { + requestCopy.Headers.Authorization = new AuthenticationHeaderValue("OAuth2", authInfo.AccessToken); + return await Request(requestCopy, isFileDownload, returnAsString); + } + } + else { - requestCopy.Headers.Authorization = new AuthenticationHeaderValue("OAuth2", authInfo.AccessToken); - return await Request(requestCopy, isFileDownload, returnAsString); + OAuth = null; + throw new PodioAuthorizationException((int)response.StatusCode, podioError); } } else { - OAuth = null; - throw new PodioAuthorizationException((int)response.StatusCode, podioError); - } + ProcessErrorResponse(response.StatusCode, podioError); + } + } - else + catch (JsonException ex) { - ProcessErrorResponse(response.StatusCode, podioError); + throw new PodioInvalidJsonException((int)response.StatusCode, new PodioError + { + Error = "Error response is not a valid Json string.", + ErrorDescription = ex.ToString(), + ErrorDetail = responseBody + }); } - + return default(T); } } @@ -215,6 +232,7 @@ private HttpRequestMessage CreateHttpRequest(string url, HttpMethod httpMethod, private void ProcessErrorResponse(HttpStatusCode statusCode, PodioError podioError) { var status = (int)statusCode; + switch (status) { case 400: diff --git a/Source/Podio .NET/Services/FileService.cs b/Source/Podio .NET/Services/FileService.cs index a432b52..063cb75 100644 --- a/Source/Podio .NET/Services/FileService.cs +++ b/Source/Podio .NET/Services/FileService.cs @@ -318,5 +318,21 @@ public async Task DownloadFile(FileAttachment fileAttachment) }; return await _podio.Get(fileLink, new Dictionary(), true); } + /// + /// Add linked account file (like sharefile, google drive) + /// + /// + /// + /// + /// + public async Task UploadLinkedAccountFile(int linkedAccountId, string externalFileId, bool preservePermissions = true) + { + var url = $"/file/linked_account/{linkedAccountId}/"; + var request = new + { + external_file_id = externalFileId + }; + return await _podio.Post(url, request); + } } } \ No newline at end of file diff --git a/Source/Podio .NET/Utils/ItemFields/LocationItemField.cs b/Source/Podio .NET/Utils/ItemFields/LocationItemField.cs index 37f697d..971cfaa 100644 --- a/Source/Podio .NET/Utils/ItemFields/LocationItemField.cs +++ b/Source/Podio .NET/Utils/ItemFields/LocationItemField.cs @@ -77,6 +77,44 @@ public double? Longitude this.Values.First()["lng"] = value; } } + public string StreetAddress + { + get + { + if (this.Values.Any()) + { + return (string)this.Values.First["street_address"]; + } + + return null; + } + } + + public string City + { + get + { + if (this.Values.Any()) + { + return (string)this.Values.First["city"]; + } + + return null; + } + } + + public string PostalCode + { + get + { + if (this.Values.Any()) + { + return (string)this.Values.First["postal_code"]; + } + + return null; + } + } public string Country {