【问题标题】:Calling a SOAP webservice from TSQL stored procedure从 SQL 存储过程调用 SOAP Web 服务
【发布时间】:2014-11-30 12:55:26
【问题描述】:

我正在尝试在 TSQL 中构建一个存储过程来调用 Web 服务。我以前在 Oracle 中做过,但在 MSSQL 中似乎并不那么容易。 当然有很多理由不在存储过程中执行此操作,但由于此过程仅用于每日批处理,因此性能不是太大问题。 我想做的事情如下:向webservice发送一个全名,webservice将返回一个名称,分为名字、前缀、姓氏等。返回的值需要写入一个表。

我在http://www.vishalseth.com/post/2009/12/22/Call-a-webservice-from-TSQL-(Stored-Procedure)-using-MSXML.aspx 发现了一个有趣的过程,它似乎完全符合我的要求,但是一旦你在调用中添加了一个主体,我就会遇到像“参数不正确”这样的错误。文章中也说明了这一点,显然没有简单的解决方案。我肯定需要发送请求正文。

我还阅读了很多关于使用 CLI 或“Web 服务任务编辑器”或“SSIS”位解决它的文章,但我找不到任何关于从哪里开始的教程。目前我只有 Microsoft SQL Server Management Studio。

顺便说一句,我使用的是 SQL Server 2012。

关于我应该朝哪个方向发展有什么想法吗?

我已经找到了这个描述,看起来很干净:http://www.databasejournal.com/features/mssql/article.php/3821271/Calling-a-Web-Service-from-within-SQL-Server.htm 但是,在安装 Visual Studio 2012 并创建“SQL Server 数据库项目”后,我无法在解决方案上下文中选择“添加 Web 引用”菜单,菜单里只有nu个这样的选项。

【问题讨论】:

  • 您找到解决方案了吗?我目前处于完全相同的情况

标签: sql-server web-services tsql sql-server-2012 clr


【解决方案1】:

过去我使用过以下方法,现在它可能不是最好的方法,但它对我来说很成功:

DECLARE @obj int,
        @url VarChar(MAX),
        @response VarChar(MAX),
        @requestHeader VarChar(MAX),
        @requestBody VarChar(MAX)

SET @url = 'http://....'

SET @requestBody = '<soapenv:Envelope>
                     <soapenv:Header/>
                      <soapenv:Body>
                       ...
                      </soapenv:Body>
                     </soapenv:Envelope>'

EXEC sp_OACreate 'MSXML2.ServerXMLHttp', @obj OUT
EXEC sp_OAMethod @obj, 'Open', NULL, 'GET', @url, false
EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'Content-Type', 'text/xml;charset=UTF-8'
EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'SOAPAction', 'POST'
EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'Content-Length', LEN(@requestBody)
EXEC sp_OAMethod @obj, 'send', NULL, @requestBody
EXEC sp_OAGetProperty @obj, 'responseText', @response OUT


SELECT @response [RESPONSE]

EXEC sp_OADestroy @obj

我用它来调用一个 web 服务,该服务生成一个报告并在方法中通过电子邮件发送它。

【讨论】:

  • 这与我引用的过程中的代码相同。这段代码的问题是你不能用它发送内容主体(也就是实际的肥皂消息)。这种方法似乎只适用于 REST web 服务。
  • 我添加了一些修改来展示如何指定请求正文和帖子。
  • 抱歉刚刚查看了您的链接,他们给出了相同的答案,一定是星期一!
【解决方案2】:

根据自己的需要制作这个怪物

CREATE PROCEDURE [dbo].[RequestHttpWebService]
@Url varchar(1024),
@HttpMethod varchar(10),
@ParamsValues varchar(1024),    -- param1=value&param2=value
@SoapAction varchar(1024) = null
AS
BEGIN
SET NOCOUNT ON;

--set @Url = 'http://localhost/service.asmx'
--set @HttpMethod = 'soap'
--set @ParamsValues = 'login=tr2280&password=Qwe12345&domain=webtech.development'
--set @SoapAction = 'Authenticate'


if @HttpMethod in ('get','GET') and len(@ParamsValues) > 0
begin
    set @Url = @Url + '?' + @ParamsValues
end

declare @obj int
    ,@response varchar(8000)
    ,@responseXml xml
    ,@status varchar(50)
    ,@statusText varchar(1024)
    ,@method varchar(10) = (case when @HttpMethod in ('soap','SOAP') then 'POST' else @HttpMethod end)

exec sp_OACreate 'MSXML2.ServerXMLHttp', @obj out
exec sp_OAMethod @obj, 'Open', null, @method, @Url, false

if @HttpMethod in ('get','GET')
begin
    exec sp_OAMethod @obj, 'send'
end
else if @HttpMethod in ('post','POST')
begin
    exec sp_OAMethod @obj, 'setRequestHeader', null, 'Content-Type', 'application/x-www-form-urlencoded'
    exec sp_OAMethod @obj, 'send', null, @ParamsValues
end
else if @HttpMethod in ('soap','SOAP')
begin
    if @SoapAction is null
        raiserror('@SoapAction is null', 10, 1)

    declare @host varchar(1024) = @Url
    if @host like 'http://%'
        set @host = right(@host, len(@host) - 7)
    else if @host like 'https://%'
        set @host = right(@host, len(@host) - 8)

    if charindex(':', @host) > 0 and charindex(':', @host) < charindex('/', @host)
        set @host = left(@host, charindex(':', @host) - 1)
    else 
        set @host = left(@host, charindex('/', @host) - 1)

    declare @envelope varchar(8000) = '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><{action} xmlns="http://tempuri.org/">{params}</{action}></soap:Body></soap:Envelope>'
    declare @params varchar(8000) = '' 

    WHILE LEN(@ParamsValues) > 0
    BEGIN
        declare @param varchar(256),
                @value varchar(256)

        IF charindex('&', @ParamsValues) > 0
        BEGIN

            SET @param = left(@ParamsValues, charindex('&', @ParamsValues) - 1)
            set @value = RIGHT(@param, len(@param) - charindex('=', @param))
            set @param = left(@param, charindex('=', @param) - 1)
            set @params = @params + '<' + @param + '>' + @value + '</'+ @param + '>'
            SET @ParamsValues = right(@ParamsValues, LEN(@ParamsValues) - LEN(@param + '=' + @value + '&'))
        END
        ELSE
        BEGIN
            set @value = RIGHT(@ParamsValues, len(@ParamsValues) - charindex('=', @ParamsValues))
            set @param = left(@ParamsValues, charindex('=', @ParamsValues) - 1)

            set @params = @params + '<' + @param + '>' + @value + '</'+ @param + '>'
            SET @ParamsValues = NULL
        END
    END

    set @envelope = replace(@envelope, '{action}', @SoapAction)
    set @envelope = replace(@envelope, '{params}', @params)

    set @SoapAction = 'http://tempuri.org/' + @SoapAction

    print @host
    print @SoapAction
    print @envelope

    exec sp_OAMethod @obj, 'setRequestHeader', null, 'Content-Type', 'text/xml; charset=utf-8'
    exec sp_OAMethod @obj, 'setRequestHeader', null, 'Host', @host
    exec sp_OAMethod @obj, 'setRequestHeader', null, 'SOAPAction', @SoapAction
    exec sp_OAMethod @obj, 'send', null, @envelope
end

exec sp_OAGetProperty @obj, 'responseText', @response out
exec sp_OADestroy @obj

select @status as [status], @statusText as [statusText], @response as [response]
END
GO

编辑:格式化

【讨论】:

    【解决方案3】:

    我也遇到了这个问题。以下是使用 T-SQL 中的参数执行 HTTP Post 的正确方法:

    DECLARE @authHeader NVARCHAR(64);
    DECLARE @contentType NVARCHAR(64);
    DECLARE @postData NVARCHAR(2000);
    DECLARE @responseText NVARCHAR(2000);
    DECLARE @responseXML NVARCHAR(2000);
    DECLARE @ret INT;
    DECLARE @status NVARCHAR(32);
    DECLARE @statusText NVARCHAR(32);
    DECLARE @token INT;
    DECLARE @url NVARCHAR(256);
    
    SET @authHeader = 'BASIC 0123456789ABCDEF0123456789ABCDEF';
    SET @contentType = 'application/x-www-form-urlencoded';
    SET @postData = 'value1=Hello&value2=World'
    SET @url = 'https://requestb.in/16xdq1p1'
    
    -- Open the connection.
    EXEC @ret = sp_OACreate 'MSXML2.ServerXMLHTTP', @token OUT;
    IF @ret <> 0 RAISERROR('Unable to open HTTP connection.', 10, 1);
    
    -- Send the request.
    EXEC @ret = sp_OAMethod @token, 'open', NULL, 'POST', @url, 'false';
    EXEC @ret = sp_OAMethod @token, 'setRequestHeader', NULL, 'Authentication', @authHeader;
    EXEC @ret = sp_OAMethod @token, 'setRequestHeader', NULL, 'Content-type', @contentType;
    EXEC @ret = sp_OAMethod @token, 'send', NULL, @postData;
    
    -- Handle the response.
    EXEC @ret = sp_OAGetProperty @token, 'status', @status OUT;
    EXEC @ret = sp_OAGetProperty @token, 'statusText', @statusText OUT;
    EXEC @ret = sp_OAGetProperty @token, 'responseText', @responseText OUT;
    
    -- Show the response.
    PRINT 'Status: ' + @status + ' (' + @statusText + ')';
    PRINT 'Response text: ' + @responseText;
    
    -- Close the connection.
    EXEC @ret = sp_OADestroy @token;
    IF @ret <> 0 RAISERROR('Unable to close HTTP connection.', 10, 1);
    

    Credit goes to the original author.

    编辑:我在这里调用的示例服务似乎已关闭。您需要换出 URL 并发布到不同的端点才能看到它的工作。

    【讨论】:

      【解决方案4】:

      在 Visual Studio 中维护 SQL Server 项目时,不能以通常的方式添加 Web 引用。但是,您可以使用 WSDL 实用程序来创建 Web 界面并将其添加到您的解决方案中。随后,您将能够在 CLR 存储过程中访问所需的 Web 方法。

      WSDL.exe 实用程序可以在已安装的 Microsoft SDK 中找到,我使用 Windows 7 版本运行我的实用程序,但简单搜索您的 HDD 即可找到您的位置,该位置安装在以下目录中:C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin

      运行 WSDL.exe 实用程序时使用的命令是:

      WSDL.exe /o:(name of Visual Studio Class file) /n:(name of namespace) (address of webservice)
      

      例如:

      WSDL.exe /o:Weather.cs /n:Weather.Test http://wsf.cdyne.com/WeatherWS/Weather.asmx
      

      这将在此实例中生成一个Weather.cs 文件,然后您可以将其添加到您的项目中并在您的方法中调用。

      【讨论】:

      • 听起来很有趣,你能告诉我在哪里可以找到 WSDL 实用程序吗?是 VS 还是 microsoft sql server management studio 中的东西?
      • @ErikL 我昨天放了一天假,学习如何成为一名咖啡师(以防万一:))我已经更新了我的答案,以展示你如何调用 wsdl.exe
      猜你喜欢
      • 1970-01-01
      • 2013-08-31
      • 2010-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多