none
ajaxサーバ側スクリプト実行後エラーになる RRS feed

  • 質問

  • jQueryのdatepickerで、データベース中にデータが存在する日付だけを選択可能にするよう、datepickerのBeforeShowイベントでサーバ側のスクリプトでデータベースを検索して、データのある日付をListにしてjQueryに戻しています。下記のような感じです。

    Visual Studioのローカル環境では正常に動作するのですが、Azureにアップロードして実行させると、サーバ側スクリプトは正常に動作するのですが、jQueryにerrorで戻っててしまいます。

    AzureにアップロードしたプログラムはTraceできないので、プログラムの確認したい箇所を通過するとデバッグファイルに行を書き出すトレース関数を作って動作確認しています。実行を確認したところ、Azure上のスクリプトは、ローカル環境と同じく実行しています。ローカルではjQueryにsuccessで戻るのに、Azureではerrorで戻ります。

    応答データはサーバ側スクリプトではDateTime型Listで作成し、それをjQueryにhtml形式で戻しています。19日と20日では下記のような戻り値になります。

    ["¥/Date(1453129200000)¥/","¥/Date(1453215600000)¥/"]

    単体でdatepickerだけ動かすと正しく動作します。サーバ側を呼び出さず、本日より前の日付だけ選択できるようにするとかなら、問題なく動作します。

    サーバ側スクリプトはC#で記述しています。AzureのjQueryのサーバ側スクリプトの呼び出しには何か制限があるのでしょうか。

    2016年1月20日 4:13

回答

  • > このエラーメッセージの意味はJSONのデータが戻されていない=戻り値が見つからないという
    > 意味だと理解しております(確証はありませんが)。

    エラーメッセージ Not Found を信じない質問者さんのその自信は、

    > こちらはサーバ側スクリプトのApp_Dataフォルダ内にデバッグファイルを設けて、スクリプト
    > returnの直前にこのファイルに書き込んで、Azureでもスクリプトが呼び出されていることを
    > 確認しています。

    というところからきていると思いますが、私のレスを信じないのはともかく、エラーメッセージはウソを言わないはずなのでまずそれを信じて、上の質問者さんの「確認」を再度良くチェックしてみるという方向に進むべきだと思いますが・・・

    ちなみに function (xhr, status, err) の err は jQuery.ajax() の API Documentation によると、

    > When an HTTP error occurs, errorThrown receives the textual portion of the HTTP status,
    > such as "Not Found" or "Internal Server Error."

    とのことです。これもウソではなくてホントのはずです。

    前の私のレスで、

    > また、Fiddler を使って要求 / 応答をキャプチャして中身を見ると、何か手がかり(本当に
    > クロスドメインの問題はないかなど)が得られるかもしれません。

    とアドバイスしましたが、やってみましたか? HTTP 404 Not Found エラーが返ってきているかどうか確認できるはずです。

     

    • 回答としてマーク 少菅閑事 2016年1月22日 14:41
    2016年1月21日 14:41

すべての返信

  • 具体的にどのようにしているのか質問に書かれている情報では分からないので単なる想像(空想かも)ですが・・・

    beforeShow に設定したメソッドで AJAX を使ってサーバから情報を取得するようになっているが、Azure の環境ではクロスドメインになって失敗するというようなことはないですか?

    2016年1月20日 5:51
  • スクリプトもデータベースもAzure上にしかなく、クロスドメインにはなっていないはずです。

    ■■■■■サーバ側スクリプトはHomeController.csの中に書いていて下記のような感じです。■■■■■

    [HttpPost]
    public ActionResult SearchDate(int year, int month)
    {
        if (Request.IsAjaxRequest()) {
            SqlConnection SQLconnection = new SqlConnection(ここでSQL接続文字列を設定・・・・・
    /******** ここで有効なデータが存在する日付を検索 **********/
    /******** 検索した日付は「DataTable dayTable.Rows[i].ItemArray[0]」に格納 **********/
            List<DateTime> dateList = new List<DateTime>();
            for (int i = 0; i < dayTable.Rows.Count; i++) {
                Trace.WriteLine("day:" + dayTable.Rows[i].ItemArray[0].ToString());
                dateList.Add(new DateTime(year, month, (int)dayTable.Rows[i].ItemArray[0]));
            }
            return Json(dateList); /**********Azureでもここには来る**********/
        }
        else {
            return new EmptyResult();
        }
    }



    ■■■■■■■■■■Index.cshtmlは下記のような感じです。■■■■■■■■■■

    @using (Html.BeginForm())  {
        <p>
            データの年月日を選択してください
        <br />
            <span style=">@Html.TextBox("selectDate")</span>
        </p>
    }
    <script type="text/javascript">
        enableDate = new Array(); /*この配列にdatepickerで選択可能な日を格納*/

        function getEnableDate(year, month) {
            $.ajax({
                url: '/Home/SearchDate',
                type: 'POST',
                dataType: 'html',
                data: {
                    year: year,
                    month: month,
                },
                async: false,
                success: function (data) {
    /********************** ローカルVisual StudioではSearchDateからここに戻る **********************/
                    var arrayData = eval('(' + data + ')');
                    enableDate.length = 0;
                    for (var i = 0; i < arrayData.length; i++) {
                        arrayData[i] = arrayData[i].replace('/Date(', '');
                        arrayData[i] = arrayData[i].replace(')/', '');
                        enableDate[i] = new Date(parseInt(arrayData[i])).getDate();
                    }
                },
                error: function (xhr, status, err) {
    /*************************** AzureではSearchDateからここに戻る ***************************/
                }
            });
        }
        $(function () {
            $.datepicker.setDefaults($.extend($.datepicker.regional['ja']));
            $('#selectDate').datepicker({
                appendText: '(yyyy-mm-dd)',
                showAnim: 'show',
                beforeShow: function (input, inst) {
                    today = new Date();
                    if ($(this).datepicker('getDate') != null) {
                        today = $(this).datepicker('getDate');
                    }
                    getEnableDate(today.getFullYear(), today.getMonth() + 1);
                },
                onChangeMonthYear: function (year, month, inst) {
                    getEnableDate(year, month);
                },
                beforeShowDay: function (date) {
                    for (i = 0; i < enableDate.length; i++) {
                        if (date.getDate() == enableDate[i]) {
                            return [true];
                        }
                    }
                    return [false];
                },
                onSelect: function (dateText, inst) {
                    $('.showData').css('visibility', 'visible');
                },
                dateFormat: 'yy/mm/dd'
            });
            $('#selectDate').datepicker({ currentText: 'Now' });
            $(function () {
                $('.showData').css('visibility', 'hidden');
            });
        });
    </script>

    2016年1月20日 7:01
  • error: function (xhr, status, err) の引数の情報で何か分かりませんか?

    また、Fiddler を使って要求 / 応答をキャプチャして中身を見ると、何か手がかり(本当にクロスドメインの問題はないかなど)が得られるかもしれません。

    2016年1月20日 7:15
  • 以前 Azure のフォーラムで話題になった Azure Web Apps の sandbox(そのときは GDI+ エラーの話)に関する記事が見つかりましたので紹介しておきます。

    Azure runtime environment
    https://github.com/projectkudu/kudu/wiki/Azure-runtime-environment

    そのときは上の記事の Restrictions のセクションに少し書かれていたのですが、別の記事(URL 下記)にまとめられてリンクが張られています。

    Azure Web App sandbox
    https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox

    質問者さんの作った Controller のアクションメソッドが上に紹介した記事の制約に引っかかるかは分かりません(調べてません、というか調べられないです)。ご自分でチェックしてみてください。

    2016年1月20日 9:42
  • error:functionの戻り値をブラウザ上に表示するように改造して確認すると、Azureで実行させると下記のようになっています。

    xhr は [object Object]

    status は error

    err は Not Found

    です。Visual Studio ローカル環境で実行させてjQuery側で確認したsuccessの戻り値dataは

    ["\/Date(1453129200000)\/","\/Date(1453215600000)\/","\/Date(1453302000000)\/"]

    になっています。WEbサーバ側スクリプトで編集・制作してjQueryに返すパラメータに、AzureとVisualStudioローカルで何らかの互換性がないのが原因のように思います。(サーバ側スクリプトでは\は\で、これが気になります。Visual Studio日本語版のエディタではそもそも\は出ず、プログラム上\と同じものとして処理しています)

    このスクリプトは、ローカル環境でも日本国内ホスティング業者のWEBサーバ(Windowsサーバ日本語版)では、正しく実行しています。AzureのWindowsサーバは英語版のようで、日本語版と英語版で何か差があるのでしょうか。\と\は同じものと考えて処理していますが、これがまずいのでしょうか。

    jQueryを実行するブラウザは、現状はGoogle Chrome日本版です。(マイクロソフト製ブラウザでないほうが、動作確認上はいいと考えています)

    2016年1月20日 22:19
  • 返信を投稿して気づいたのですが、この投稿用のエディタでもバックスラッシュが円マークに自動的に変換されてしまいます。

    投稿で示したsucessの戻り値dataの円マークはバックスラッシュです。本文中のバックスラッシュもすべて円マークに変換して表示されています。デバッグ用にブラウザで表示したdataはバックスラッシュで表示されています。

    投稿用エディタで編集中はバックスラッシュになっているのですが、投稿すると円マークに自動変換されるようです。

    2016年1月20日 22:27
  • お示しいただいたURLの内容を拝読いたしました。

    ローカルとAzureで環境の書き方が違うのではと疑っては見ましたが、jQuery側から呼び出しているサーバ側スクリプトのパスは

    url: '/Home/SearchDate'

    と書いています。これをいろいろ変えてみたのですが、正しく動作しません。

    現状ではjQuery側からWebサーバ側スクリプトの呼び出しはできているようなので、ファイルパスの環境とかの問題はないと考えています。

    2016年1月20日 22:44
  • サーバ側スクリプトの戻り値dataType: 'html'を'json'に変えてみました。

    サーバ側の戻り値を下記のようにJsonに変更してみました。

    結果は同じで、Visual Studioでは正常で、Azureではエラーになります。

    System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
    return Json(serializer.Serialize(dateList));

    2016年1月21日 0:10
  • > err は Not Found

    であれば原因として一番怪しいのは、getEnableDate メソッドの中の

    > url: '/Home/SearchDate',

    が間違っているということです。

    前のレスで、

    > return Json(dateList);  /**********Azureでもここには来る**********/

    とありましたが、Not Found(SearchDate というアクションメソッドは見つからない)とサーバーが言っているので、そんなことはないはずですが・・・

    質問者さんの前のスレッド ↓ の話と関係ありませんか?

    WEBアプリケーションをサブフォルダの下に置きたい
    https://social.msdn.microsoft.com/Forums/ja-JP/019d9ffa-89e6-4afc-881c-7864ade8a6fb/web?forum=windowsazureja


    > この投稿用のエディタでもバックスラッシュが円マークに自動的に変換されてしまいます。

    「バックスラッシュ」と「円マーク」は見え方(フォント)が違うだけで中身(UTF-16 で 0x005C)は同じです。


    > サーバ側スクリプトの戻り値dataType: 'html'を'json'に変えてみました。

    Not Found(SearchDate というアクションメソッドは見つからない)であればそれ以前の問題です。

    2016年1月21日 1:52
  • >であれば原因として一番怪しいのは、getEnableDate メソッドの中の

    >> url: '/Home/SearchDate',

    >が間違っているということです。

    こちらはサーバ側スクリプトのApp_Dataフォルダ内にデバッグファイルを設けて、スクリプトreturnの直前にこのファイルに書き込んで、Azureでもスクリプトが呼び出されていることを確認しています。Trace.Write()とほぼ同等の動作確認ができていると考えております。

    実行しているということはjQueryから見つけられて呼び出されていると思うのですが・・・

    >「バックスラッシュ」と「円マーク」は見え方(フォント)が違うだけで中身(UTF-16 で 0x005C)は同じです。

    こちらはおっしゃるとおり、\は関係なかったです。

    JSONのDateTime型には\が含まれるので、DateTime型でなく日だけを戻すように変えても、結果は変わりませんでした。

    そこでjQueryに戻すJSONデータ列(単純な文字列)の内容も確認しています。Visual StudioとAzureは同じ内容で、これでなぜだめなのか見当がつかないでおります。

    プログラムを変更して、JSONで戻すデータをDateTime型でなく、日付のintだけにしました。先のソースはjQuery側でDateTimeから日付を取り出しておりますが、C#側で日付を取り出して、JSONでは日付だけ戻すようにしました。

    >Not Found(SearchDate というアクションメソッドは見つからない)であればそれ以前の問題です。

    上記のとおりSearchDateは実行しているようなので、このエラーメッセージの意味はJSONのデータが戻されていない=戻り値が見つからないという意味だと理解しております(確証はありませんが)。

    2016年1月21日 5:27
  • > このエラーメッセージの意味はJSONのデータが戻されていない=戻り値が見つからないという
    > 意味だと理解しております(確証はありませんが)。

    エラーメッセージ Not Found を信じない質問者さんのその自信は、

    > こちらはサーバ側スクリプトのApp_Dataフォルダ内にデバッグファイルを設けて、スクリプト
    > returnの直前にこのファイルに書き込んで、Azureでもスクリプトが呼び出されていることを
    > 確認しています。

    というところからきていると思いますが、私のレスを信じないのはともかく、エラーメッセージはウソを言わないはずなのでまずそれを信じて、上の質問者さんの「確認」を再度良くチェックしてみるという方向に進むべきだと思いますが・・・

    ちなみに function (xhr, status, err) の err は jQuery.ajax() の API Documentation によると、

    > When an HTTP error occurs, errorThrown receives the textual portion of the HTTP status,
    > such as "Not Found" or "Internal Server Error."

    とのことです。これもウソではなくてホントのはずです。

    前の私のレスで、

    > また、Fiddler を使って要求 / 応答をキャプチャして中身を見ると、何か手がかり(本当に
    > クロスドメインの問題はないかなど)が得られるかもしれません。

    とアドバイスしましたが、やってみましたか? HTTP 404 Not Found エラーが返ってきているかどうか確認できるはずです。

     

    • 回答としてマーク 少菅閑事 2016年1月22日 14:41
    2016年1月21日 14:41
  • おっしゃるとおりで、スクリプトをルートフォルダに移動したらJsonを取得できるようになりました。ありがとうございました。

    >エラーメッセージ Not Found を信じない質問者さんのその自信は、

    ただいま使っているWindowサーバでは、jQueryからWEBサーバ呼び出しを含むスクリプトをサブフォルダに置いて問題なく動作していたので、まさかAzureでスクリプトの位置の問題が生じると思えませんでした。

    サーバ呼び出しを含まないjQueryは、サブフォルダに置いて問題なく動作しています。

    ルートフォルダのIndex.htmlには全体のメインページがあり、サブのページをメインページに移動することが簡単できない状況です。移動して動いても、WEBページ全体の構成を再検討する必要が生じ、現状のままでなんとかしたいと思っていました。

    WEBページの全体構成で、URLのトップにメインのページを置いて、サブフォルダにいろいろ置くのはふつうの構成と考えていました。たいていの企業ではそうなっていると思われます。

    ただいまはjQueryサーバ呼び出しを含むページを、Homeでない名前に変更して、ルートフォルダのIndex.htmlとの干渉を避けています。(そういうページが増えたらどうするか考えます。)

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

    2016年1月21日 21:57
  • 解決したのですよね。そうであれば解決に役に立った回答に「回答としてマーク」をつけてこのスレッドをクローズしてください。前のような放置はこのフォーラムのマナーとして NG です。
    2016年1月22日 3:37