Last active
March 1, 2023 23:17
-
-
Save mikeblakeuk/b9062d9b2f68cc3830591009b0e59889 to your computer and use it in GitHub Desktop.
PowerBIHttpOperationExceptionHandler - converts error to exceptions for power bi calls (to include the real message from the header)
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 characters
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; } | |
} | |
} | |
} |
Author
mikeblakeuk
commented
Jul 5, 2017
We are receiving this error on attempt to upload a powerbi .pbix file, are we able to get any better detail on the cause?
X-PowerBI-Error-Details: {"error":{"code":"UnknownError","pbi.error":{"code":"UnknownError","parameters":[],"details":[],"exceptionCulprit":1}}}
We didnt find out cause of our error but we did find a code sample that worked so ended up using that -> https://gitlab.com/Lieben/assortedFunctions/blob/master/Import-PBIXToPowerBI.ps1
No sorry, You could try this instead? https://github.com/mikeblakeuk/PowerBI-Developer-Samples/tree/feature/loadtests/LoadTesting
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment