Skip to content

Instantly share code, notes, and snippets.

@mikeblakeuk
Last active March 1, 2023 23:17
Show Gist options
  • Save mikeblakeuk/b9062d9b2f68cc3830591009b0e59889 to your computer and use it in GitHub Desktop.
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)
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; }
}
}
}
@mikeblakeuk
Copy link
Author

        return new PowerBIClient(new Uri(PowerBIRootUrl), GetToken(), new PowerBIHttpOperationExceptionHandler());

@mattduguid
Copy link

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}}}

@mattduguid
Copy link

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

@mikeblakeuk
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment