22

JSONP WCF エンドポイントがあり、504 エラーが発生する理由を突き止めようとしています。

HTTP/1.1 504 Fiddler - Receive Failure
Content-Type: text/html
Connection: close
タイムスタンプ: 11:45:45:9580
ReadResponse() が失敗しました: サーバーはこの要求に対する応答を返しませんでした。

エンドポイント内の任意の場所にブレークポイントを設定し、コードをステップ実行して、応答に必要なデータが正常に収集されることを確認し、コードの最終行に到達すると、WCF 呼び出しから抜け出すとすぐに 504 エラーが発生します。 これは先週働いていました!

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceContract(Name = "NegotiateService", Namespace = "http://rivworks.com/Services/2009/01/15")]
public class NegotiateService //: svcContracts.INegotiateService
{
    public NegotiateService() { }

    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Json)]
    public dataObjects.NegotiateSetup GetSetup(string method, string jsonInput)
    {
        dataObjects.NegotiateSetup resultSet = new dataObjects.NegotiateSetup();

        using (RivFeedsEntities1 _dbFeed = new FeedStoreReadOnly(AppSettings.FeedAutosEntities_connString, "", "").ReadOnlyEntities())
        {
            using (RivEntities _dbRiv = new RivWorksStore(AppSettings.RivWorkEntities_connString, "", "").NegotiationEntities())
            {
                // Deserialize the input and get all the data we need...
                Newtonsoft.Json.Linq.JObject o = Newtonsoft.Json.Linq.JObject.Parse(jsonInput);
                string urlRef = String.Format("{0}", o["ref"]).Replace("\"", "");
                string clientDate = String.Format("{0}", o["dt"]).Replace("\"", "");
                string ProductID = String.Format("({0})", o["productId"]).Replace("\"", "");
                string SKU = String.Format("{0}", o["sku"]).Replace("\"", "");
                string env = String.Format("{0}", o["env"]).Replace("\"", "");

                IList<Product> efProductList = null;
                Product workingProduct = null;
                vwCompanyDetails workingCompany = null;
                bool foundItem = false;

                if (!String.IsNullOrEmpty(SKU))
                    efProductList = _dbRiv.Product.Include("Company").Where(a => a.SKU == SKU).ToList();
                else if (!String.IsNullOrEmpty(ProductID))
                    efProductList = _dbRiv.Product.Include("Company").Where(a => a.ProductId == new Guid(ProductID)).ToList();

                foreach (Product product in efProductList)
                {
                    if (String.IsNullOrEmpty(product.URLDomain))
                    {
                        var efCompany = _dbRiv.vwCompanyDetails
                                              .Where(a => a.defaultURLDomain != null && a.CompanyId == product.Company.CompanyId)
                                              .FirstOrDefault();

                        if (efCompany != null && urlRef.Contains(efCompany.defaultURLDomain))
                        {
                            foundItem = true;
                            workingProduct = product;
                            workingCompany = efCompany;
                        }
                    }
                    else
                    {
                        if (urlRef.Contains(product.URLDomain))
                        {
                            foundItem = true;
                            workingProduct = product;
                            workingCompany = _dbRiv.vwCompanyDetails
                                                   .Where(a => a.CompanyId == product.Company.CompanyId)
                                                   .FirstOrDefault();
                        }
                    }
                }

                if (foundItem)
                {
                    try
                    {
                        // Update the resultSet...
                        if (workingProduct != null && workingCompany != null)
                        {
                            string rootUrl = String.Empty;
                            try
                            {
                                rootUrl = AppSettings.RootUrl;
                            }
                            catch
                            {
                                rootUrl = env + @"/";
                            }
                            resultSet.button = workingProduct.ButtonConfig;
                            resultSet.swfSource = String.Format(@"{0}flash/negotiationPlayer.swf", rootUrl);
                            resultSet.gateway = rootUrl;
                            resultSet.productID = workingProduct.ProductId.ToString();
                            resultSet.buttonPositionCSS = workingProduct.buttonPositionCSS;
                        }
                    }
                    catch (Exception ex)
                    {
                        log.WriteLine("      ERROR: ", ex.Message);
                        log.WriteLine("STACK TRACE: ", ex.StackTrace);
                    }
                }
            }
        }
        return resultSet;
    }
}

私のweb.config:

<!-- WCF configuration -->
<system.serviceModel>
  <behaviors>
    <endpointBehaviors>
      <behavior name="JsonpServiceBehavior">
        <webHttp />
      </behavior>
    </endpointBehaviors>
  </behaviors>

  <services>
    <service name="RivWorks.Web.Service.NegotiateService">
      <endpoint address=""
              binding="customBinding"
              bindingConfiguration="jsonpBinding"
              behaviorConfiguration="JsonpServiceBehavior"
              contract="RivWorks.Web.Service.NegotiateService" />
    </service>
  </services>

  <extensions>
    <bindingElementExtensions>
      <add name="jsonpMessageEncoding" type="RivWorks.Web.Service.JSONPBindingExtension, RivWorks.Web.Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </bindingElementExtensions>
  </extensions>

  <bindings>
    <customBinding>
      <binding name="jsonpBinding" >
        <jsonpMessageEncoding />
        <httpTransport manualAddressing="true"/>
      </binding>
    </customBinding>
  </bindings>    
</system.serviceModel>

私が言ったように、コードは最後まで実行されるので、応答を送信しない理由を理解しようとしています。

4

7 に答える 7

31

申し訳ありませんが、直接的な解決策はありませんが、WCF関連の問題を追跡すると、WCFトレースログをオンにしてシナリオを実行し、SvcTraceViewer.exeのログを確認することがわかりました。助けになります...あなたは物事があなたに崩壊している可能性が高いスタックへのある程度の可視性を得るでしょう。

WCFサービス構成エディター」を使用して、さまざまなログ設定とレベルのオン/オフを切り替えることができます。

于 2010-01-28T19:22:15.120 に答える
8

同様の問題が発生したばかりで、トレースがそれを特定する唯一の方法でした(@Tylerによってすでに提案されているように)。また、サーバーから HTTP 504 が返され、Visual Studio でサービスをデバッグしても例外は表示されませんでした。実際、デバッガーからは、サービスが適切に応答を返したように見えました。

私の特定のケースでは、エラーの原因は、データ コントラクト クラスのメンバーの 1 つが列挙型であり、値が EnumMemberAttribute でマークされていないことでした。

WCF でのトレースの構成の詳細については、こちらを参照してください。また、WCF サービス データ コントラクトの列挙型については、こちらを参照してください

于 2011-07-14T16:02:21.203 に答える
5

この特定の問題については、最終的に接続文字列になりました。Web サービスにあるため、Web サイトの構成ファイルからプルしていませんでした。少しの魔法 (ハード コーディング) を使用して、コンテキストを最終的にアクティブにし、システムが機能し始めました。他の根本的なエラーがポップアップしているため、まだこの 504 を完全に処理していません。

2010 年 2 月 1 日 - 接続文字列エラーを解決したところ、いくつかの基本的な EF エラーが見つかりましたが、これらはすぐに解決されました。現在、稼働を再開しています。

于 2010-01-29T16:27:40.203 に答える
4

私は同じ問題を数回抱えていました:

  • あるシナリオでは、パブリックプロパティの1つ(DataMember)にはゲッターのみがあり、セッターはありませんでした。そのDataMemberをgetterとsetterの両方を持つように変更すると、問題が解決しました。

  • 他のシナリオでは、EF4 POCO(ナビゲーションプロパティが入力されている)をJSONとの間でシリアル化/逆シリアル化していたため、逆シリアル化中に再帰的なループが発生しました。POCOの属性を変更し[DataContract(IsReference = true)]て再帰ループの問題を解決しましたが、DataContractJsonSerializerは参照をサポートしていないため、形式をXMLに切り替える必要がありました。(PS -WEB APIでは、デフォルトのJSONシリアライザーはJSON.NETになり、問題なく参照を処理します)。

ヒント:他の人が示唆しているように、WCFトレースロギングは504エラーを解決するための友達です。

于 2011-10-24T18:38:09.777 に答える
4

うまくいけば、これは誰かを助けるでしょう。JSON を返す WCF レスト サービスがあり、フィドラーから 504 が返されました。ReadResponse() が失敗しました: サーバーは、この要求に対する応答を返しませんでした。

私の問題は、次のようなモデルを返していたことです。

public class ServerResult
{
    public StatusCode Status { get; set; }
    public object Data { get; set; }

    public static ServerResult CreateServerResult(StatusCode status)
    {
        return new ServerResult() { Status = status };
    }

    public static ServerResult CreateServerResult(StatusCode status, object data)
    {
        return new ServerResult() { Data = data, Status = status };
    }
}

wcf は、オブジェクトをエンコードする方法を理解していないようです。私が返していたオブジェクトは、文字列と整数だけでまったく問題ありませんでした。これを機能させるには、これに対する応答を変更する必要がありました。

public class ServerResult<T>
{
    public StatusCode Status { get; set; }
    public T Data { get; set; }

    public static ServerResult<T> CreateServerResult(StatusCode status)
    {
        return new ServerResult<T>() { Status = status };
    }

    public static ServerResult<T> CreateServerResult(StatusCode status, T data)
    {
        return new ServerResult<T>() { Data = data, Status = status };
    }
}
于 2012-07-20T08:25:08.567 に答える
0

誰にでも役立つ場合は、Web Api から Entity Framework 4 の「EntityObject」のリストを返そうとしたときに、これに遭遇しました。それを修正するために、EntityObject はシリアライズされるのを好まないので、明示的な選択を行うようにしました。

return Request.CreateResponse(HttpStatusCode.OK, people.Select(p => new {
    p.Id,
    p.Name,
    p.CreateDate
}));
于 2015-09-30T15:14:08.680 に答える