工作的程式師

與我對談,第 4 篇:Feliza 發聲

Ted Neward

 

Ted Neward
我們現在正在跑向終點線。在本系列的第一列介紹對流層 (請參閱 msdn.microsoft.com/magazine/hh781028)。第二部分介紹了 Feliza,F # 元件的一些簡單的字串解析聽起來合理地像壞的精神病學家的把戲的做法 (請參見 msdn.microsoft.com/magazine/hh852597)。第三部分有線的對流層與 Feliza Web 網站 (以便對流層從 Web 網站,而不是一個駐留在其自己的伺服器上的腳本接收其命令) 所以我們能做的最後接線獲取 Feliza (請參見 msdn.microsoft.com/magazine/hh975378)。現在,我們和完成佈線工作變成 Feliza 松世界。

記得,最後一塊,從我們的 Feliza 能夠採取撥打電話的夢想是在這一刻,對流層 API,受到的限制,但 Feliza 有沒有用短信的問題 — — 在 425-247-3096 — — 或與 IM (使用 feliza@tropo.im 的註冊的 Jabber 控制碼),所以我們會繼續這樣。請記住,是否綁定的一組選項可供選擇,因此,如果我們想要到固定輸入限制 Feliza,我們可以輕鬆地回到聲音,對流層可以輕鬆地處理語音輸入。然而,為 Feliza 的目的,是不會罷工我作為偉大的使用者體驗:"你好 !如果你是鬱悶,說 '鬱悶' ; 如果你只感覺不好,說,'的感覺差' ; 如果你準備好要殺死一個自動化的治療系統,說 '模、 模具、 模具' ... ..."

儘管所限,Feliza 仍然可以説明人們 (嗯,排序的),所以讓我們繼續。還記得我們需要 Feliza,站在後面一個 Web 網站,知道如何回應對流層休息/JSON 請求對流層火災看著我們,因此我們需要能夠解釋傳入 JSON,把它交給 Feliza,然後生成答覆。這意味著我們需要一種 ASP.NET MVC 結構來表示傳入 JSON,和一個來表示傳出回應。

創建 Microsoft.net 框架類相匹配與這 (以便 ASP.NET MVC 能做解析 JSON 的繁重) 是非常簡單,如中所示圖 1

圖 1 匹配對流層結構針對 JSON 物件到.net 類

public class Session
{
  public string accountId { get; set; }
  public string callId { get; set; }
  public class From
  {
    public string id { get; set; }
    public string name { get; set; }
    public string channel { get; set; }
    public string network { get; set; }
  }
  public From from { get; set; }
  public class To
  {
    public string id { get; set; }
    public string name { get; set; }
    public string channel { get; set; }
    public string network { get; set; }
  }
  public To to { get; set; }
  public string id { get; set; }
  public string initialText { get; set; }
  public string timestamp { get; set; }
  public string userType { get; set; }
};

不是所有的中顯示的屬性圖 1 總是會填充,但它提供了如何映射 JSON 物件對對流層結構工作的榜樣。

因此,這似乎是一個非常簡單的例子,解析傳入 JSON ("會話"物件),提取的 initialText 欄位中的文本,生成的回應物件和手回,如中所示圖 2

解析 JSON 的圖 2

[AcceptVerbs("GET", "POST")]
public ActionResult Index(Tropo.JSON.Session session)
{
  string incoming = session.initialText;
  object felizaResponse = new
  {
    tropo = new object[]
    {
      new
      {
        ask = new Tropo.JSON.Ask()
        {
          say = new Tropo.JSON.Say() {
          value = "I'm Feliza.
What about '" + incoming +
            "' would you like to talk about?"
          },
          choices = new Tropo.JSON.Ask.Choices() {
            value = "[ANY]"
          }
        }
      }
    }
  };
  return Json(felizaResponse);
}

不幸的是,我們遇到的 ASP.NET MVC JSON 序列化程式的限制,因為任何它認為在返回的物件中的空值將變成"空"值的 JSON 序列化的反應,和對流層具有 null 值 JSON 領域的若干問題。 幸運的是,我們可以修復這通過使用自訂的 JSON 序列化程式 (在此情況下,詹姆斯 · 牛頓國王的優秀 Json.NET 序列化程式在 bit.ly/a27Ou),它可以被配置為不序列化空值。 此更改的代碼稍有返回自訂的行動 (感激地獲得來自 bit.ly/1DVucR) 而不是標準 (請參閱 圖 3)。

圖 3 定制的行動

public class JsonNetResult : ActionResult
{
  public Encoding ContentEncoding { get; set; }
  public string ContentType { get; set; }
  public object Data { get; set; }
  public JsonSerializerSettings SerializerSettings { get; set; }
  public Formatting Formatting { get; set; }
  public JsonNetResult() { SerializerSettings =
    new JsonSerializerSettings(); }
  public override void ExecuteResult(ControllerContext context)
  {     
    if (context == null)
      throw new ArgumentNullException("context");
    HttpResponseBase response = context.HttpContext.Response;
    response.ContentType = !string.IsNullOrEmpty(ContentType) ?
ContentType : "application/json";
    if (ContentEncoding != null)
      response.ContentEncoding = ContentEncoding;
    if (Data != null)
    {
      JsonTextWriter writer =
        new JsonTextWriter(response.Output) 
        { Formatting = Formatting };
      JsonSerializer serializer =
        JsonSerializer.Create(SerializerSettings);
      serializer.Serialize(writer, Data);
      writer.Flush();
    }
  }
}

然後,在控制器中,我們使用此行動而不是基於 JSON 的並確保將其配置為不發送回空值:

[AcceptVerbs("GET", "POST")]
public ActionResult Index(Tropo.JSON.Session session)
{
  string incoming = session.initialText;
  object felizaResponse = // ...;
  JsonNetResult jsonNetResult = new JsonNetResult();
  jsonNetResult.SerializerSettings.NullValueHandling =
    NullValueHandling.Ignore;
  jsonNetResult.Data = felizaResponse;
  return jsonNetResult;
}

所以在這一點上,玩的代碼在家裡的那些讀者,伺服器是能夠採取傳入的 SMS 消息,挑出傳入的文本並生成回應回來的。 您很可能會猜接下來。

高興見到你,Feliza

它是二進位檔案 Feliza F # 從這一系列的第二列中拉出完成電路的時間。 複製在已編譯的二進位檔案從舊的代碼,或者,如果您願意,ASP.NET MVC 對流層解決方案中創建一個 (二) F # 庫專案、 代碼標記為根據的 Feliza 專案和副本的 TropoApp 專案。 (請確保 ASP.NET MVC 專案還知道 F # 依存關係,特別是 FSharp.Core.dll)。

現在,生成回應是一樣微妙採取傳入的文本,將它傳遞給 Feliza1 的回應方法和捕獲結果到返回 JSON,如中所示 圖 4

圖 4 生成回應

[AcceptVerbs("GET", "POST")]
public ActionResult Index(Tropo.JSON.Session session)
{
  object felizaResponse = new
  {
    tropo = new object[]
    {
      new
      {
        ask = new Tropo.JSON.Ask()
        {
          say = new Tropo.JSON.Say() {
            value = Feliza1.respond(session.initialText)
          },
          choices = new Tropo.JSON.Choices() {
            value = "[ANY]"
          }
        }
      }
    }
  };
  JsonNetResult jsonNetResult = new JsonNetResult();
  jsonNetResult.SerializerSettings.NullValueHandling =
    NullValueHandling.Ignore;
  jsonNetResult.Data = felizaResponse;
  return jsonNetResult;
}

它真的是那麼容易 — —,如果電話是非常方便的將其拉出,你會看到,發短信 Feliza 在一種對話的結果。 她不是世界上最聰明的聊天機器人,但為 F # 在她身後的核心,有很的多我們可以做改善她的反應。

語音或 SMS 併入應用程式

Feliza 的做的而且現在世界可以高枕無憂,任何人都知道,如果熬夜晚,只是希望有人將文本、 Feliza 的準備和等待他們。 當然,它不會一次非常令人滿意的談話,因為大部分時間她不會有了線索,她正在看的書。

對流層 API 有一些有趣的怪癖,但顯然有一些大的權力。 雙模式 — — 承載的腳本,以及"Web API"— — 當思考如何納入語音、 短信或即時消息應用程式提供一些有趣的靈活性。

Feliza 的網站上,也可以加強在多方面 — — 例如,對於那些更多移動 Web-頭腦的人,似乎適當創建一組靜態 HTML5 頁使用 jQuery 的命中 Feliza 與鍵入的文字並將追加到頁的回應。 實質上,對流層通過其接收輸入,提供了一套新的"管道"和理想的情況是這些管道將規範其輸入到一套 JSON 結構,以簡化的 ASP.NET MVC 終結點代碼。 並明確對流層故事將適合井旁其他與客戶或使用者的通訊手段。 其它明顯的管道,會很有趣,若要添加用於 Twitter 或 Facebook,例子。 (對流層有能力掛鉤到 Twitter,順便說一句,這將簡化該特定通道,但 Facebook 通道將是我們親手打造的東西。

現在,其他主題緊迫,所以它是向 Feliza 揮手告別,並移動的時間。 別擔心,她還是會有當你感到孤獨。 在此期間...

編碼愉快 !

Ted Neward 是 Neudesic LLC 建築顧問。他寫了一百多篇,是一個 C# MVP 和 INETA 的演講者已創作和合著了十幾本書,包括最近公佈"專業 F # 2.0"(Wrox,2010年)。他諮詢、 定期指導。他在到達 ted@tedneward.com 如果你感興趣讓他來和你的團隊工作或閱讀他在博客上的 blogs.tedneward.com