我正在尝试通过SSIS获取BingAds数据以存储在我们的会计系统中。我已经为https://api.sandbox.bingads.microsoft.com/Api/Advertiser/v8/CampaignManagement/CampaignManagementService.svc?wsdl添加了服务参考以进行测试。
我直接从http://msdn.microsoft.com/en-us/library/adcenter-campaign-management-csharp-samples-get-campaigns.aspx复制了GetCampaigns代码,并略有修改,因为这不是控制台应用程序。
当我运行脚本组件时,我收到以下消息:
Message
Could not find default endpoint element that references contract
'BingAds.CampaignManagementService.ICampaignManagementService' in the ServiceModel
client configuration section. This might be because no configuration file was
found for your application, or because no endpoint element matching this contract
could be found in the client element.
我的app.config看起来应该包含所需的一切。我错过了什么吗?
我的app.config如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_ICampaignManagementService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://api.sandbox.bingads.microsoft.com/Api/Advertiser/V8/CampaignManagement/CampaignManagementService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ICampaignManagementService"
contract="BingAds.CampaignManagementService.ICampaignManagementService"
name="BasicHttpBinding_ICampaignManagementService" />
</client>
</system.serviceModel>
</configuration>
我的脚本组件代码如下:
#region Namespaces
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.IO;
using System.Xml;
using System.Net;
// @TODO this should be something more sane; we'll get to that
using SC_356d75396bc04171b425bdd1a48dd7b6.BingAds.CampaignManagementService;
#endregion
namespace GetCampaignsByAccount
{
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
private static CampaignManagementServiceClient service = null;
// private static StringBuilder output_messages = new StringBuilder();
private static List<string> strings = new List<string>();
// Specify your credentials.
private static string m_password = "";
private static string m_username = "";
private static string m_token = "";
// Specify the advertiser's account ID and customer ID.
private static long m_accountId = null;
private static long m_customerId = null;
// Simple example that shows how to create a campaign.
static void Main()
{
Campaign[] campaigns = null;
try
{
CampaignManagementServiceClient service = new CampaignManagementServiceClient();
campaigns = GetCampaigns(m_customerId, m_accountId);
// Print information about the campaigns.
if (campaigns.Length > 0) {
AddMessage("Account {0} contains the following campaigns", m_accountId);
foreach (Campaign campaign in campaigns) {
AddMessage("Campaign: {0}", campaign.Name);
AddMessage("ID: {0}", campaign.Id);
// AddMessage("Status: {0}", campaign.Status);
AddMessage("Time zone: {0}", campaign.TimeZone);
// AddMessage("Budget type: {0}", campaign.BudgetType);
if (BudgetLimitType.MonthlyBudgetSpendUntilDepleted == campaign.BudgetType)
{
Console.WriteLine("Monthly budget: {0:C}", campaign.MonthlyBudget);
}
else
{
Console.WriteLine("Daily budget: {0:C}", campaign.DailyBudget);
}
Console.WriteLine();
}
}
else
{
AddMessage("Account {0} does not contain campaigns.", m_accountId);
}
service.Close();
}
catch (CommunicationException e)
{
AddMessage("{0}", "Communication Exception!");
AddMessage("{0}", e.Message);
AddMessage("{0}", e.StackTrace);
if (null != e.InnerException)
{
AddMessage("{0}", "Inner Exception!");
AddMessage("{0}", e.InnerException.Message);
AddMessage("{0}", e.InnerException.StackTrace);
}
if (service != null)
{
service.Abort();
}
}
catch (TimeoutException e)
{
AddMessage("{0}", "Timeout Exception!");
AddMessage("{0}", e.Message);
AddMessage("{0}", e.StackTrace);
if (service != null)
{
service.Abort();
}
}
catch (Exception e)
{
// Ignore fault exceptions that we already caught.
if (e.InnerException is FaultException)
{
;
}
else
{
AddMessage("{0}", "Other Exception!");
AddMessage("{0}", e.Message);
AddMessage("{0}", e.StackTrace);
}
if (service != null)
{
service.Abort();
}
}
}
private static void AddMessage(string format, string str)
{
string[] lines = str.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
foreach (string value in lines)
{
string longVal = String.Format(format, value);
strings.Add(longVal.Substring(0, Math.Min(longVal.Length, 8000)));
}
}
private static void AddMessage(string format, long str)
{
strings.Add(String.Format(format, str));
}
private static void AddMessage(string format, long? str)
{
strings.Add(String.Format(format, str));
}
static Campaign[] GetCampaigns(long customerId, long accountId)
{
GetCampaignsByAccountIdRequest request = new GetCampaignsByAccountIdRequest();
GetCampaignsByAccountIdResponse response = null;
// Set the header information.
request.CustomerId = customerId.ToString();
request.CustomerAccountId = accountId.ToString();
request.DeveloperToken = m_token;
request.UserName = m_username;
request.Password = m_password;
// Set the request information.
request.AccountId = accountId;
try
{
response = service.GetCampaignsByAccountId(request);
}
catch (FaultException<AdApiFaultDetail> fault)
{
// Log this fault.
strings.Add("GetCampaignsByAccountId failed with the following faults:\n");
foreach (AdApiError error in fault.Detail.Errors)
{
if (105 == error.Code)
{ // InvalidCredentials
Console.WriteLine("The specified credentials are not valid " +
"or the account is inactive.");
}
else
{
Console.WriteLine("Error code: {0} ({1})\nMessage: {2}\nDetail: {3}\n",
error.ErrorCode, error.Code, error.Message, error.Detail);
}
}
throw new Exception("", fault);
}
catch (FaultException<ApiFaultDetail> fault)
{
// Log this fault.
Console.WriteLine("GetCampaignsByAccountId failed with the following faults:\n");
foreach (OperationError error in fault.Detail.OperationErrors)
{
switch (error.Code)
{
case 106: // UserIsNotAuthorized
Console.WriteLine("The user is not authorized to call this operation.");
break;
case 1030: // CampaignServiceAccountIdHasToBeSpecified
Console.WriteLine("The CustomerAccountId header element " +
"cannot be null or empty.");
break;
case 1102: // CampaignServiceInvalidAccountId
Console.WriteLine("The account ID is not valid");
break;
default:
Console.WriteLine("Error code: {0} ({1})\nMessage: {2}\nDetail: {3}\n",
error.ErrorCode, error.Code, error.Message, error.Details);
break;
}
}
// This is not a batch operation, so there should be no batch errors.
foreach (BatchError error in fault.Detail.BatchErrors)
{
Console.WriteLine("Unable to add extension #{0}", error.Index);
Console.WriteLine("Error code: {0} ({1})\nMessage: {2}\nDetail: {3}\n",
error.ErrorCode, error.Code, error.Message, error.Details);
}
throw new Exception("", fault);
}
return response.Campaigns;
}
/// <summary>
/// This method is called once, before rows begin to be processed in the data flow.
///
/// You can remove this method if you don't need to do anything here.
/// </summary>
public override void PreExecute()
{
base.PreExecute();
}
/// <summary>
/// This method is called after all the rows have passed through this component.
///
/// You can delete this method if you don't need to do anything here.
/// </summary>
public override void PostExecute()
{
base.PostExecute();
}
public override void CreateNewOutputRows()
{
Main();
foreach (string value in strings)
{
MessagesBuffer.AddRow();
MessagesBuffer.Message = value;
}
}
}
}
答案 0 :(得分:3)
.NET在加载配置数据时查找的配置文件是实际运行的可执行文件的配置文件;在SSIS脚本组件的项目中添加app.config
不会生成SSIS知道要查找的配置文件。根据您选择运行软件包的方式,它将查找BIDS或SQL Server或dtexec
的配置文件。
在代码中构建端点并完全绕过配置文件会更好。如果您的大多数配置选项都是默认配置,那么它甚至都不复杂,因为您只需要设置更改的属性。
此Stack Overflow问题应该告诉你如何操作:
答案 1 :(得分:0)
对于使用SSDT 2015的用户,使用调试器时.config文件的文件位置已经改变;它们现在可以在以下路径下找到:C:\ Program Files(x86)\ Microsoft Visual Studio 14.0 \ Common7 \ IDE \ Extensions \ Microsoft \ SSIS \ 140 \ Binn