【问题标题】:SSIS Script Task Web Service errorSSIS 脚本任务 Web 服务错误
【发布时间】:2024-01-18 07:12:01
【问题描述】:

我在 SSIS 包中有一个脚本任务来调用 Web 服务 (WCF)。我要做的就是向 Web 服务发送一个请求,然后我会收到一个结果(1 或 0)。但是,如果失败并显示以下错误消息。当我将代码放在窗口应用程序表单中时,它可以工作。

我几乎从一个窗口应用程序中复制了代码,并试图让它在 SSIS 中工作。不幸的是,我不知道 Web 服务是如何工作的,也不知道从哪里开始寻找解决方案。我需要做任何绑定吗?有一个应用程序配置文件,但它说 CustomBinding。再次,我为我缺乏知识道歉,我完全一无所知。任何帮助,将不胜感激。谢谢!

在 System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) 在 System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(对象 obj,对象 [] 参数,对象 [] 参数) 在 System.Reflection.RuntimeMethodInfo.Invoke(Object obj,BindingFlags invokeAttr,Binder binder,Object[] 参数,CultureInfo 文化) 在 System.RuntimeType.InvokeMember(字符串名称、BindingFlags bindingFlags、Binder binder、Object 目标、Object[] providedArgs、ParameterModifier[] 修饰符、CultureInfo 文化、String[] namedParams) 在 Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTATaskScriptingEngine.ExecuteScript()

以下是我在脚本任务中的代码。

public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{

    public void Main()
    {
        // TODO: Add your code here                

        ServiceReference.SendMessageClient svc = new ServiceReference.SendMessageClient();


        MessageCredentialsHeader MessageSecurityHeader = new MessageCredentialsHeader("user", "pw");
        try
        {
            using (System.ServiceModel.OperationContextScope contextScope = new System.ServiceModel.OperationContextScope(svc.InnerChannel))
            {
                System.ServiceModel.OperationContext.Current.OutgoingMessageHeaders.Add(MessageSecurityHeader);

                MessageBox.Show(svc.SendMessage("111", "222", "SSIS test").Result.ToString());

            }
        }
        catch (Exception ex)
        {
            string s = ex.Message;
        }

        Dts.TaskResult = (int)ScriptResults.Success;
    }


    enum ScriptResults
    {
        Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
        Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
    };
    #endregion
    public class MessageCredentialsHeader: System.ServiceModel.Channels.MessageHeader
    {

        public string Username { get; set; }
        public string Password { get; set; }

        public MessageCredentialsHeader(string username, string password)
        {
            Username = username;
            Password = password;
        }

        public override string Name
        {
            get { return "Security"; }
        }

        public override string Namespace
        {
            get { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; }
        }

        public override bool MustUnderstand
        {
            get
            {
                return true;
            }
        }

        protected override void OnWriteStartHeader(XmlDictionaryWriter writer, System.ServiceModel.Channels.MessageVersion messageVersion)
        {
            base.OnWriteStartHeader(writer, messageVersion);
            string prefix = writer.LookupPrefix("http://schemas.xmlsoap.org/soap/envelope/");
            writer.WriteAttributeString(prefix + ":actor", "http://example.org/ws/webservicesecurity");
        }

        protected override void OnWriteHeaderContents(System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Channels.MessageVersion messageVersion)
        {
            writer.WriteStartElement("UsernameToken", Namespace);
            writer.WriteStartElement("Username", Namespace);
            writer.WriteRaw(Username);
            writer.WriteEndElement();
            writer.WriteStartElement("Password", Namespace);
            writer.WriteAttributeString("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
            writer.WriteRaw(Password);
            writer.WriteEndElement();
            writer.WriteEndElement();
        }
    }

}

【问题讨论】:

    标签: c# web-services wcf ssis


    【解决方案1】:

    您可以将读写参数传递给您的脚本任务 - 例如安全响应。您需要首先在包中创建一个变量,其值为 xml 响应。然后,在您的脚本代码中,您可以添加这样的代码,这可能会引导您朝着正确的方向前进:

     object nativeObject = Dts.Connections["Webservice"].AcquireConnection(null);
     HttpClientConnection conn = new HttpClientConnection(nativeObject);
    
     Service ws = new Service(conn.ServerURL);
     securityRequest req = new securityRequest();
     req.username = "****";
     req.password = "****";
    
     securityResponse response = ws.GetSecurityResp(req);
    
     System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(response.GetType());
     StringWriterWithEncoding responseToXml = new StringWriterWithEncoding(new StringBuilder(), Encoding.UTF8);
    
     x.Serialize(responseToXml, response);
     Dts.Variables["User::securityResponse"].Value = responseToXml.ToString();
     Dts.TaskResult = (int)ScriptResults.Success;
    

    然后,您将需要使用读取此 XML 并将其放置到记录集目标或表的 XML 源创建另一个数据流任务。

    【讨论】:

      【解决方案2】:

      事实证明,SSIS 无法访问脚本任务中的应用配置文件。这就是为什么我必须用代码编写绑定。我刚刚添加了以下绑定代码,它就可以工作了。

      HttpsTransportBindingElement httpsTransport = new HttpsTransportBindingElement();
      
              httpsTransport.ManualAddressing = false;
              httpsTransport.MaxBufferPoolSize = 524288;
              httpsTransport.MaxReceivedMessageSize = 65536;
              httpsTransport.AllowCookies = false;
              httpsTransport.AuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;
              httpsTransport.BypassProxyOnLocal = false;
              httpsTransport.DecompressionEnabled = true;
              httpsTransport.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
              httpsTransport.KeepAliveEnabled = true;
              httpsTransport.MaxBufferSize = 65536;
              httpsTransport.ProxyAuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;
              httpsTransport.Realm = "";
              httpsTransport.TransferMode = TransferMode.Buffered;
              httpsTransport.UnsafeConnectionNtlmAuthentication = false;
              httpsTransport.UseDefaultWebProxy = true;
              httpsTransport.RequireClientCertificate = false;
      
              TextMessageEncodingBindingElement encoding = new TextMessageEncodingBindingElement();
              encoding.MessageVersion = MessageVersion.Soap11;
              encoding.WriteEncoding = Encoding.UTF8;
              encoding.MaxReadPoolSize = 64;
              encoding.MaxWritePoolSize = 16;
              encoding.ReaderQuotas.MaxDepth = 32;
              encoding.ReaderQuotas.MaxStringContentLength = 8192;
              encoding.ReaderQuotas.MaxArrayLength = 16384;
              encoding.ReaderQuotas.MaxBytesPerRead = 4096;
              encoding.ReaderQuotas.MaxNameTableCharCount = 16384;
      
              CustomBinding binding = new CustomBinding();
              binding.Name = "SendMessage";
              binding.Elements.Add(encoding);
              binding.Elements.Add(httpsTransport);
      
              EndpointAddress endPoint = new EndpointAddress("https://example.org/SendMessage");
      
              ServiceReference.SendMessageClient svc = new ServiceReference.SendMessageClient (binding, endPoint);
      

      【讨论】: