11

何百ものフィールドがあるフォームを含むページを含むWebアプリケーションがあります。フィールドのいずれかを変更すると、サーバーにjQuery $ .ajaxコールバックが発生し、新しい値に基づいてフォームに他のフィールドを追加する必要があるかどうかを判断します。つまり、1つのフィールドが変更されたときに、依存フィールドをフォームに追加する必要があるかどうかを確認します。

このプロセスには少し複雑さがあり、その結果、これらのチェックに数秒かかる場合があります。

問題は、あるフィールドが$ .ajax呼び出しの途中にあり、最初のフィールドが完了するのを待っている間に別のフィールドを変更しようとすると、UIがブロックされ、ページ上で何もできないということです。最初の呼び出しが完了します。これは、UIが一度に1つの$.ajax呼び出ししか処理できないようなものです。$.ajax呼び出しのコピーは次のとおりです。

$.ajax({
        type: "POST",
        async: true,
        url: serviceUrl,
        data: JSON.stringify(data),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        processdata: true,
        success: serviceSuccess,
        error: serviceFailed
    });

serviceSuccessコールバックにはUIを更新するための複雑なコードがたくさんありますが、その中のすべてのコードを削除しても問題は発生します。コールバックが完了する前に発生したように見えるので、コールバックとは何の関係もないと思いましたが、念のために言ってみました。

jQuery $ .ajaxでこのようなことを聞​​いたことがある人はいますか?

編集: $。ajax呼び出しから返される応答のサイズが約130kであることに気づきました。

編集2: $。ajax呼び出しは、WCFサービスを呼び出しています。クラス定義は次のようになります。

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ReviewDataService : IReviewDataService, IReadOnlySessionState 

解決策:ジェイソンは間違いなく私を正しい方向に向けました。私の問題は、実際、ASP.NETセッションのロックが原因でした。これを回避するには、WCFサービスから発信された呼び出しで、呼び出しスタックのどこからでもSessionを使用しないようにする必要がありました。さらに、AspNetCompatibilityRequirementsModeをAspNetCompatibilityRequirementsMode.NotAllowedに設定し、web.configのserviceHostingEnvironment要素でaspNetCompatibilityEnabled="false"を設定しました。

これにより、SessionにアクセスしようとしたときにWCFがエラーをスローし、セッションに依存しないように、これらの各インスタンスをリファクタリングしました。その後、私のWCF呼び出しは、同期ではなく同時に実行を開始しました。

4

1 に答える 1

9

ASP.NETを使用している場合は、Sessionオブジェクトに対して読み取り/書き込みロックを使用します。これにより、AJAXリクエストがシリアルになります。

ASP.NETでは、セッションに読み取り/書き込みロックをかけないIReadOnlySessionStateを実装するIHttpHandlerを使用できます。ただし、使用している環境がわかりません。

編集1

この投稿は、WCFサービスではセッションのロックを解除する柔軟性がないことを示しているようです。

IISでホストされているWCFまたはASMX[Webサービス]にセッションオブジェクトを読み取り専用で使用させるにはどうすればよいですか?

編集2

SessionオブジェクトをロックしないIHttpHandlerを設定します。

Web.config

<configuration>
    <connectionStrings>
    </connectionStrings>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>
    <system.webServer>
        <httpProtocol>
            <customHeaders>
                <add name="Access-Control-Allow-Origin" value="*" />
            </customHeaders>
        </httpProtocol>
        <modules runAllManagedModulesForAllRequests="true" />
        <handlers>
            <add name="MyProvider" path="MyProvider.aspx" verb="*" type="MyNamespace.MyProvider" resourceType="Unspecified" />
        </handlers>
    </system.webServer>
</configuration>

MyProvider.cs

using System;
using System.Web;
using System.Web.SessionState;

namespace MyNamespace
{
    public class MyProvider : IHttpHandler, IReadOnlySessionState
    {
        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
        }
    }
}

JSONオブジェクトを受信して​​返すプロバイダーを作成する場合は、リクエストとレスポンスのクラスを作成してから、ハンドラーを次のように設定できます。

MyProvider.cs(JSONオブジェクトの処理)

using System;
using System.Runtime.Serialization.Json;
using System.Web;
using System.Web.SessionState;

namespace TestWebsite
{
    public class MyProvider : IHttpHandler, IReadOnlySessionState
    {
        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            var response = new Json.Response();
            try
            {
                var requestSerializer = new DataContractJsonSerializer(typeof(Json.Request));
                var request = (Json.Request)requestSerializer.ReadObject(context.Request.InputStream);

                // ...
            }
            catch (Exception ex)
            {
                response.Error = ex.ToString();
            }

            try
            {
                var responseSerializer = new DataContractJsonSerializer(typeof(Json.Response));
                context.Response.ContentType = "application/json";
                responseSerializer.WriteObject(context.Response.OutputStream, response);
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}
于 2012-12-20T21:42:46.430 に答える