Forked from mikeblakeuk/PowerBIHttpOperationExceptionHandler.cs
Created
March 1, 2023 23:17
-
-
Save DiracSpace/0a1b4f95fb4b0d3e2b7cad13c3f4e702 to your computer and use it in GitHub Desktop.
Revisions
-
mikeblakeuk renamed this gist
Jul 5, 2017 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
mikeblakeuk created this gist
Jul 5, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,128 @@ using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Microsoft.Rest; using Microsoft.Rest.Serialization; using Newtonsoft.Json; namespace PowerBI { // Samples: // {"error":{"code":"InvalidRequest", "message":"datasetId is null or empty"}} // {"error":{"code":"GeneralException", "message":"Failed to process dataset PostDataset","target":"PostDataset","details":[{"message":"SQL operation failed: The Database operation reached a timeout of '00:01:30'"}]}} // {"error":{"code":"DM_GWPipeline_UnknownError","pbi.error":{"code":"DM_GWPipeline_UnknownError","parameters":{},"details":[]}}} // {"error":{"code":"FeatureNotAvailableError","pbi.error":{"code":"FeatureNotAvailableError","parameters":{},"details":[]}}} // {"error":{"code":"UnknownError", "pbi.error":{"code":"UnknownError","parameters":{},"details":[],"exceptionCulprit":1}}} public class PowerBIHttpOperationExceptionHandler : DelegatingHandler { const string XPowerBIErrorDetailsHeaderKey = "X-PowerBI-Error-Details"; const string RequestIdHeaderKey = "RequestId"; protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var response = await base.SendAsync(request, cancellationToken); if (response.IsSuccessStatusCode) { return response; } var errorBody = ErrorInHeader(response); var content = response.Content?.ReadAsStringAsync().Result ?? string.Empty; errorBody = errorBody ?? content; var errorTypeSafe = IsPowerBIErrorJson(errorBody); if (errorTypeSafe == null) { return response; } var message = $"Power BI operation returned an error code '{errorTypeSafe.Code}'"; var exception = new PowerBIErrorException(message) { Body = errorBody, Code = errorTypeSafe.Code, ErrorMessage = errorTypeSafe.Message, Details = errorTypeSafe.Details?.FirstOrDefault()?.Message, Request = new HttpRequestMessageWrapper(request, request.Content?.ReadAsStringAsync().Result), //If the user was uploading a 10meg pbix, we have just read it twice Response = new HttpResponseMessageWrapper(response, content) }; if (response.Headers.Contains(RequestIdHeaderKey)) { exception.RequestId = response.Headers.GetValues(RequestIdHeaderKey).FirstOrDefault(); } var shouldTrace = ServiceClientTracing.IsEnabled; if (shouldTrace) { //var invocationId = (ServiceClientTracing.NextInvocationId - 1).ToString(); //need to use the same id from the call. //ServiceClientTracing.Error(invocationId, exception); } request.Dispose(); response.Dispose(); throw exception; } static string ErrorInHeader(HttpResponseMessage response) { IEnumerable<string> errorHeaderValues = null; if (response.Headers?.TryGetValues(XPowerBIErrorDetailsHeaderKey, out errorHeaderValues) == true) { var xHeaderErrorDetails = errorHeaderValues?.SingleOrDefault(); if (xHeaderErrorDetails != null) { return xHeaderErrorDetails; } } return null; } static PowerBIError IsPowerBIErrorJson(string body) { if (string.IsNullOrEmpty(body)) { return null; } try { var json = SafeJsonConvert.DeserializeObject<PowerBIErrorBody>(body); return json?.Error; } catch (JsonException) { } return null; } public class PowerBIErrorBody { [JsonProperty(PropertyName = "error")] public PowerBIError Error { get; set; } } public class PowerBIError { [JsonProperty(PropertyName = "code")] public string Code { get; set; } [JsonProperty(PropertyName = "details")] public IEnumerable<PowerBIExceptionDetails> Details { get; set; } [JsonProperty(PropertyName = "message")] public string Message { get; set; } [JsonProperty(PropertyName = "target")] public string Target { get; set; } } public class PowerBIExceptionDetails { [JsonProperty(PropertyName = "message")] public string Message { get; set; } } } }