Gmail Calendar Documents Reader Web more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Group info
Recent pages and files
Adding implicit SOAP headers to C#    
As of the most recent release of the AdSense API we stopped including the headers in the WSDL file. This presents a particular problem for C# developers because the web service code generator stops making valid source files. There is a workaround (hooray!), but its not very pretty, (boo!). 

 

I used Visual Studio 2008 for C# to work out this solution. I can't comment on this solution's compatibility with other environments. Visual Studio's web service code generator creates a class for each web service method. The class simply encapsulates all the method arguments into one object. The basic strategy of this workaround is to create a base class for all the call classes to inherit from. I'll use the AccountService.associateExistingAccount call as an example of what to do, which starts out looking like

 

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="associateExistingAccount",
                                              WrapperNamespace="http://www.google.com/api/adsense/v2",
                                              IsWrapped=true)]
public partial class associateExistingAccountRequest {

  [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.google.com/api/adsense/v2",
                                                  Order=0)]
  public string loginEmail;

  [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.google.com/api/adsense/v2",
                                                  Order=1)]
  public string postalCode;

  [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.google.com/api/adsense/v2",
                                                  Order=2)]
  public string phone;

  public associateExistingAccountRequest() { }

  public associateExistingAccountRequest(string loginEmail,
                                         string postalCode,
                                         string phone) {
    this.loginEmail = loginEmail;
    this.postalCode = postalCode;
    this.phone = phone;
  }
}


In the same namespace as the associateExistingAccountRequest, create a class called baseRequest. This is the parent class the web service method classes will inherit from. It contains the message headers.

 

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName = "createAdSenseAccount",
                                              WrapperNamespace = "http://www.google.com/api/adsense/v2",
                                              IsWrapped = true)]
public class baseRequest {

  [System.ServiceModel.MessageHeader(Namespace = "http://www.google.com/api/adsense/v2",
                                     Name = "developer_email")]
  public string developerEmail;

  [System.ServiceModel.MessageHeader(Namespace = "http://www.google.com/api/adsense/v2",
                                     Name = "developer_password")]
  public string developerPassword;

  [System.ServiceModel.MessageHeader(Namespace = "http://www.google.com/api/adsense/v2",
                                     Name = "client_id")]
  public string clientId;

  public baseRequest(string developerEmail,
                     string developerPassword,
                     string clientId) {
    this.developerEmail = developerEmail;
    this.developerPassword = developerPassword;
    this.clientId = clientId;
  }

  public baseRequest() { }
}


Note that the value of the WrapperName attribute is "createAdSenseAccount". The value of WrapperName can be any valid web service method name in the service  that you are working. The derived classes override this value, so its okay to have the associateExistingAccountRequest class inherit from a parent with a different WrapperName.

 

The next step is to modify the associateExistingAccount class to inherit from baseRequest and modify the constructor for associateExistingAccount to accept additional parameters and call the superclass constructor. The resulting class definition looks like

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="associateExistingAccount",
                                              WrapperNamespace="http://www.google.com/api/adsense/v2",
                                              IsWrapped=true)]
public partial class associateExistingAccountRequest : baseRequest {

  [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.google.com/api/adsense/v2",
                                                  Order=0)]
  public string loginEmail;

  [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.google.com/api/adsense/v2",
                                                  Order=1)]
  public string postalCode;

  [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://www.google.com/api/adsense/v2",
                                                  Order=2)]
  public string phone;

  public associateExistingAccountRequest() { }

  public associateExistingAccountRequest(string developerEmail,
                                         string developerPassword,
                                         string clientId,

                                         string loginEmail,
                                         string postalCode,
                                         string phone) : base(developerEmail,
                                                              developerPassword,
                                                              clientId)
{
    this.loginEmail = loginEmail;
    this.postalCode = postalCode;
    this.phone = phone;
  }
}


The changed sections above have been bolded.


Unfortunately this solution means that each web service method needs to be modified, which is tedious. Following this solution strictly also means that a baseRequest class needs to be added to the generated code for each web service. It may be possible to create a baseRequest class in the top-level namespace of your project and have all methods of all service inherit from it. The one problem with this is that I believe WrapperName needs to be valid method name in the service of derived class, meaning you would need to create a baseRequest class for each service. If more expert C# programmers out there see problems or possible improvements to this solution, please post on the forum about them!

Version: 
Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2010 Google