読者です 読者をやめる 読者になる 読者になる

SIN@SAPPOROWORKSの覚書

C#を中心に、夜な夜な試行錯誤したコードの記録です。

ASP.NET MVC Facebookテンプレートで日本語情報を取得する

VS2012 SP2 から提供されている、ASP.NET MVCFacebookテンプレートは、Graph API へのアクセスが、
クラス定義だけで利用できるようなっていて超便利です。しかし、日本語情報(日本語の姓名など)が必要になった時、ちょっと困ってしまいます。

Graph API で日本語情報を取得するには、「locale=ja_JP」というパラメータを追加するだけなのですが、
拡張メソッドでは、GraphAPIへのリクエストが完全にラップされているため、パラメータを追加する余地がないのです。

今回は、このパラメータを追加する方法を紹介したいと思います。


1 基本アクセス

Facebookテンプレートでは、自分の情報を取得するコードが雛形として提供されています。


public class HomeController : Controller {
        [FacebookAuthorize("email", "user_photos")]
        public async Task<ActionResult> Index(FacebookContext context) {
            if (ModelState.IsValid) {
                var user = await context.Client.GetCurrentUserAsync<MyAppUser>();
                return View(user);
            }
            return View("Error");
        }


必要な情報(カラム)をMyAppUserクラスのプロパティとして定義し、GetCurrentUserAsyncという拡張メソッドを呼び出すだけです。


public class MyAppUser {
        public string Id { get; set; }
        public string Name { get; set; }
}

例えば、MyAppUserクラスを上のように定義(雛形を修正)したとしたら、GraphAPIへのリクエストは、次のようになります。


https://graph.facebook.com/me?fields=id,name

※アクセストークンに関しては省略しています。


2 GetFacebookObjectAsync

先のコードを一つ低レベルメソッドGetFacebookObjectAsyncで書くと次のようになります。


 
var user = await context.Client.GetFacebookObjectAsync<MyAppUser>("me");
 

これでも、まだFieldsへの展開(?fields=id,name)がラップされているため、パラメータを追加する方法がありません。
たとえば、"me"のところを"me?locale=ja_JP"と指定すると例外で落とされてしまいます。

これは、与えられた型情報からFieldsへのパラメータを生成するヘルパであるFacebookQueryHelper.GetFields()が、パラメータの接続子である?まで生成しているためです。

001

例外で落とされるのは、パラメータの接続で&が使用されず、生成されるURLが"/me?locale=ja_JP?fields=id,name"となってしまうためです。


3 GetTaskAsync

先のコードをさらに低レベルメソッドGetTaskAsyncで書くと次のようになります。


 
var fields = FacebookQueryHelper.GetFields(typeof (MyAppUser));
var path = "me" + fields;
var user = await context.Client.GetTaskAsync<MyAppUser>(path);
 

やっと、パラメータを全部自由に定義できるところまで来たようです。

4「locale=ja_JP」追加

それでは、「locale=ja_JP」を追加してみます。


 
var fields = FacebookQueryHelper.GetFields(typeof (MyAppUser));
var path = "me" + fields + "&locale=ja_JP";
var user = await context.Client.GetTaskAsync<MyAppUser>(path);
 

002
どうやら無事、日本語名が取得できたようです。

003
↑日本語対応にしたFacebookテンプレートの雛形

それにしても、"?"まで付けてしまう、FacebookQueryHelperが、すごく乱暴に感じるのは私だけでしょうか・・・