none
VB MVC5でAjaxが成功しない。 RRS feed

  • 質問

  • いつもお世話になります。

    Visual Studio 2015 Update3 pro. のVBで、Webアプリを作ろうとしています。Ajaxのところで上手くいかずに右往左往している状況です。

    VSで新しいWeb APIプロジェクトを作成して、以下のものを書き加えました。

    (1)読み取り/書き込みのあるWebAPI2コントローラーを作成して、FoodsController.vb

    Imports System.Net
    Imports System.Web.Http
    
    Namespace Controllers
        Public Class FoodsController
            Inherits ApiController
    
            Private foods As String() = {"bread", "rice", "noodles", "sushi", "spaghetti", "pizza"}
    
            ' GET: api/Foods
            Public Function GetValues() As IEnumerable(Of String)
                Return foods
            End Function
    
            ' GET: api/Foods/5
            Public Function GetValue(ByVal id As Integer) As String
                If id > 0 And id <= foods.Length Then
                    Return foods(id - 1)
                Else
                    Return "I don't know."
                End If
            End Function
    
        End Class
    End Namespace

    これを実行して、
    http://localhost:49286/api/foods にアクセスすると、["bread","rice","noodles","sushi","spaghetti","pizza"]

    http://localhost:49286/api/foods/4 にアクセスすると、"sushi"

    http://localhost:49286/api/foods/100 にアクセスすると、"I don't know."

    が戻ってくることを確認しました。

    次に、MVC5コントローラ-空 を作成して、FoodlistController.vb

    Namespace Controllers

    Public Class FoodlistController Inherits Controller ' GET: Foodlist Function Index() As ActionResult Return View() End Function Function Food(id As Integer) As ActionResult Return View(id) End Function End Class End Namespace

    と、 Foodlist/Index.vbhtml

    @Code
        ViewData("Title") = "Index"
    End Code
    
    <h2>Please Push Button</h2>
    
    <button id="display" class="btn btn-success">Display List</button>
    
    <h2>Foods List</h2>
    <div id="list"></div>
    
    <h2>End of List</h2>
    
    @Section scripts
    <script>
        $("#display").click(function () {
            var url = "api/foods/";
            $.getJSON(url)
                .done(function (data) {
                    var html = "<ul>";
                    $.each(data, function (index, value) {
                        html += "<li>" + value + "</li>";
                    })
                    html *= "/ul>";
                    $("#list").html(html);
                })
                .fail(function(data){
                    $("#list").text("Error on Ajax!!!");
                });
        });
    
    </script>
    End section
    

    を書きました。そして、実行して、[Display List]ボタンを押しても、”Error on Ajax!!!”という失敗メッセージしか現れません。

    何をすれば、Ajaxが成功するようになるでしょうか?よろしくお願いします。

    2016年7月6日 22:55

回答

すべての返信

  • ざっと見たかぎりでは問題になりそうなところは見当たらないです。

    質問者さんのコードを詳しく調べる前に一つお願いできますか?

    それは、質問者さんの方で Fidder などのキャプチャツールを使って、要求と応答がどうなっているか調べることです。

    期待した GET 要求が出ているか、期待した JSON 文字列が返ってきているかを調べてください。うまく行くと以下のようになるはずです。

    #開発環境(VS だけではなくて、OS、IIS、jQuery のバージョン、ブラウザは何かなども)を書いてください。

    #もし公開されているどこかの Web の記事がベースになっているのであればその URL を書いてください。


    • 編集済み SurferOnWww 2016年7月7日 1:48 「jQuery のバージョン」追記
    2016年7月7日 1:26
  • こんにちは。

    //var url = "api/foods/";
    var url = "/api/foods/";

    ではないでしょうか。
    あと、ulが閉じれてないようです。

    //html *= "/ul>";
    html += "</ul>";


    2016年7月7日 1:52
    モデレータ
  • 一つ気がつきました。

    > 次に、MVC5コントローラ-空 を作成して、FoodlistController.vb

    というのは、Web API 用に作ったプロジェクト / アプリケーションとは別プロジェクト / 別アプリケーションですか? 

    AJAX 呼び出しを行うわけですから、2 つのプロジェクト / アプリケーションは同じドメイン内にないとダメです。(AJAX の約束事)

    IIS Express 上で実行すると 2 つのプロジェクト / アプリケーションがどういう関係で実行されるのかは知りませんが、そのあたり(「MVC5コントローラ-空」アプリから「Web API」アプリが呼び出せてない)に問題がありそうな気がします。

    呼び出し側も同じプロジェクト / アプリケーションに実装してください。

    MVC5 は多少違うかもしれませんが、テンプレートを使って作ると全体の構成は以下のようになるのでは?

    ASP.NET Web API を使ってみよう: MVC 4 新機能シリーズ
    https://blogs.msdn.microsoft.com/chack/2012/02/24/asp-net-web-api-mvc-4-2/

    であれば、上記の記事の手順 5 に書いてあるように、その中の(同じプロジェクト / アプリケーションの)Index.cshtml に Web API を呼び出す jQuery のスクリプトを実装して試してみてください。

    Fiddler などのパケットキャプチャツールで調べると、どこに問題があるかが容易に見つかると思います。だから、そういうことを前のレスで提案してます。使えるようになりましょう。

    2016年7月7日 3:55
  • Tak1waさま

    ありがとうございました。

    var url = "/api/foods/";

    の修正で、期待通りのajax動作ができました。

    これも思い込みで、参考書を良く見ると、やはりちゃんとスラッシュからurlを書いていました。
    完全に、私の見落としでした。ありがとうございました。

    2016年7月7日 4:00
  • SurferOnWwwさま

     いつもいろいろ教えてくださり、感謝しています。

     教えていただいた、Fidderを早速ダウンロードして試してみます。なかなか多彩な機能の開発ツールみたいですね。
    大きな収穫のひとつでした。ありがとうございます。

     当初の問題は、この後のTak1waさんの回答で氷解しました。私のつまらない思い込みでしたね。
    いろいろ煩わせてすみません。

     ちなみに、開発環境はAzureのVMで、OSはWindows Server2012R2 です。職場の事務用パソコンではメモリ不足になるので。
     参考にしたものは、最近2週間ぐらいに10冊ぐらい関連書籍を斜め読みしましたが、一番頼りにしているのは、
    山田祥寛氏の「ASP.NET MVC5実践プログラミング」(秀和システム)で、P.435からAjaxの説明があります。

    いろいろとありがとうございました。

    2016年7月7日 4:10
  • SuferOnWwwさま

     一つのMVC5のWeb APIプロジェクトを新規作成すると、Webアプリケーションの機能も同時に構築されるみたいです。
    今回は、この方法でしたので、同一のサイトに2つの機能があります。更にこのサイトにはHelpコントローラが付いてきて、
    自作したWeb APIのヘルプ情報を自動的に収集して表示してくれる仕組みもついていました。
    web APIの実装を秘密にする必要がない場合はとても便利ですが、
    秘密にしておこうと思っても知らないところででAPIのヘルプがみられてしまうというのも少し恐ろしいことかなと思いました。

     教えていただいたFiddlerをインストールして試しています。なかなか面白いです。ありがとうございます。

    2016年7月7日 5:43
  • > 当初の問題は、この後のTak1waさんの回答で氷解しました。私のつまらない思い込みでしたね。

    「つまらない思い込み」ということはなくて、スラッシュ '/' は結構深い話だと思うのですが。

    特に最初のスラッシュ '/' の有無による違いは重要で、それによってブラウザが要求をかける際のパスが違ってくるということを理解していますか?

    理解していたら失礼しました。以下のレスはスルーしてください。

    "/api/foods" のように最初にスラッシュ '/' を付けると「サイト ルート相対パス」、"api/foods" のようにすると「現在のページ パスに対して解決される相対パス」になります。詳しい説明は以下の記事を見てください。

    ASP.NET Web サイトのパス
    https://msdn.microsoft.com/ja-jp/library/ms178116(v=VS.100).aspx

    今回の問題は、Foodlist/Index.vbhtml からでは "api/foods" のような「現在のページパスに対して解決される相対パス」ではパスが通らなかったからで、"/api/foods" としたらパスが開発環境での 「サイト ルート相対パス」即ち http://<hostname>/api/foods となったので問題が解決したのだと思います。

    しかし、例えば実際の運用環境で、アプリケーションとして Web API をデプロイする場合、URL は http://<hostname>/<appname>/api/foods というようになるはずですが、これを jQuery.getJSON で url を "/api/foods" として要求したのでは HTTP 404 エラーになるはずです(http://<hostname>/api/foods を要求するので)。

    最後のスラッシュ(「トレーリングスラッシュ」という)にも意味があって、それに関わる問題もあります。(特に SEO 対策)

    URLの終りに「/」(スラッシュ)は必要?、不要?
    https://www.suzukikenichi.com/blog/do-we-need-a-trailing-slash-at-the-end-of-url/

    RESTful API ではちょっと違う意味があって "But from the original paper on REST a full (not ending in /) URL names a resource, while one ending in a slash '/' is a resource group" ということだそうです。(original paper は調べてませんが)

    Trailing slash in RESTful API
    http://programmers.stackexchange.com/questions/186959/trailing-slash-in-restful-api

    2016年7月7日 7:53
  • > Webアプリケーションの機能も同時に構築されるみたいです。

    全体的にどういう構成になるのか VS2015 を持っていない自分には分かりませんが、Web API とは同一ドメインになると理解します。でないと、AJAX は使えないので。(JSONP は使っていないと理解)

    2016年7月7日 7:56
  • みなさまのおかげで無事動作できましたので、成果を
    https://code.msdn.microsoft.com/Minimum-of-sample-written-7ebe939d

    で公開させていただきました。ありがとうございました。

    2016年7月7日 18:16