jQuery (JavaScript) から C# のメソッドを呼び出す [クロスドメイン編]

# はじめに
Visual Studio を使えば `Web ブラウザ`上で動作する JavaScript から `Web サーバー`上にある C# のコード(メソッド)を容易に呼び出すことができます。
実際に動作するコードを見れば、簡単にエレガントにリモート呼び出し(Ajax 呼び出し)ができることがわかるでしょう。

* jQuery から C# のメソッドを呼び出す基本的なやり方は[こちらの記事](http://qiita.com/akmiyoshi/items/16c4a65731f8ec32e233)を御覧ください。

* 今回は、Ajax+JSONPでクロスドメインに外部APIと連携する方法を紹介します。

* より複雑なメソッド(レコード、配列の受け渡し等)は別途サンプルを作って提示します。乞うご期待！

# Web.config の修正

クロスドメインから C# のメソッド呼び出しができるようにするためには Web.config に以下の様な記述を追加する必要があります。
http://stackoverflow.com/questions/5686059/how-to-avoid-cross-domain-policy-in-jquery-ajax-for-consuming-wcf-service を参考にしました。

```xml:Web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections> <!-- 省略 --> </configSections>
  <connectionStrings> <!-- 省略 --> </connectionStrings>
  <appSettings> <!-- 省略 --> </appSettings>
  <system.web> <!-- 省略 --> </system.web>
  <system.webServer> <!-- 省略 --> </system.webServer>
  <runtime> <!-- 省略 --> </runtime>
  <entityFramework> <!-- 省略 --> </entityFramework>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="WebApplication1.Service1AspNetAjaxBehavior">
          <enableWebScript />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
      multipleSiteBindingsEnabled="true" />
    <services>
      <service name="WebApplication1.Service1">
        <!-- bindingConfiguration="crossDomain" を追加 -->
        <endpoint address=""
                  behaviorConfiguration="WebApplication1.Service1AspNetAjaxBehavior"
                  binding="webHttpBinding"
                  bindingConfiguration="crossDomain"
                  contract="WebApplication1.Service1" />
      </service>
    </services>
    <!-- コード追加開始 -->
    <bindings>
      <webHttpBinding>
        <binding name="crossDomain" crossDomainScriptAccessEnabled="true"></binding>
      </webHttpBinding>
    </bindings>
    <!-- コード追加終了 -->
  </system.serviceModel>
</configuration>
```
# 呼び出される側(C#)のコード
クロスドメイン呼び出しのために`jsonp`を用いるため`[WebInvoke(Method = "GET")]`を指定しておきます。

```csharp:Service1.svc.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;

namespace WebApplication1
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Service1
    {
        // 追加の操作をここに追加して、[OperationContract] とマークしてください
        [OperationContract, WebInvoke(Method = "GET")]
        public int Add2(int x, int y)
        {
            return x + y;
        }
        [OperationContract, WebInvoke(Method = "GET")]
        public int Sub2(int x, int y)
        {
            return x - y;
        }
    }
}
```

Webサーバー(C#)アプリを http://www.visualstudio.expressweb.jp/samples/app20140424/ にデプロイしてあります。
http://www.visualstudio.expressweb.jp/samples/app20140424/Service1.svc/Add2?x=11&y=22 をブラウザで開くと `{"d":33}` というJSON形式のレスポンスが返って来ます。(Webサービスを直接起動できます。実験してみてください)

# 呼び出す側(JavaScript/jQuery)のコード

「jsdo.it」に呼び出し側のサンプル(HTML)を載せました⇒ http://jsdo.it/akmiyoshi/simple-ajax-call-to-csharp-methods

```
JavaScript、HTML5、CSS 共有コミュニティ

「jsdo.it - share JavaScript, HTML5 and CSS -」は、Web制作の次世代開発言語「HTML5」と、「JavaScript」「CSS」のソースコードを投稿してユーザー間で共有できるWebサービスです。
あらゆるWebデザイナー、マークアップエンジニア、Webプログラマーの知識と技術の共有を可能に。
"その場で作れるWebアプリケーション"として、上記プログラムを全て「jsdo.it」内で記述できます。
また、投稿された作品（プログラム）を別のユーザーが書き換えるFork機能も実装しており、１つの作品を幾通りにも別の作品へと発展させることもできます。
```

```html:jsdo.itから自動生成されたHTML
<html><head><meta charset="UTF-8">
<title>Simple Ajax Call to C# Methods - js do it</title>
<meta name="Description" content="jsdo.it - share JavaScript, HTML5 and CSS -">
<meta name="Keywords" content="JavaScript,HTML5,CSS">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<style type="text/css">* {
  margin: 0;
  padding: 0;
  border: 0;
}

body {
  background: #ddf;
  font: 30px sans-serif;
}

input[type=button]{
   border-radius: 5px;
   border:#a9a9a9 1px solid;
   box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2),0 0 2px rgba(0,0,0,0.3);
   width:150px;
   height:25px;
   padding:0 3px;
   cursor:pointer;
   color:#333;
   font-weight:bold;
   background:#f5f5f5;
   text-shadow:1px 1px 0px #fff;
}</style>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
</head><body style="">
        
    <h3>AJAX テスト</h3>

    <input id="first" type="text" value="11">
    <input id="second" type="text" value="22">
    <br>
    <input id="button1" type="button" value="Add2">
    <input id="button2" type="button" value="Sub2">
    <br>
    <b>戻り値</b><div id="result"></div>
    
<script type="text/javascript">$(document).ready(function () {
    $("#button1").click(function () {
        var args = { x: $("#first").val(), y: $("#second").val() };
        $.ajax({
            type: "GET",
            url: 'http://www.visualstudio.expressweb.jp/samples/app20140424/Service1.svc/Add2',
            crossDomain: true,
            data: args,
            dataType: 'jsonp',
            success: function (data) {
                $("#result").text(data);
            },
            error: function (xhr) {
                alert("failed");
                alert(xhr.responseText);
            }
        });
    });
    $("#button2").click(function () {
        var args = { x: $("#first").val(), y: $("#second").val() };
        $.ajax({
            type: "GET",
            url: 'http://www.visualstudio.expressweb.jp/samples/app20140424/Service1.svc/Sub2',
            crossDomain: true,
            data: args,
            dataType: 'jsonp',
            success: function (data) {
                $("#result").text(data);
            },
            error: function (xhr) {
                alert("failed");
                alert(xhr.responseText);
            }
        });
    });
});</script></body></html>
```