web-dev-qa-db-ja.com

SQLストアドプロシージャからSOAP webserviceを呼び出す

TSQLでWebサービスを呼び出すストアドプロシージャを構築しようとしています。これは以前にOracleで行ったことがありますが、MSSQLではそれほど簡単ではないようです。もちろん、ストアドプロシージャでこれを行わない理由はたくさんありますが、このプロシージャは毎日のバッチでのみ使用されるため、パフォーマンスはそれほど問題になりません。私がやりたいことは次のとおりです:フルネームをWebサービスに送信すると、Webサービスは名前を名前、プレフィックス、姓などに分けて返します。返された値はテーブルに書き込む必要があります。

http://www.vishalseth.com/post/2009/12/22/Call-a-webservice-from-TSQL-(Stored-Procedure)-usingで興味深い手順を見つけました-MSXML.aspx は、私が望んでいるとおりに動作するように見えましたが、呼び出しに本文を追加するとすぐに、「パラメーターが正しくありません」などのエラーが発生します。これは記事にも記載されており、簡単な解決策はないようです。リクエスト本文を送信する必要があります。

また、CLIや "Webサービスタスクエディター"、または "SSIS"で解決する方法についての記事もたくさん読みました。現在、私はMicrosoft SQLサーバー管理スタジオしか持っていません。

ちなみに私は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サーバーデータベースプロジェクト」を作成した後、ソリューションのコンテキストメニューで[Web参照の追加]を選択できません、メニューにはnuのようなオプションがあります。

7
ErikL

過去に私は次の方法を使用しましたが、最近は最善の方法ではないかもしれませんが、私にとってはうまくいきました:

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サービスを呼び出しました。

7
Mattgb

私自身のニーズのためにこのモンスターを作りました

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
Arthur

私もこの問題に遭遇しました。 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);

クレジットは元の作者に送られます。

編集:ここで呼び出していたサンプルサービスがシャットダウンしたようです。 URLが機能することを確認するには、URLを交換して別のエンドポイントに投稿する必要があります。

2
misteroptimist

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ファイルが生成され、プロジェクトに追加して、メソッド内で呼び出すことができます。

0
Mattgb