• 追加された行はこの色です。
  • 削除された行はこの色です。
#title(Webサービスを作成する)

#navi(.NETプログラミング研究)

#contents

*.NETプログラミング研究 第76号 [#b0d59a7e]

**.NET Tips [#f2591077]

**Webサービスを作成する [#y24a1d73]

今回は、XML Webサービスを作成する方法を説明します。次回はAjaxについて説明する予定ですので、その準備です。

なおWebサービスの作成法については、MSDNの「ASP.NET を使用した XML Web サービス」などで説明されています。

-[[ASP.NET を使用した XML Web サービス>http://msdn2.microsoft.com/ja-jp/library/ba0z6a33.aspx]]

***Visual StudioでWebサービスを作成する [#w2857a6e]

まずはVisual Studio 2005を使ってWebサービスを作成する方法を順を追って説明します。Visual Studio .NETでもほぼ同様です。

1.メニューの[ファイル]-[新規作成]-[Webサイト]などにより、「新しいWebサイト」ダイアログを表示します。

2.「新しいWebサイト」ダイアログで「ASP.NET Webサービス」を選択し、OKボタンをクリックします。

3.作成されたWebサイトには、「Service.asmx」と「App_Code/Service.cs」(VB.NETの場合は、「App_Code/Service.vb」)と「web.config」(VB.NETの場合のみ)が作成されています。

「Service.asmx」の中身は、次のようになっています。

VB.NETの場合

#pre{{
<%@ WebService Language="vb" CodeBehind="~/App_Code/Service.vb" Class="Service" %>
}}

C#の場合

#pre{{
<%@ WebService Language="C#" CodeBehind="~/App_Code/Service.cs" Class="Service" %>
}}

つまり、コードビハインドとなっており、本体のコードはApp_Codeディレクトリの「Service.cs」や「Service.vb」に記述します。これらのファイルの中身は、初期状態で次のようになっています。

#code(vbnet){{
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
     Inherits System.Web.Services.WebService

    <WebMethod()> _
    Public Function HelloWorld() As String
        Return "Hello World"
    End Function

End Class
}}

#code(csharp){{
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
    public Service () {

        //デザインされたコンポーネントを使用する場合、次の行をコメントを解除してください 
        //InitializeComponent(); 
    }

    [WebMethod]
    public string HelloWorld() {
        return "Hello World";
    }
    
}
}}

注意:.NET Framework 1.1以下ではWebServiceBindingAttributeとDesignerGeneratedAttributeはサポートされていません。

補足:「別のファイルにコードを書き込む」をオフにしてWebサービスを作成したときは、作成されたクラスにDesignerGeneratedAttribute属性は適用されません。

4.これですでに立派なWebサービスが作成されています。現時点では、「http://tempuri.org/」という名前空間の「Service」という名前のWebサービスに、「HelloWorld」というWebサービスメソッドが一つあるだけです。

5.これに独自のWebサービスメソッドを追加してみましょう。ここでは送信された文字列を大文字に変換して返す「ToUpper」というWebサービスメソッドを追加します。HelloWorldメソッドと同様に、Serviceクラスにプロパティメソッドを追加し、WebMethodAttribute属性を適用します。

追加するメソッドのコードは次のようなものです。

#code(vbnet){{
<WebMethod()> _
Public Function ToUpper(ByVal str As String) As String
    Return str.ToUpper()
End Function
}}

#code(csharp){{
[WebMethod]
public string ToUpper(string str)
{
    return str.ToUpper();
}
}}

6.さらにXML名前空間を独自のものに変更します。ここでは、XML名前空間を「http://dobon.net/services/」に変更します。XML名前空間はWebServiceAttribute属性のNamespaceプロパティで変更できます。Namespaceプロパティを指定しなかった場合は、「http://tempuri.org/」となります。
6.さらにXML名前空間を独自のものに変更します。ここでは、XML名前空間を「https://dobon.net/services/」に変更します。XML名前空間はWebServiceAttribute属性のNamespaceプロパティで変更できます。Namespaceプロパティを指定しなかった場合は、「http://tempuri.org/」となります。

このようにして変更された「Service.cs」や「Service.vb」は次のようになります。

#code(vbnet){{
Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://dobon.net/services/")> _
<WebService(Namespace:="https://dobon.net/services/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class Service
    Inherits System.Web.Services.WebService

    <WebMethod()> _
    Public Function HelloWorld() As String
        Return "Hello World"
    End Function

    <WebMethod()> _
    Public Function ToUpper(ByVal str As String) As String
        Return str.ToUpper()
    End Function
End Class
}}

#code(csharp){{
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://dobon.net/services/")]
[WebService(Namespace = "https://dobon.net/services/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
    public Service()
    {

        //デザインされたコンポーネントを使用する場合、次の行をコメントを解除してください 
        //InitializeComponent(); 
    }

    [WebMethod]
    public string HelloWorld()
    {
        return "Hello World";
    }

    [WebMethod]
    public string ToUpper(string str)
    {
        return str.ToUpper();
    }
}
}}

7.Webブラウザで「Service.asmx」のURLを開くと、「サービスヘルプページ」と呼ばれるHTMLページが表示されます。このページには、Webサービスに関する様々な情報が表示されます。

Visual Studioでこのページを表示させるには、F5キーや、ツールバーの「デバッグの開始」ボタンを押してデバッグを開始するか、ソリューションエクスプローラで「Service.asmx」を右クリックして、コンテキストメニューから「ブラウザで表示」を選択します。

サービスヘルプページでは、サポートされているWebサービスメソッドの一覧や、それぞれのメソッドの使用可能なプロトコル別の要求とその反応の例を見ることができます。さらに、送信する値を入力して、HTTP POSTを使用したテストを行うこともできます。

8.このように作成されたWebサービスは、SOAPに対応しています。このWebサービスのWSDLは、次のようなURLで取得できます。

http://localhost/Service/Service.asmx?WSDL

つまり、ASMXのURLの末尾に「?WSDL」を付加したものとなります。このURLへのリンクは、サービスヘルプページの「サービスの説明」の箇所にあります。

***Visual Studioを使わないでWebサービスを作成する [#v24b41ed]

Visual Studioを使わない場合も、上記で紹介したようなファイルを自分で用意すれば、全く問題ありません。

前と全く同じでは面白くありませんので、コードビハインドとしないで、ASMXファイルにコードも書いてしまう例を示します。以下の内容を拡張子が".asmx"のテキストファイルとして保存してください。

#code(vbnet){{
<%@ WebService Language="VB" Class="WebService" %>

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols

<WebService(Namespace:="http://dobon.net/services/")> _
<WebService(Namespace:="https://dobon.net/services/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
Public Class WebService
    Inherits System.Web.Services.WebService
    
    <WebMethod()> _
    Public Function ToUpper(ByVal str As String) As String
        Return str.ToUpper()
    End Function
End Class
}}

#code(csharp){{
<%@ WebService Language="C#" Class="WebService" %>

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://dobon.net/services/")]
[WebService(Namespace = "https://dobon.net/services/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
    [WebMethod]
    public string ToUpper(string str)
    {
        return str.ToUpper();
    }
}
}}

基本的な事柄の説明は以上です。ここからは上記で示したコードに登場した属性などについて、簡単に説明します。

***WebServiceAttribute属性 [#re44d788]

Webサービスを実装したクラスには、WebServiceAttribute属性を適用します。

WebServiceAttributeのNamespaceプロパティには、XML名前空間を指定します。省略した場合は、「http://tempuri.org/」となります。XML名前空間が「http://tempuri.org/」のままだと、サービスヘルプページで詳しい説明と共に、名前空間を変更するように勧められます。

WebServiceAttribute.Nameプロパティには、Webサービスの名前を指定します。省略すると、クラスの名前と同じになります。

WebServiceAttribute.Descriptionプロパティには、Webサービスの説明を指定することができます。

***WebServiceBindingAttribute属性 [#o5a46942]

Visual Studio 2005からは、始めに作成されるWebサービスクラスにWebServiceBindingAttribute属性が適用されます。WebServiceBindingAttributeのConformsToプロパティにWsiProfiles.BasicProfile1_1を指定することにより、WebサービスがWSI Basic Profileバージョン 1.1に準拠していることを示します。

-[[ASP.NET 2.0 を使用した WS-I Basic Profile 準拠 Web サービスの構築>http://msdn2.microsoft.com/ja-jp/library/ms230196.aspx]]

***WebMethodAttribute属性 [#oe2e4ba6]

XML Webサービスメソッドとするメソッドは、パブリックとして、WebMethodAttribute属性を適用します。

Descriptionプロパティには、メソッドの説明を指定します。

MessageNameプロパティには、Webサービスメソッドに使用される名前を指定します。このプロパティを使って、Webサービスクラスに同じメソッド名の複数のオーバーロードが存在する時に、メソッドの名前を変えることなく、Webサービスメソッドの名前がダブることを防ぐことができます。

''キャッシュを有効にする''

WebMethodAttribute.CacheDurationプロパティを使用することにより、応答のキャッシュを有効にできます。CacheDurationプロパティには、応答をキャッシュ内に保持する秒数を指定します。キャッシュの保持期間中は、要求が同じならば、同じ結果を返します。

MSDNには、キャッシュ機能を使う際の注意事項が幾つか示されています。まず、キャッシュを有効にすると、要求と応答のデータはメモリに保存されるため、要求や応答のデータが巨大であったり、要求の変更幅が大きい場合は、注意が必要です。また、HTTP POSTでは、通常、キャッシュは行われません。.NET Framework 2.0のサービスヘルプページのテストでは、通常、HTTP POSTが使われているため、キャッシュの効果は確認できません。

補足:サービスヘルプページのテストでHTTP GETが使われるようにするには、Windowsディレクトリの「Microsoft.NET」ディレクトリ以下にある「CONFIG」ディレクトリ内の「DefaultWsdlHelpGenerator.aspx」ファイルをエディタで開き、

 bool showPost = true;

を

 bool showPost = false;

に変更します。

さらに、"Cache-Control"が"no-cache"となっているHTTPヘッダが見つかった場合はキャッシュは無効となります。

''セッション状態を保存する''

Webサービスでも、WebService.Sessionプロパティを使ってセッション状態の保存と取得を行うことができます。ただし、WebMethodAttribute.EnableSessionプロパティをtrueとしたメソッドでしかセッションは使用できません。

これとは別に、アプリケーション状態の保存と取得を行うWebService.Applicationプロパティも使用できます。これは、EnableSessionプロパティに関係なく、使用できます。

***HTTP GETを有効にする [#jf6587a8]

デフォルトでは、作成されたWebサービスは、HTTP SOAPと、要求元がローカルコンピュータのHTTP POSTのみサポートしています(.NET Framework 1.0では、HTTP GETとPOSTもサポートされています)。

HTTP GETやPOSTをサポートするには、Machine.configまたはWeb.configファイルに<protocols>の<add>要素を追加します。

#pre{{
<configuration>
  <system.web>
    <webServices>
      <protocols>
        <add name="HttpPost"/>
        <add name="HttpGet"/>
      </protocols>
    </webServices>
  </system.web>
</configuration>
}}

逆にプロトコルのサポートを無効にするには、<remove>要素を使用します。

add要素とremove要素のname属性には次のようなオプションがあります。

name属性,説明
HttpSoap,HTTP SOAPのサポートを制御する。デフォルトで有効。
HttpGet,HTTP GETのサポートを制御する。.NET Framework 1.1以上ではデフォルトで無効。
HttpPost,HTTP POSTのサポートを制御する。.NET Framework 1.1以上ではデフォルトで無効。
HttpPostLocalhost,要求元がローカルコンピュータのHTTP POSTのサポートを制御する。デフォルトで有効。
Documentation,サービスヘルプページを表示するか。デフォルトで有効。
|name属性|説明|h
|HttpSoap|HTTP SOAPのサポートを制御する。デフォルトで有効。|
|HttpGet|HTTP GETのサポートを制御する。.NET Framework 1.1以上ではデフォルトで無効。|
|HttpPost|HTTP POSTのサポートを制御する。.NET Framework 1.1以上ではデフォルトで無効。|
|HttpPostLocalhost|要求元がローカルコンピュータのHTTP POSTのサポートを制御する。デフォルトで有効。|
|Documentation|サービスヘルプページを表示するか。デフォルトで有効。|

このようにしてHTTP GETを有効にしたWebサービスにアクセスするには、ASMXファイルのURLの後に「/(メソッド名)」を付けたものを要求先の基本的なURLとして、この後に「?」とクエリーパラメータを続けます。クエリーパラメータは「(パラメータ名)=(値)」の形式で、複数のパラメータは「&」で区切ります。パラメータ名と値は必要に応じてURLエンコードします。

例えば、Service.asmxのToUpperメソッドをパラメータ値を「abcde」として呼び出すには、次のようにします。

http://localhost/Service/Service.asmx/ToUpper?str=abcde

HTTP POSTの場合も同様に、ASMXファイルのURLの後に「/(メソッド名)」を付けたものを要求先のURLとして、パラメータを送信します。

***サービスヘルプページが表示されないようにする [#ie8a9e9f]

ASMXファイルをWebブラウザで開くとサービスヘルプページが表示されますが、これを表示されないようにするには、上記と同じように、<protocols>の<remove>要素をMachine.configまたはWeb.configファイルに追加します。

#pre{{
<configuration>
  <system.web>
    <webServices>
      <protocols>
        <remove name="Documentation" />
      </protocols>
    </webServices>
  </system.web>
</configuration>
}}

しかしこれでは、WSDLの生成も無効になります。WSDLを有効にしたままサービスヘルプページの表示を無効にするには、<wsdlHelpGenerator>要素を使って、ASMXファイルに直接アクセスした時に別のページが表示されるようにします。

次の例では、デフォルトのサービスヘルプページの代わりにblank.htmlを表示するようにしています。

#pre{{
<configuration>
  <system.web>
    <webServices>
      <wsdlHelpGenerator href="blank.html"/>
    </webServices>
  </system.web>
</configuration>
}}

***複数のデータを返すWebサービスメソッドを作成する [#w33357c9]

複数のデータを返すWebサービスメソッドが必要な場合は、それらのデータを格納できるクラスや構造体を作成して、メソッドの戻り値の型として使用するようにします。

***例外をスローする [#g6be3e7b]

Webサービスメソッドから例外をスローする場合は、SoapExceptionをスローし、Webサービスメソッドを呼び出したクライアントでも、SoapExceptionをキャッチします。WebサービスメソッドからSoapException以外の例外がスローされた場合は、SoapExceptionに変換されて、クライアントにスローされます。

SoapExceptionでは、次のようなプロパティを設定できます。Messageプロパティには、例外の説明をするメッセージを指定します。Codeプロパティには、SOAP違反コードの種類を指定します。クライアントの呼び出し方に問題があれば、SoapException.ClientFaultCodeを指定します。SoapException以外の例外がスローされた場合は、CodeにSoapException.ServerFaultCodeが設定されます。Actorプロパティには、通常、WebサービスメソッドのURLを指定します。Detailプロパティには、エラーの詳細を設定します。

Webサービスメソッドから例外をスローする例を以下に示します。

#code(vbnet){{
<WebMethod()> _
Public Function ToUpper(ByVal str As String) As String
    If str.Length = 0 Then
        Throw New SoapException("パラメータが空です。", _
            SoapException.ClientFaultCode, _
            Context.Request.Url.AbsoluteUri)
    End If

    Return str.ToUpper()
End Function
}}

#code(csharp){{
[WebMethod]
public string ToUpper(string str)
{
    if (str.Length == 0)
    {
        throw new SoapException("パラメータが空です。",
            SoapException.ClientFaultCode,
            Context.Request.Url.AbsoluteUri);
    }
    
    return str.ToUpper();
}
}}

上記の例では、Message、Code、Actorプロパティを設定しています。Detailも設定してスローする方法は、MSDNの「XML Web サービスでの例外の処理およびスロー」等をご覧ください。

-[[XML Web サービスでの例外の処理およびスロー>http://msdn2.microsoft.com/ja-jp/library/ds492xtk.aspx]]

**コメント [#aa037ea7]
#comment

//これより下は編集しないでください
#pageinfo([[:Category/.NET]],2006-12-31 (日) 06:00:00,DOBON!,2010-03-23 (火) 03:26:21,DOBON!)
#pageinfo([[:Category/.NET]],2006-12-31 (日) 06:00:00,DOBON!,2013-03-22 (金) 19:11:46,DOBON!)

[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]