How to fix error 'There was an error deserializing the object of type Microsoft.AdCenter.Advertiser.Reporting.Api.DataContracts.Request.ReportRequest.?
My error:
WebFault while downloading report: Server raised fault: 'The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter https://bingads.microsoft.com/Reporting/v13:ReportRequest. The InnerException message was 'There was an error deserializing the object of type Microsoft.AdCenter.Advertiser.Reporting.Api.DataContracts.Request.ReportRequest. The value '' cannot be parsed as the type 'Int32'.'. Please see InnerException for more details.'
My code:
def download_campaign_report_for_account(reporting_service_manager, account_id, authorization_data):
"""Download campaign performance report with spend and click data using official example approach"""
try:
# Set account ID
authorization_data.account_id = account_id
# Get reporting service
reporting_service = ServiceClient(
service='ReportingService',
version=13,
authorization_data=authorization_data,
environment=ENVIRONMENT
)
# Following the exact pattern from the official Microsoft example
# Step 1: Build the report request
report_request = reporting_service.factory.create('CampaignPerformanceReportRequest')
report_request.Format = 'Csv'
report_request.ReportName = f'My Campaign Performance Report {account_id}'
report_request.ReturnOnlyCompleteData = False
report_request.Aggregation = 'Daily'
# Step 2: Set the time
report_time = reporting_service.factory.create('ReportTime')
report_time.PredefinedTime = 'Yesterday'
report_request.Time = report_time
# Step 3: Set the columns
report_columns = reporting_service.factory.create('ArrayOfCampaignPerformanceReportColumn')
report_columns.CampaignPerformanceReportColumn.append([
'AccountName',
'CampaignName',
'CampaignId',
'TimePeriod',
'Impressions',
'Clicks',
'Ctr',
'AverageCpc',
'Spend'
])
report_request.Columns = report_columns
# Step 4: Set the scope exactly as in the official example
scope = reporting_service.factory.create('AccountThroughCampaignReportScope')
# Key Change: Set the AccountIds directly without trying to create an array
scope.AccountIds = {'long': [account_id]}
report_request.Scope = scope
# Generate unique report filename
report_file_path = f"report_{account_id}_{int(time.time())}.csv"
log_debug(f"Submitting report request for account {account_id}...", critical=True)
try:
# Using the two-step approach with submit_download and download_result_file
# This avoids needing to use ReportingDownloadParameters
download_id = reporting_service_manager.submit_download(report_request)
log_debug(f"Report download submitted with ID: {download_id}", critical=True)
# Now poll for the report completion
result_file_path = reporting_service_manager.download_result_file(
download_id,
result_file_directory=None, # Use default directory
result_file_name=report_file_path,
decompress=True,
overwrite=True,
timeout_in_milliseconds=300000 # 5 minute timeout
)
log_debug(f"Report downloaded to {result_file_path}", critical=True)
# Process the report
report_data = []
if os.path.isfile(result_file_path):
# Log file size and preview for debugging
file_size = os.path.getsize(result_file_path)
log_debug(f"Report file size: {file_size} bytes")
if file_size < 100:
log_debug("WARNING: Report file is very small, may contain no data", critical=True)
with open(result_file_path, 'r', encoding='utf-8-sig') as f:
file_content = f.read(1000)
log_debug(f"Report preview:\n{file_content[:500]}")
# Reset file pointer
f.seek(0)
try:
csv_reader = csv.DictReader(f)
for row in csv_reader:
report_data.append(row)
log_debug(f"Parsed {len(report_data)} rows from report", critical=True)
if report_data:
log_debug(f"Sample data: {report_data[0]}")
except Exception as csv_err:
log_debug(f"Error parsing CSV: {str(csv_err)}", critical=True)
# Clean up
try:
os.remove(result_file_path)
log_debug(f"Removed temporary file: {result_file_path}")
except Exception as e:
log_debug(f"Failed to remove temp file: {str(e)}")
return report_data
else:
log_debug(f"Report file not found: {result_file_path}", critical=True)
return []
except WebFault as wf:
# Detailed error extraction
log_debug(f"WebFault while downloading report: {str(wf)}", critical=True)
if hasattr(wf, 'fault') and hasattr(wf.fault, 'detail'):
log_debug(f"Fault detail: {str(wf.fault.detail)}", critical=True)
raise wf
except Exception as e:
log_debug(f"Error in report submission: {str(e)}", critical=True)
raise e
except Exception as ex:
log_debug(f"Error downloading report for account {account_id}: {str(ex)}", critical=True)
return []