2014-10-07 73 views
0

我正在嘗試使用名爲FatSecret Sharp的包裝器調用Fatsecret API的基本ASP.NET應用程序,但是當出現此錯誤時我嘗試從我的JS腳本進行服務器端方法調用,並且想確定如何成功使用此包裝器創建Web應用程序。當調用FatSecret Sharp API時此時無法啓動異步操作

你會注意到來自包裝器的API調用明確提到它是「同步的」,所以我認爲這就是拋出錯誤,我只是不知道爲什麼,或者我怎樣才能成功地使用該調用一個Web應用程序。

這裏是我的代碼:

的Javascript

var jsonData; 

function search() { 
    var element = document.getElementById("searchField") 
    var searchTerm = element.value; 

    callAJAX("FoodSearchExample", searchTerm); 
} 

function callAJAX(requestMethod, term) { 
    var pageMethod = "default.aspx/" + requestMethod; 

    $.ajax({ 
    url: pageMethod, 
    data: JSON.stringify({ searchTerm : term }), 
    type: "POST", 
    contentType: "application/json",  
    dataType: "JSON", 
    timeout: 600000, 
    success: function (result) { 
     ajaxCallback(result.d); 
    }, 
    error: function (xhr, status) { 
     alert(status + " - " + xhr.responseText); 
    } 
}); 

return false; 
} 

function ajaxCallback(serverResponse) { 
    if (serverResponse !== "loadLocations") { 
     //jsonData = JSON.parse(serverResponse); 
     alert(serverResponse); 
    } 
    else 
     alert("error"); 
} 

C#

namespace HELP_Testing 
{ 

public partial class _default : System.Web.UI.Page 
{ 
    private static string consumerKey = "key (removed from question)"; 
    private static string consumerSecret = "secret (removed from question)"; 

    [WebMethod] 
    public static string FoodSearchExample(string searchTerm) 
    { 
     FoodSearch foodSearch = new FoodSearch(consumerKey, consumerSecret); 
     string str = ""; 

     var response = foodSearch.GetResponseSynchronously(new FoodSearchRequest() 
     { 
      SearchExpression = searchTerm 
     }); 

     List<Food> foods = new List<Food>(); 

     if (response.HasResults) 
     {    
      Food f; 

      foreach (var food in response.foods.food) 
      { 
       f = new Food(); 
       f.FoodId = food.food_id; 
       f.FoodType = food.food_type; 
       f.FoodName = food.food_name; 
       foods.Add(f); 
      } 
     } 
     else 
      Console.WriteLine("No results from term"); 

     JavaScriptSerializer serializer = new JavaScriptSerializer(); 
     str = serializer.Serialize(foods); 

     return str; 
    } 

    protected void Page_Load(object sender, EventArgs e) 
    { 

    } 
} 

}

HTML

<%@ Page Language="C#" AutoEventWireup="true" Async="True" CodeBehind="default.aspx.cs"  Inherits="HELP_Testing._default" %> 

<!DOCTYPE html> 

<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server">  
    <script type="text/javascript" src="scripts/default.js"></script> 
    <script type="text/javascript" src="scripts/jquery-1.11.1.js"></script> 
    <title>Healthy Eating Life Planner</title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div> 
     <input type="text" name="Food Search" id="searchField" /> 
     <button type="submit" onclick="search()">Search</button> 
    </div> 
    </form> 
</body> 
</html> 

完整的錯誤消息是:

此時無法啓動異步操作。異步操作只能使用異步處理程序或模塊 或頁生命週期中的某些事件期間啓動。如果執行頁面時發生此異常,請確保頁面標記爲Async = true。此異常也可能表示嘗試調用「異步無效」方法,該方法在ASP.NET請求處理中通常不支持 。相反,異步方法應該返回一個任務,調用者應該等待它」

回答

1

是,the problem is in GetResponseSynchronously。輪詢完成是非常值得懷疑的做法。

有一對夫婦的方式來解決這個問題。一個是拋出了FatSearch CSHARP庫,並使用HttpClient寫信給自己的JSON API。這種方法是清潔的,但意味着你必須編寫更多的代碼。

的另一種方法是wrap the sort-of-EBAP APIs from FatSearch CSharp as async-compatible methods。在這種情況下,重要的成員爲GotResult,GotErrorStartRequestAsync。請注意,您的網絡方法將變爲async

+0

額外的旁註:事實證明,包裝有一個異步選項,但我們還沒有弄清楚如何使用它。 – mcraen 2014-10-10 12:37:55

0

而不是調用的 公共任務GetResponseSynchronously(TRequest請求)之類的示例控制檯應用程序表明,在諸如MVC web環境,最好是增加一個異步方法,如一個我下面的成功寫道:

/// <summary> 
    /// Gets the response Asynchronously. 
    /// </summary> 
    /// <param name="request">The request.</param> 
    /// <returns>A parsed response, or throws an exception.</returns> 
    public async Task<TResponse> GetResponseAsynchronously(TRequest request) 
    { 

     var requestUrl = CreateRequestUrl(request); 

     HttpClient APIRequest = new HttpClient(); 

     var response = await APIRequest.GetAsync(requestUrl).ConfigureAwait(false); 

     response.EnsureSuccessStatusCode(); 

     string downloadedString = await response.Content.ReadAsStringAsync(); 


     var result = ConvertClientResultString(downloadedString);      

     return result; 
    } 

需要注意的是可以獲得無縫的結果是很重要的,你需要添加一個響應處理方法,如下面的一個改變Service4u2Lib的BaseJsonService.cs:

/// <summary> 
    /// Handles the client result string. 
    /// </summary> 
    /// <param name="downloadedString">The downloaded string.</param> 
    public TResultType ConvertClientResultString(string downloadedString) 
    { 
     // Check for html doctype and report error if found. 
     int takeLength = downloadedString.Length > 20 ? 20 : downloadedString.Length; 
     if (downloadedString.Substring(0, takeLength).Contains("!DOCTYPE html")) 
      HandleClientError(new NotSupportedException("The service call returned html and not json")); 

     var result = new TResultType(); 

     string json = downloadedString; 

     if (result is IJSONMassager) 
     { 
      json = ((IJSONMassager)result).MassageJSON(downloadedString); 
     } 

     if (result is IJSONSelfSerialize<TResultType>) 
     { 
      result = ((IJSONSelfSerialize<TResultType>)result).SelfSerialize(json); 
     } 
     else 
      result = JsonHelper.Deserialize<TResultType>(json); 

     if (GotResult != null) 
      GotResult(this, new EventArgs<TResultType>() { Argument = result }); 

     return result; 
    } 

基本上我們重新對現有對象進行洗牌,以使它們與可以使用.ConfigureAwait(false)處理請求的HTTPClient對象一起工作;確保回調發生的方法。

相關問題