2013/07/31

jQuery から WCF のサービスを GET/POST で呼び出す


WCF のサービスを作成し、 jQuery から GET/POST で呼びだそうとしたら、思いの外苦労しました。ですので、同じようなことをしようとしている方向けに方法を掲載しておこうと思います。

WCF のサービスは、jQuery から GET/POST でリクエストを受けて、レスポンスを JSON 形式で返すようにします。なお、.NET のクラスインスタンスを JSON に変換するのに、オープンソースの JSON.NET を使用しています。

GET/POST 共通部分

WCF サービス

まず、WCF サービスを JavaScript から呼び出せるように、Service1.svc (svc ファイル) を「マークアップの表示」から表示して、以下の色付けした部分を追加します。

<%@ ServiceHost Language="C#" Debug="true" Service="WcfService1.Service1" CodeBehind="Service1.svc.cs" Factory="System.ServiceModel.Activation.WebServiceHostFactory"%>

データクラスである Person クラスを作成します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WcfService1
{
  public class Person
  {
    public string Name { get; set; }
    public int Age { get; set; }
  }
}

WCF GET パラメーターなし

WCF サービス

WCF サービスは、まずインターフェースを作成する必要があります。GET リクエストにパラメータがつかない場合は、メソッドの属性は WebGet となります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Web;
using System.ServiceModel.Channels;

namespace WcfService1
{
  [ServiceContract]
  public interface IService1
  {
    [OperationContract]
    [WebGet(UriTemplate = "GetPerson")]
    Message GetPerson();
  }
}

インターフェースを実装します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Web;
using System.ServiceModel.Channels;
using Newtonsoft.Json;


namespace WcfService1
{
  public class Service1 : IService1
  {
    public Message GetPerson()
    {
      Person person = new Person() {Name = "Yamada", Age = 10 };

      //object to json by JSON.NET
      string body = JsonConvert.SerializeObject(person);

      //Return JSON
      return WebOperationContext.Current.CreateTextResponse(body,
        "application/json; charset=utf-8",
        Encoding.UTF8);
    }
  }
}

これで WCF サービスの設定は終了です。

jQuery で呼び出し

jQuery を使用し、パラメータなしの GET リクエストを呼び出します。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title></title>
  <script src="Scripts/jquery-2.0.3.min.js"></script>
  <script type="text/javascript">
    $.ajax({
      type: "GET",
      url: "Service1.svc/GetPerson",
      data: null,
      success: function (data, textStatus, xhr) {

        //HTML escape and append
        $("#person").text(data.Name + " " + data.Age);
      }
    });
  </script>
</head>
<body>
  <div id="person"></div>
</body>
</html>

実行結果は、ブラウザに以下のように表示されます。

Yamada 10

WCF GET パラメーターあり

WCF サービス

インターフェースを定義しますが、GET リクエストでパラメータを受け取る場合は、属性は WebGet ではなく、WebInvoke を使用します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Web;
using System.ServiceModel.Channels;

namespace WcfService1
{
  [ServiceContract]
  public interface IService1
  {
    [OperationContract]
    [WebInvoke(UriTemplate = "GetPerson?name={name}", Method = "GET")]
    Message GetPerson(string name);
  }
}

インターフェースを実装します。今回はパラメータを受け取っているので、List から LINQ を使用してデータを抽出後、JSON に変換して値を返すようにします。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Web;
using System.ServiceModel.Channels;
using Newtonsoft.Json;


namespace WcfService1
{
  public class Service1 : IService1
  {
    public Message GetPerson(string name)
    {
      //create data
      List<Person> list = new List<Person>();
      list.Add(new Person() { Name = "Yamada", Age = 10 });
      list.Add(new Person() { Name = "Sato", Age = 20 });
      list.Add(new Person() { Name = "Tanaka", Age = 30 });

      //select person by LINQ
      var person = from t in list
             where t.Name == name
             select t;

      //object to json by JSON.NET
      string body = JsonConvert.SerializeObject(person);

      //Return JSON
      return WebOperationContext.Current.CreateTextResponse(body,
        "application/json; charset=utf-8",
        Encoding.UTF8);
    }
  }
}

jQuery で呼び出し

jQuery を使用し、パラメータありの GET リクエストを呼び出します。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title></title>
  <script src="Scripts/jquery-2.0.3.min.js"></script>
  <script type="text/javascript">
    $.ajax({
      type: "GET",
      url: "Service1.svc/GetPerson",
      data: "name=Yamada",
      success: function (data, textStatus, xhr) {

        //HTML escape and append
        $("#person").text(data[0].Name + " " + data[0].Age);
      }
    });
  </script>
</head>
<body>
  <div id="person"></div>
</body>
</html>

実行結果は、ブラウザに以下のように表示されます。

Yamada 10

WCF POST パラメーターあり

WCF サービス

WCF サービスを POST リクエストで呼ぼうとすると途端に難しくなります。調べた範囲では、POST リクエストのパラメータのデータ形式は、JSON か XML でなければいけませんでした。Stream を使用する方法もあるようですが、今回は JSON 形式を採用することにします。

POST リクエストになると、インターフェースを定義するメソッドの属性が大きく変わることが分かります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Web;
using System.ServiceModel.Channels;

namespace WcfService1
{
  [ServiceContract]
  public interface IService1
  {
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "GetPerson", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json)]
    Message GetPerson(string name);
  }
}

インターフェースの実装は以下のようにします(GET リクエスト時と同じ)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Web;
using System.ServiceModel.Channels;
using Newtonsoft.Json;


namespace WcfService1
{
  public class Service1 : IService1
  {
    public Message GetPerson(string name)
    {
      //create data
      List<Person> list = new List<Person>();
      list.Add(new Person() { Name = "Yamada", Age = 10 });
      list.Add(new Person() { Name = "Sato", Age = 20 });
      list.Add(new Person() { Name = "Tanaka", Age = 30 });

      //select person by LINQ
      var person = from t in list
             where t.Name == name
             select t;

      //object to json by JSON.NET
      string body = JsonConvert.SerializeObject(person);

      //Return JSON
      return WebOperationContext.Current.CreateTextResponse(body,
        "application/json; charset=utf-8",
        Encoding.UTF8);
    }
  }
}

jQuery で呼び出し

jQuery を使用し、パラメータありの POST リクエストを呼び出します。リクエストパラメーターが JSON 形式になっていること、情報が増えていることに注意してください。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title></title>
  <script src="Scripts/jquery-2.0.3.min.js"></script>
  <script type="text/javascript">
    $.ajax({
      type: "POST",
      url: "Service1.svc/GetPerson",
      data: '{"name":"Yamada"}',
      dataType: 'json',
      contentType: "application/json; charset=utf-8",
      success: function (data, textStatus, xhr) {

        //HTML escape and append
        $("#person").text(data[0].Name + " " + data[0].Age);
      }
    });
  </script>
</head>
<body>
  <div id="person"></div>
</body>
</html>

実行結果は、ブラウザに以下のように表示されます。

Yamada 10

おわりに

jQuery から WCF サービスを GET/POST の両方の形式で呼び出す方法は以上のようになります。まとめてしまうと簡単に見えるかもしれませんが、ネットでかなり調べましたが使える情報はほとんどありませんでした。ニーズがないのでしょうか?

なお、このサンプルプログラムは単純化するために JSON のセキュリティ対策を省いています。JSON のセキュリティ対策を施したプログラムについては以下の記事をご参照ください。


スポンサーリンク


このエントリーをはてなブックマークに追加




Twitter ではブログにはない、いろんな情報を発信しています。


コメント

Factory = "System.ServiceModel.Activation. WebServiceHostFactory"

追加したら Webサービス参照しようとした時にえらーがでるくらしいびくんびくん

'http://localhost:49813/MyWcfService/RssItemService.svc' をダウンロード中にエラーが発生しました。
HTTP ステータス 400: Bad Request で要求が失敗しました。
メタデータに、解決できない参照が含まれています。'http://localhost:49813/MyWcfService/RssItemService.svc'。
コンテンツの種類 application/soap+xml; charset=utf-8 はサービス http://localhost:49813/MyWcfService/RssItemService.svc でサポートされていませんでした。
クライアントとサービスのバインドが整合していない可能性があります。
リモート サーバーがエラーを返しました: (415) Unsupported Media Type
サービスが現在のソリューションに定義されている場合は、ソリューションの構築とサービス参照の追加を再試行してください。

コメントを書く



プロフィール

  • 名前:fnya
    経歴:
    SE としての経験は15年以上。様々な言語と環境で業務系システム開発を行い、セキュリティ対策などもしていました。現在は趣味SE。

    Twitter では、ブログでは取り上げない情報も公開しています。


    ブログについて

    このブログは、IT、スマートフォン、タブレット、システム開発などに関するさまざまな話題を取り上げたり、雑感などをつづっています。

    現在、Enty で支援を受け付けています。もしよければご支援ください。



    >>ブログ詳細
    >>自作ツール
    >>運営サイト
    >>Windows 10 まとめ

    Twitter のフォローはこちらから Facebook ページはこちら Google+ページはこちら RSSフィードのご登録はこちらから