single.php

IISでホストするREST Webサービス(WCF サービス)

IISで提供できるREST Web APIを作成しようとして、試行錯誤していたら結構面倒だったので備忘録的な記事。

基本は、WCF(Windows Communication Foundation)で作成するのがお約束みたいです。
WebサイトのURLに対してGETメソッドでアクセスして、URL上のパラメタを判断してJSON形式で値を戻すREST APIを作成することを目標にします。

プロジェクトを作成しないと始まらないので以下の手順で作成(VS2010以降メニューの名前などが多少異なりますが同じ手順で作成できます)

  1. Visual Studioで[ファイル|新規作成|プロジェクト]で[ASP.NET 空のWebアプリケーション]を作成
    フレームワークは[.NET Framework 4]を選択(Client Profileではありません)vs-2010-new-project-empty-website-fw4
  2. ソリューションに、新しいプロジェクトに[WCF サービス ライブラリ]を追加する。vs-2010-add-project-wcf-service-lib-fw4
  3. 一旦ビルドする。
  4. 各プロジェクトの参照設定に、Webサイトには[System.ServiceModel]、[System.ServiceModel.Activation]、[System.ServiceModel.Web]と[プロジェクト]の[SampleWCFLib]を追加して、WCFサービスには、[System.ServiceModel]、[System.ServiceModel.Web]を追加する。vs-2010-browse-settings-wfcservice-app
  5. [SampleWCFLib]プロジェクトの[IService1.cs]と[Service1.cs]を変更します。(例:IService1.cs → IWfcService.cs、Service1.cs → WfcService.cs)
  6. 変更する場合に、すべての参照をすべて変更する画面は[はい]を選択します。
  7. IWfcService.csとWfcService.csの内容を開きます。
    テンプレの状態で、[GetData]メソッドと[GetDataUsingDataContract]メソッドが記載されているので、今回はバッサリ削除します。IWfcService.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace SampleWCFLib
    {
        // メモ: [リファクター] メニューの [名前の変更] コマンドを使用すると、コードと config ファイルの両方で同時にインターフェイス名 "IService1" を変更できます。
        [ServiceContract]
        public interface IWfcService
        {
    /*
            [OperationContract]
            string GetData(int value);
    
            [OperationContract]
            CompositeType GetDataUsingDataContract(CompositeType composite);
    */
            // TODO: ここにサービス操作を追加します。
        }
    
        // サービス操作に複合型を追加するには、以下のサンプルに示すようにデータ コントラクトを使用します。
    /*
        [DataContract]
        public class CompositeType
        {
            bool boolValue = true;
            string stringValue = "Hello ";
    
            [DataMember]
            public bool BoolValue
            {
                get { return boolValue; }
                set { boolValue = value; }
            }
    
            [DataMember]
            public string StringValue
            {
                get { return stringValue; }
                set { stringValue = value; }
            }
        }
    */
    }
    

    WfcService.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace SampleWCFLib
    {
        // メモ: [リファクター] メニューの [名前の変更] コマンドを使用すると、コードと config ファイルの両方で同時にクラス名 "Service1" を変更できます。
        public class WfcService : IWfcService
        {
    /*
            public string GetData(int value)
            {
                return string.Format("You entered: {0}", value);
            }
    
            public CompositeType GetDataUsingDataContract(CompositeType composite)
            {
                if (composite == null)
                {
                    throw new ArgumentNullException("composite");
                }
                if (composite.BoolValue)
                {
                    composite.StringValue += "Suffix";
                }
                return composite;
            }
    */ 
        }
    }
    
    
  8. IWCFService.csを編集して、メソッドと戻り値JSON用の構造体を定義します。
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    
    namespace SampleWCFLib
    {
        // メモ: [リファクター] メニューの [名前の変更] コマンドを使用すると、コードと config ファイルの両方で同時にインターフェイス名 "IService1" を変更できます。
        [ServiceContract]
        public interface IWfcService
        {
            // TODO: ここにサービス操作を追加します。
            [OperationContract]
            DataList GetData(string name);
        }
    
        // サービス操作に複合型を追加するには、以下のサンプルに示すようにデータ コントラクトを使用します。
        [DataContract(Namespace = "", Name = "DataList")]
        public class DataList
        {
            [DataMember]
            public int Id;
            [DataMember]
            public string Name;
            [DataMember]
            public List<DataItem> data_collection;
    
            [DataContract]
            public class DataItem
            {
                [DataMember]
                public string Id;
                [DataMember]
                public string Name;
            }
        }
    
    }
    
  9. WCFService.csを編集して、メソッドを実装します。
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.ServiceModel.Web;
    using System.ServiceModel.Activation;
    using System.Text;
    using System.Runtime.Serialization.Json;
    
    namespace SampleWCFLib
    {
        // メモ: [リファクター] メニューの [名前の変更] コマンドを使用すると、コードと config ファイルの両方で同時にクラス名 "Service1" を変更できます。
        public class WfcService : IWfcService
        {
            [WebGet(UriTemplate = "api/v1/data/{name}", ResponseFormat = WebMessageFormat.Json)]
            public DataList GetData(string name)
            {
                int count = 0;
                DataList sl = new DataList();
                sl.data_collection = new System.Collections.Generic.List<DataList.StampItem>();
                for (int nLoop = 0; nLoop < 2; nLoop++)
                {
                    DataList.DataItem item = new DataList.DataItem();
                    item.Name = name;
                    item.Id = count.ToString();
    
                    sl.data_collection.Add(item);
                    count++;
                }
                sl.Id = count;
                sl.Name = name;
                return sl;
            }
        }
    }
    
  10. [SampleWCFApp]の[Web.config]を編集して、WCFがASP環境で動作する[aspNetCompatibilityEnabled]属性を追加します。
    <?xml version="1.0" encoding="utf-8"?>
    <!-- ASP.NET アプリケーションの構成方法の詳細については、 http://go.microsoft.com/fwlink/?LinkId=169433 を参照してください -->
    <configuration>
        <system.web>
            <compilation debug="true" targetFramework="4.0" />
        </system.web>
        <system.serviceModel>
          <!-- WCFがASP.NET環境で動くように -->
          <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
        </system.serviceModel>
    </configuration>
    
  11. [SampleWCFApp]に[Global.asax]を追加して、ASPに要求されたURLでWCFのサービスにアクセスできるようにします。
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.Web.SessionState;
    
    using System.ServiceModel;
    using System.ServiceModel.Activation;
    using System.ServiceModel.Web;
    
    namespace DsServiceApp
    {
        public class Global : System.Web.HttpApplication
        {
            protected void Application_Start(object sender, EventArgs e)
            {
                //WCFServiceというURLでアクセスSampleWCFLib.WfcServiceクラスで実装してるサービスにアクセスできるようにする。
                System.Web.Routing.RouteTable.Routes.Add(new ServiceRoute("WCFService", new WebServiceHostFactory(), typeof(SampleWCFLib.WfcService)));
            }
            protected void Session_Start(object sender, EventArgs e)
            {
            }
            protected void Application_BeginRequest(object sender, EventArgs e)
            {
            }
            protected void Application_AuthenticateRequest(object sender, EventArgs e)
            {
            }
            protected void Application_Error(object sender, EventArgs e)
            {
            }
            protected void Session_End(object sender, EventArgs e)
            {
            }
            protected void Application_End(object sender, EventArgs e)
            {
            }
        }
    }
    
  12. ビルドを行い、デバッグ実行を行います。開発用のWebサーバーが起動しブラウザが表示されます。
  13. アドレスに、http://localhost/WFCService/api/v1/data/sample と入力します。
  14. ASP.NETのエラー画面が表示されます。wcf-service-asperror
  15. WcfService.csを編集して[AspNetCompatibilityRequirements]属性を追加します。
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.ServiceModel.Web;
    using System.ServiceModel.Activation;
    using System.Text;
    using System.Runtime.Serialization.Json;
    
    namespace SampleWCFLib
    {
        // メモ: [リファクター] メニューの [名前の変更] コマンドを使用すると、コードと config ファイルの両方で同時にクラス名 "Service1" を変更できます。
        [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
        public class WfcService : IWfcService
        {
            [WebGet(UriTemplate = "api/v1/data/{name}", ResponseFormat = WebMessageFormat.Json)]
            public DataList GetData(string name)
            {
                int count = 0;
                DataList sl = new DataList();
                sl.data_collection = new System.Collections.Generic.List<DataList.DataItem>();
                for (int nLoop = 0; nLoop < 2; nLoop++)
                {
                    DataList.DataItem item = new DataList.DataItem();
                    item.Name = name;
                    item.Id = count.ToString();
                    sl.data_collection.Add(item);
                    count++;
                }
                sl.Id = count;
                sl.Name = name;
                return sl;
            }
        }
    }
    
  16. リビルド後、デバッグ実行を行い起動したブラウザにURLを入力します。
    wcf-service-asp-success
  17. JSON形式でデータがダウンロードされます。
    ブラウザをChromeなどに変更すると、ブラウザ画面でJSON形式が表示されます。wcf-service-asp-success-chrome

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です