Giter Site home page Giter Site logo

googleads-dotnet-lib's Introduction

Google Ad Manager SOAP API .NET Client Library

This project hosts the .NET client library for the Google Ad Manager SOAP API.

Features

  • Distributed via Nuget
  • Stub classes for all the supported API versions and services.
  • Helpful utilities
  • SOAP messages are logged, for easier debugging purposes
  • Automatic handling of SOAP headers
  • Easy management of credentials, authentication, and session information
  • Docs available in HTML and XML format.

Supported Frameworks

Announcements and updates

For API and client library updates and news, please follow our Google Ads Developers blog: http://googleadsdeveloper.blogspot.com/.

Getting started

  1. Install your library. We recommend using the following Nuget distribution:
  • Google.Dfp: Ad Manager API DotNet Client Library

You can learn more about the nuget package manager at http://www.nuget.org. For other distribution options, see the alternative distribution options below.

  1. Setup your OAuth2 credentials.

The and Ad Manager API uses OAuth2 as the authentication mechanism. Follow the appropriate guide below based on your use case.

If you're accessing an API using your own credentials...

If you're accessing an API on behalf of clients...

Alternative distribution options

Binary distribution

The binary distribution of the Ads API .NET library consists of a precompiled version of the library as a .NET assembly, code examples for using the library, and library documentation. If you are interested in just using the library and not in its internals, and you don't use nuget package manager in your development environment, then you should download this distribution.

The contents of this distribution are as follows:

  \
    \lib
      - Precompiled assemblies.
      - Documentation xmls for the assemblies.
    \examples
       Code examples, in C# and VB.NET (when available).
    README
    ChangeLog
    COPYING
    Visual Studio solution file

To run the code examples:

  • Open Visual Studio solution file in the root folder of the binary distribution in Microsoft Visual Studio
  • Open App.config for the examples project and follow the instructions in the file to enter required configuration values.
  • Save and close App.config.
  • Open the Properties dialog for the Examples project (Right click the Examples project of your choice in the Solution Explorer and select the Properties option from the context menu.).
  • Navigate to the Debug Tab and enter the command line options. The command line options are of the form version.examplename. For instance, v202308.GetCurrentNetwork is the command line option to run GetCurrentNetwork example in v202308 version of the Ad Manager API.
  • Compile and run the Examples project.

Alternatively, each code example has a main() method, so you can set the appropriate code example as the Startup object (Select the Application tab on the Examples Properties dialog and pick the desired class from the "Startup object" dropdown.).

To use the library in a new project:

  • Create a new Visual Studio project of your choice (for instance, a C# Windows application).
  • Copy the lib folder from the binary distribution to your project folder. Add references to all the assemblies in this folder in your project.
  • Add a reference to System.Web.Services in your project.
  • Copy examples\App.config to your project directory and add it to your project.
  • Edit the required keys in App.config. If your application has its own App.config, then you need to merge its contents with the contents of examples\App.config.
  • Make a call to the library, e.g.:
// Create an appropriate AdsUser instance.
AdManagerUser user = new AdManagerUser();

// Create the required service.
using (NetworkService networkService = user.GetService<NetworkService>())
{
    // make calls to service class.
}

You can refer to this wiki article for more details.

How to enable logging

See https://github.com/googleads/googleads-dotnet-lib/wiki#logging for details.

Miscellaneous

Wiki

Issue tracker

API Documentation:

Support forum

Authors

googleads-dotnet-lib's People

Contributors

akilburge avatar anashoommen avatar christopherseeley avatar dependabot[bot] avatar jimper avatar majagrubbe avatar mayerwin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

googleads-dotnet-lib's Issues

Issue with SOAP Logging Instructions for AdWords

Option 1 of this link https://github.com/googleads/googleads-dotnet-lib/wiki/How-to-capture-SOAP-messages doesn't appear to work with modification, which is not clear from the instructions. At the very least, the values of the switches should not be 'Off'. However, even when I change this, I still cannot get any logging from my application, so I suspect there may either be another issue with the code, or there is a step missing from the instructions. Either way, a novice 'logger' cannot use these instructions as is.

Thanks,
Conor

ReportResponse.Text throws exception (Array cannot be null)

(Common.Utils.Reports.)ReportReponse.Text is a helper method, relying on ReportResponse.Contents ... or it should be.

Instead, it is using the underlying contents variable, which is not set unless Download() is called first - resulting in an exception. It should, instead, be calling into the Contents property (which does call Download()).

Ensure that enums have immutable numerical values associated with them

This has more to do with the way Ads Apis manage their enums. But to summarize the problem, let's say a new value got added / removed from an existing enum across API versions. The generated code would look like this:

v1

enum MyEnum {
value1, //0
value2, //1
value3 //2
}

v2

enum MyEnum {
value1, //0
value3 //1
}

If someone were to depend on the value associated with the enum for serialization purposes, they need to migrate their database values also when moving from v1 to v2.

.NET's recommended approach is to ensure that values are unique, like this:

enum MyEnum {
value1 = 0,
value2 = 1,
value3 = 2
}

However, the code generator doesn't have a good way of ensuring this kind of a numbering, so a possible workaround would be

enum MyEnum {
value1 = crc32("value1"),
value2 = crc32("value2"),
value3 = crc32("value3")
}

This works across versions, but it is not backward compatible.

Improve detection of AdWords and Common library versions when generating user agent string

The user agent for some requests does not pick up the proper AdWords and Common library versions. See the rows below where the version string is not of the form xx.xx.xx.

AdWords Common
1.3.15233 1.3.15233
16.3.0 1.9.0
16.7.0 2.2.0
16.7.1 2.2.1
17.0.0 2.3.0
17.1.0 2.4.0
17.1010.4782 17.1010.4782
17.1020.3735 17.1020.3735
17.1024.9098 17.1024.9098
17.1029.4135 17.1029.4135
17.1103.5855 17.1103.5855
17.1103.6798 17.1103.6798
17.1103.9267 17.1103.9267
17.1103.9940 17.1103.9940
17.1104.236 17.1104.236
17.1104.3226 17.1104.3226
17.1104.3849 17.1104.3849
17.1104.4402 17.1104.4402
17.1105.4792 17.1105.4792
17.1105.8617 17.1105.8617
17.2.0 2.4.0
17.3.0 2.5.0
17.3.1 2.5.1
17.3.2 2.5.2
17.512.4508 17.512.4508
17.611.9594 17.611.9594
17.618.1599 17.618.1599
17.623.4677 17.623.4677
17.707.4388 17.707.4388
17.717.2120 17.717.2120
17.820.7953 17.820.7953
17.916.8107 17.916.8107
18.0.0 3.0.0
18.0.0 3.1.0
18.1.0 3.1.0
18.2.0 3.1.0
18.2.0 3.2.0
18.3.0 3.2.0
18.4.0 3.3.0
18.5.0 2.2.0
18.5.0 3.4.0

Whither ApiErrorType?

You may have been a bit too aggressive removing the ".Type" fields for DFP API v201502 because the client library's "ApiError.ApiErrorType" field is gone too. (I have C# client library 18.10.0.0)

I thought perhaps the comment about typeof/instanceof/etc. in the DFP API release notes meant the method had changed so I went looking for a different field and serialized an ApiException to:

{
   "message" : "[TeamError.ALL_TEAM_ASSOCIATION_NOT_ALLOWED @ appliedTeamIds; trigger:'28469']",
   "errors" : [
      {
         "fieldPath" : "appliedTeamIds",
         "reason" : 4,
         "trigger" : "28469",
         "reasonSpecified" : true,
         "errorString" : "TeamError.ALL_TEAM_ASSOCIATION_NOT_ALLOWED"
      }
   ]
}

but other than substring'ing "errorString" I don't see a reasonable replacement for what "errors[x].ApiErrorType" used to have. (As an aside, the client library doesn't recognize the existence of the "reason" field above, if that is supposed to be included.)

Alternatively, you forgot to update your "Getting Started" guide https://github.com/googleads/googleads-dotnet-lib/wiki/Getting-Started regarding error handling and I missed whatever notification was put out regarding a change in exception handling, which wouldn't surprise me given how busy I've been.

While talking about the "Getting Started" guide's example, there is no "ErrorUtilities" in the DFP C# client library.

For reference, the error handling I use looks like:

                catch (DfpApiException e) {
                    ApiException eapi = (ApiException)e.ApiException;
                    foreach (ApiError err in eapi.errors) {
                        if (err.ApiErrorType == "QuotaError") {
                            QuotaError qerr = (QuotaError)err;
                            if (qerr.reason == QuotaErrorReason.EXCEEDED_QUOTA) {
                                Console.WriteLine("\tExceeded quota.");
                                Thread.Sleep(1000 * 1); // 1 second
                                goto re/*try*/;
                            }
                        } else if (err.ApiErrorType == "FeatureError") {
...etc...

(I don't particularly like comparing them as strings but such is life.)

ReportResponse Text and Contents Missing

The ReportResponse.Text and Contents methods are missing in the Ads API .NET Client Library - v18.14.0. I have tried accessing these methods through our custom application and adding them to the AdWords.Examples project but they are not available and give the below compile error message:
'Text' is not a member of 'Google.Api.Ads.Common.Util.Reports.ReportResponse'.

The documentation here for Downloading Reports indicates that these methods are still available:
https://github.com/googleads/googleads-dotnet-lib/wiki/Downloading-Reports

I changed our code to use the ReportResponse.stream to work around the issue.

Thank you.

Nuget package in fresh .Net 4.0 Console Project throws System.TypeLoadException

What steps will reproduce the problem?

Create a Console project in visual studio using .net 4
Install the nuget package Google.AdWords
Instantiate Google.Api.Ads.AdWords.Lib.AdWordsUser
What is happening?

System.TypeLoadException crossed a native/managed boundary
HResult=-2146233054
Message=Could not load type 'System.Configuration.DictionarySectionHandler' from assembly 'System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
Source=mscorlib
TypeName=System.Configuration.DictionarySectionHandler
StackTrace:
at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type)
at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName)
at System.Type.GetType(String typeName, Boolean throwOnError)
at System.Configuration.Internal.InternalConfigHost.System.Configuration.Internal.IInternalConfigHost.GetConfigType(String typeName, Boolean throwOnError)
at System.Configuration.TypeUtil.GetTypeWithReflectionPermission(IInternalConfigHost host, String typeString, Boolean throwOnError)
InnerException:

What version of the product are you using? On what operating system?

Latest from nuget main repository: 16.2.0.0, Windows 7, .Net 4.0, Visual Studio 2012 (as Administrator)

Please provide any additional information below.

I could fix it changing this in my app.config
From

To

It is probably some .net issue related to .net 2.0 dlls running on .net 4.0 environments, so I completely understand if you mark it as won't fix.

Change ContainsKey checks to use TryGetValue

Once the runtime requirement is increased to .NET 4.0, we should replace ContainsKey checks with TryGetValue (wherever possible).This will be an overall performance improvement.

ServerError.SERVER_ERROR

LineItemService service = (LineItemService)user.GetService(DfpService.v201411.LineItemService);
Statement statement = new StatementBuilder()
                .Where("targeting.inventoryTargeting.targetedAdUnits.adUnitId IN (" + string.Join(",", adUnitIds) + ")")
                .Limit(StatementBuilder.SUGGESTED_PAGE_LIMIT)
                .ToStatement();

var page = service.getLineItemsByStatement(statement);

Hi I am using .Net version library. Is it possible to get all lineItem that having targeting in inventory?

I try the way on top but I am getting [ServerError.SERVER_ERROR @ ]

StackTrace

Message: "An error has occurred.",
ExceptionMessage: "[ServerError.SERVER_ERROR @ ]",
ExceptionType: "System.Web.Services.Protocols.SoapException",
StackTrace: " at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall) at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters) at Google.Api.Ads.Common.Lib.AdsSoapClient.MakeApiCall(String methodName, Object[] parameters)"

ReportsException does not contain trigger information

When a report request fails, the API returns useful information in the trigger field, but this is not in the toString of ReportsException. Below are some examples of the XML for reference.

Invalid DURING clause:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<reportDownloadError>
  <ApiError>
    <type>ReportDefinitionError.INVALID_DATE_RANGE_FOR_REPORT</type>
    <trigger>A single day DateRange is required for reportType:
      CLICK_PERFORMANCE_REPORT</trigger>
    <fieldPath/>
  </ApiError>
</reportDownloadError>

Invalid field name:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<reportDownloadError>
  <ApiError>
    <type>ReportDefinitionError.INVALID_FIELD_NAME_FOR_REPORT</type>
    <trigger/>
    <fieldPath>ConversionTypeName</fieldPath>
  </ApiError>
</reportDownloadError>

Support for non-impersonation service accounts

DFP recently added support for OAuth2 service accounts but this (.NET) client library still assumes a service account using a Google Apps for Business account with impersonation (PrnEmail).

Clarify AdsUser's concurrent usage in the Wiki page

Explicitly document that AdsUser is not thread-safe, which is required for all Soap calls and report downloads. To make a call in a different thread, new AdsUser (AdWordsUser, DfaUser, DfpUser) should be created.

Correctly serializes xml on mono platform

The code should look like this in src/Common/Util/SerializationUtilities.cs

public static string SerializeAsXmlText(object objToSerialize) {
   string retval = "";
   using (var writter = new Utf8StringWritter()) {
     new XmlSerializer(objToSerialize.GetType()).Serialize(writter, objToSerialize);
     retval = writter.ToString();
   }
   return retval;
  }
}

class Utf8StringWritter : StringWriter {
  public override Encoding Encoding {
    get { return new UTF8Encoding(false); }
  }
}

Ensure the library can be built using Mono

If we can ensure the library built using Mono works and passes the all tests, preparing the development environment is much more easy for developers not using windows.

Increase runtime requirement to .NET 4.0

Increase the runtime requirement of the library to .NET 4.0, so we can begin leveraging functionality introduced in newer versions of the runtime.

When accepting this request, please implement this as a fork - and keep the current lib untouched.

.NET 4.0 has higher system requirements, and not all versions of Visual Studio support .NET 4.0. I don't think that everybody should upgrade their production and development environments when only a few want extra functionality.

AdWords API: Include ApiError description in library

When the library encounters an ApiExceptionFault, it raises an AdWordsApiException with an array of ApiErrors. Those ApiErrors only contain the error types, but not the error descriptions.
For instance, when AdWords API encounters an unexpected interal error, you get an AdWordsApiException with exactly one ApiError, and that error only spells InternalApiError.UNEXPECTED_INTERNAL_API_ERROR. I want an extra field description that contains the value "API encountered an unexpected internal error."

Note the descriptions are scattered around the AdWords API docs, for instance here: https://developers.google.com/adwords/api/docs/reference/v201309/CampaignService.InternalApiError

I have two reasons for this wish:

  1. When my software cannot deal with an exception it logs that exception. It is very inconvenient to look up the ApiError every time. Now I have made a handler that looks up a few well known ApiError classes, and I assume that I am not alone. It would make sense when we could all use the same descriptions.
  2. The AdWords API team appears not to update new errors. For instance, I was surprised to learn about the new error InternalApiError.DOWNTIME. A central place where all new errors are described would make more sense.

An extra, related wish: when AdWordsApiException.ApiError contains exactly one ApiError, use the same description in AdWordsApiException.Message. Now the message always reads "An API exception has occurred. See ApiException and InnerException fields for more details."
The exception would have been clearer when the message read "An API exception has occurred: The API is currently unavailable for a planned downtime."

Preserve exception info when throwing exceptions in exception handlers.

The library (at least 16.7) shows quite a few instances like this:

    catch (WebException ex)
    {
        throw new ApplicationException(GetResponseText(ex.Response));
    }

(This instance found in OAuth2ProviderBase.cs, method CallTokenEndpoint(), line 320-363)
So, when a WebException is found, an ApplicationException is thrown. But the original WebException is not preserved! A better implementation would be:

    catch (WebException ex)
    {
        throw new ApplicationException(GetResponseText(ex.Response), ex);
    }

Here the original exception becomes the inner exception of the new exception.

I prefer to have those original exceptions, because my exception loggers also look through inner exceptions and try to retrieve as much info as possible, like HTTP status code, response headers etc.etc. Sometimes they help AdWords API support people to identify problems.

Access is Denied

Hello,
I am getting "Access is denied" error every time I try to generate OAuth2 token using the "OAuthTokenGenerator.exe" program. and I am using Client ID and Secret from "console.developers.google.com -> APIs & Auth -> Credentials.
Any kind of help will be really appreciated.
oauth error

AdWords API: code example to add siteLinks

A sample exists to add SiteLinks, but none exists to download SiteLinks or any other FeedService. The process to download is significantly different from creation and deserves its own example.

Thank you!

multi threading with reportUtilities.GetResponse() - gets stuck

Hi.
While multi threading report downloads this

       ReportResponse reportResponse = reportUtilities.GetResponse();

sometimes gets stuck.

There is no error message, or timeout or... anything.

I'm using

       foreach(AdWordsUser user in adWordsUsers)
       {
                  foreach(ReportDefinition definition in definitions)
                  {
                             Thread a = new Thread(new ThreadStart(delegate()
                                 { 
                  /*some code with GenerateRaport thing - it writes raport data to a database*/
                                 }));
                  }
         }


       public StringBuilder GenerateRaport(AdWordsUser awUser, ReportDefinition reportDefinition)
               {
                   StringBuilder reportText = new StringBuilder();
                   ReportUtilities reportUtilities = new ReportUtilities(awUser, "v201409", reportDefinition);
                   try
                   {
                           ReportResponse reportResponse = reportUtilities.GetResponse();
                           byte[] reportBytes = reportResponse.Download();
                           reportText.Append(Encoding.UTF8.GetString(reportBytes));
                   }
                   catch (Exception ex)
                   {
                       errorLog.WriteLine(System.DateTime.Now.ToString() + ": " + (awUser.Config as      AdWordsAppConfig).ClientCustomerId.ToString() + " " + reportDefinition.reportName);
                       errorLog.WriteLine(ex.ToString());
                       reportText.Append("");
                       errorLog.Flush();
                   }
                   return reportText;
                  }

It have never stucked with no threading.
How to multithread this safe?

New ReportUtilities fails to get 3 reports in a row

Hello.

I've just updated my application to 18.6.0 (via NuGet, if that matters) and discovered a weird behavior of new ReportUtilities: it successfully gets two reports for the same client, but requesting a third one will just hang until timeout. Switching back to legacy ReportUtilities works fine.

Here's some test code.
It requests 3 exactly the same reports (for simplicity, reproduces for different reports too) in a row, showing the first two are returned in a few seconds, but 3rd one always timeouts after 100 seconds (default timeout in app.config). Increasing the timeout value doesn't help, just makes it stuck for more time.

using System;
using System.Xml;
using System.Diagnostics;
using Google.Api.Ads.Common.Lib;
using Google.Api.Ads.AdWords.Lib;
using Google.Api.Ads.AdWords.v201409;

namespace test_report
{
    class Program
    {
        static void Main(string[] args)
        {
            var adwords = new AdWordsUser();
            var config = (AdWordsAppConfig)adwords.Config;

            config.Email = "...";
            config.DeveloperToken = "...";
            config.OAuth2Mode = OAuth2Flow.APPLICATION;
            config.OAuth2RefreshToken = "...";
            config.OAuth2ClientId = "...";
            config.OAuth2ClientSecret = "...";
            config.ClientCustomerId = "...";

            const string ReportVersion = "v201409";
            DateTime startDate = new DateTime(2014, 10, 1), endDate = new DateTime(2014, 10, 31);

            for (int i = 1; i <= 3; i++)
            {
                Console.WriteLine("Report #{0}...", i);

                var defi = new ReportDefinition();
                defi.dateRangeType = ReportDefinitionDateRangeType.CUSTOM_DATE;
                defi.reportType = ReportDefinitionReportType.KEYWORDS_PERFORMANCE_REPORT;
                defi.reportName = "KEYWORDS_PERFORMANCE_REPORT";
                defi.downloadFormat = DownloadFormat.XML;
                defi.selector = new Selector()
                {
                    fields = new string[] {
                        "CampaignId", "CampaignName", "Id", "KeywordText",
                        "Date", "Impressions", "Clicks", "Cost", "AdNetworkType1"
                    },
                    dateRange = new DateRange
                    {
                        min = startDate.ToString("yyyyMMdd"),
                        max = endDate.ToString("yyyyMMdd")
                    }
                };

                var stopwatch = new Stopwatch();
                stopwatch.Start();

                try
                {
                    // this works for first two reports and always fails for the 3rd one:
                    var util = new Google.Api.Ads.AdWords.Util.Reports.ReportUtilities(adwords, ReportVersion, defi);
                    var response = util.GetResponse();
                    var xml = new XmlDocument();
                    xml.Load(response.Stream);

                    // and this works okay:
                    //var util = new Google.Api.Ads.AdWords.Util.Reports.Legacy.ReportUtilities(adwords);
                    //util.ReportVersion = ReportVersion;
                    //var response = util.GetClientReport(defi);
                    //var xml = new XmlDocument();
                    //xml.LoadXml(response.Text);

                    stopwatch.Stop();
                    Console.WriteLine("Done in {0}", stopwatch.Elapsed);
                }
                catch(Exception ex)
                {
                    stopwatch.Stop();
                    Console.WriteLine("Error in {0}: {1}", stopwatch.Elapsed, ex.Message);
                }
            }
        }
    }
}

The output is:

Report #1...
Done in 00:00:04.3187831
Report #2...
Done in 00:00:02.8653650
Report #3...
Error in 00:01:40.0315389: The operation has timed out

Strongly Typed Report Result

Returning Strongly Typed Report Results. Or providing C# POCO classes to be serialized from XML results or any other way of consuming the service results with strongly typed classes.

Fix DeprecationUtilitiesTest

DeprecationUtilitiesTest seems to be broken, since we are capturing messages from the generic trace queue, but writing to a specific trace source.

Add a marker interface for ReportDefinition

Add a marker interface for ReportDefinition, so that users get a compilation error when they write code like:

new ReportUtilities(user, query, DownloadFormat.CSV) and m

Ideally, the user should write:

new ReportUtilities(user, query, DownloadFormat.CSV.ToString());

But if they forget the ToString() part, then C# will resolve the code to

public ReportUtilities(AdWordsUser user, string reportVersion, object reportDefinition)

instead of

public ReportUtilities(AdWordsUser user, string query, string format)

This compiles fine, we will also serialize DownloadFormat.CSV and send it to the server, but the server will crash because the output we send to the server is not a valid report definition.

Stackoverflow in legacy ReportUtilities

Using the latest 18.9.0.0 client library and the legacy APIs all the GetClientReport methods are calling themselves after having shown the deprecation message. Which leads to a StackOverflowException.

/// <summary>
///  Downloads a report into memory.
/// </summary>
/// <param name="reportDefinition">The report definition.</param>
/// <returns>The client report.</returns>
public ClientReport GetClientReport<T>(T reportDefinition) {
    DeprecationUtilities.ShowDeprecationMessage(this.GetType());
    return GetClientReport(reportDefinition);
}

Standardize logging messages

We currently have some custom log messages being generated by different products. We should look into removing custom logging and instead use a standard format for all log messages.

AdWords API: While trying to update a negative keyword, an Xml parsing exception is thrown

What steps will reproduce the problem?

  1. Use the AdGroupCriterionService to try and add a DestinationUrl to a negative keyword

What is the expected output? What do you see instead?
I'd expect an exception of type AdWordsApiException to be thrown, with the ApiException.Errors property populated correctly. Instead an InvalidOperationException "Response is not well-formed XML." is thrown.

What version of the product are you using? On what operating system?

Google.AdWords.dll version 16.4.0.0
API version v201309
Please provide any additional information below.
I proxied the request and the expected SOAP fault message is returning correctly, it looks like it's trying to be deserialized into the wrong .net type, because the InnerException of the InvalidOperationException is a XmlException "Data at the root level is invalid. Line 1, position 1."

The SOAP message returned from the API looks like:

soap:Header0004ed34bf61fd380a421a6f00007ff6AdGroupCriterionServicemutate10001049/soap:Headersoap:Bodysoap:Faultsoap:Server[AdGroupCriterionError.CANT_UPDATE_NEGATIVE @ operations[722].operand, AdGroupCriterionError.CANT_UPDATE_NEGATIVE @ operations[723].operand, ...

Supply better exceptions when a refreshtoken could not be retrieved

Lately I got an exception when retrieving a refreshtoken. The call stack was:

Google.Api.Ads.Common.Lib.OAuth2ProviderBase.GetAuthHeader () 
Google.Api.Ads.Common.Lib.OAuth2ProviderBase.RefreshAccessTokenIfExpiring () 
Google.Api.Ads.Common.Lib.OAuth2ProviderForApplications.RefreshAccessToken () 
Google.Api.Ads.Common.Lib.OAuth2ProviderForApplications.RefreshAccessTokenInOfflineMode () 

(Common library 2.2)
This was the value of Exception.Message:

Failed to refresh access token.
<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 502 (Server Error)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/errors/logo_sm_2.png) no-repeat}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/errors/logo_sm_2_hr.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/errors/logo_sm_2_hr.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/errors/logo_sm_2_hr.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:55px;width:150px}
  </style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p>502. <ins>That’s an error.</ins>
  <p>The server encountered a temporary error and could not complete your request.<p>Please try again in 30 seconds.  <ins>That’s all we know.</ins>

(BTW the issue-editor included newline characters - they were not in the exception.)

Reading the complete text it would have made sense to retry the call after a while. But it appears to be impossible to predict all kinds of exceptions when they have a text like this.
The request is to interprete those messages a bit more, so we know that we can retry the call after a while. Maybe we need a special exception class with properties like CanRetry and/or RetryAfter, and possibly other properties.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.