トップ回答者
ajaxサーバ側スクリプト実行後エラーになる

質問
-
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のサーバ側スクリプトの呼び出しには何か制限があるのでしょうか。
回答
-
> このエラーメッセージの意味は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
すべての返信
-
スクリプトもデータベースも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> -
以前 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 のアクションメソッドが上に紹介した記事の制約に引っかかるかは分かりません(調べてません、というか調べられないです)。ご自分でチェックしてみてください。
-
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日本版です。(マイクロソフト製ブラウザでないほうが、動作確認上はいいと考えています)
-
サーバ側スクリプトの戻り値dataType: 'html'を'json'に変えてみました。
サーバ側の戻り値を下記のようにJsonに変更してみました。
結果は同じで、Visual Studioでは正常で、Azureではエラーになります。
System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
return Json(serializer.Serialize(dateList));
-
> 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 というアクションメソッドは見つからない)であればそれ以前の問題です。
-
>であれば原因として一番怪しいのは、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のデータが戻されていない=戻り値が見つからないという意味だと理解しております(確証はありませんが)。
-
> このエラーメッセージの意味は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
-
おっしゃるとおりで、スクリプトをルートフォルダに移動したらJsonを取得できるようになりました。ありがとうございました。
>エラーメッセージ Not Found を信じない質問者さんのその自信は、
ただいま使っているWindowサーバでは、jQueryからWEBサーバ呼び出しを含むスクリプトをサブフォルダに置いて問題なく動作していたので、まさかAzureでスクリプトの位置の問題が生じると思えませんでした。
サーバ呼び出しを含まないjQueryは、サブフォルダに置いて問題なく動作しています。
ルートフォルダのIndex.htmlには全体のメインページがあり、サブのページをメインページに移動することが簡単できない状況です。移動して動いても、WEBページ全体の構成を再検討する必要が生じ、現状のままでなんとかしたいと思っていました。
WEBページの全体構成で、URLのトップにメインのページを置いて、サブフォルダにいろいろ置くのはふつうの構成と考えていました。たいていの企業ではそうなっていると思われます。
ただいまはjQueryサーバ呼び出しを含むページを、Homeでない名前に変更して、ルートフォルダのIndex.htmlとの干渉を避けています。(そういうページが増えたらどうするか考えます。)
ありがとうございました。