Url encoded slash in URL - Stack Overflow
この投稿から始まって、以下のエントリにたどり着く。
Allowing special characters (forward slash, hash, asterisk etc) in ASP.Net MVC URL parameters
まさに、同じ問題に直面した内容。
Double/incomplete Parameter Url Encoding - Stack Overflow
↑ここへのリンクもあったから覗いてみたら、Uri.EscapeDataString メソッド (System)を使ったエンコーディングがあるということを初めて知る。なにこれ~、と思って試したけど、Server.UrlEncodeと同じだった。ガッカリ。いや、違う方が驚きか。
結局、Philさんの投稿のように"/"か他の文字に置換して区切ってしまうか、Base64エンコードで渡すのがいいのかな。Base64といえばFuturesに入ってるLinqBinaryModelBinderが使えるんだもんね。
というわけで試してみた。
登録するルートは以下の通り。
routes.MapRoute(null, "Proxy/{*base64url}", new { controller = "Images", action = "Proxy" } );
Controllerはシンプルに以下。LinqBinaryModelBinderを使うので、参照設定にFuturesのアセンブリを含めるのを忘れずに(単純に文字列で渡しておいて、Binary型にしなくてもConvert.FromBase64Stringでも可)。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Mvc.Ajax; using System.Net; using System.Text; using System.Data.Linq; namespace Mvc.RC.Controllers { public class ImagesController : Controller { public ActionResult Proxy(Binary base64url) { var web = new WebClient(); var url = Encoding.UTF8.GetString(base64url.ToArray()); var bytes = web.DownloadData(url); return File(bytes, web.ResponseHeaders["Content-Type"]); } } }Viewでリンクを作る時にBase64エンコードしたパラメータを渡す。
<% = Html.ActionLink("いぬ", "Proxy", "Images", new { base64url = Convert.ToBase64String(Encoding.UTF8.GetBytes( @"http://farm1.static.flickr.com/131/353753310_1ed04f694c_m.jpg" )) }, null)%>
これが出力されると以下のHTML。
<a href="/Proxy/aHR0cDovL2Zhcm0xLnN0YXRpYy5mbGlja3IuY29tLzEzMS8zNTM3NTMzMTBfMWVkMDRmNjk0Y19tLmpwZw==">いぬ</a>
リンクをクリックする。
ちゃんと犬が表示されました。一応、ブレークポイントセットして変数の中身を確認。ちょと見にくいけど、引数のbase64UrlにはBase64エンコードされたBinary型の値が入ってて、変数urlには元のURLがデコードされてる。
問題はぱっと見どこのURLを参照してるのかを判断出来ないところ。フレンドリURLとは言い難し。
ところで、Windows Live Writerから投稿すると、毎回無駄な改行が入るのはなんでなんだろう。