前回のエントリでFlickrから画像を取得する部分のコードに違和感を持った人がいますかね? ルートの登録でもアクションの定義でも"url"って書いてるのに、使ってないじゃないか!と。 そうなんですよ。
非同期サンプル書くのにURLを渡して、そのURLに対してWebRequest(WebClientでも)で取得するのを書こうとしてたんだけど、エラーになるのでとりあえずは固定で対応という逃げの一手。 で、どういうことかというと、例えばProxy(string url)という感じでアクションを定義(前回のサンプルだとSync2とAsync3)する感じ。
ルートの定義は
routes.MapRoute(null,
"Proxy/{*url}",
new { controller = "WebRequest", action = "Proxy" }
);
みたいな。 ※WebRequestControllerっていうのがいたとして。
リクエストするときのURLが昨日の例だと
http://localhost/Proxy/http://farm1.static.flickr.com/131/353753310_1ed04f694c_m.jpg
みたいな。 でも、そこはURLエンコードしとかないとさ、っていうんで
http://localhost/Proxy/http%3A%2F%2Ffarm1.static.flickr.com%2F131%2F353753310_1ed04f694c_m.jpg
みたいな。 でね、これがね、ダメなの。
ゴルァ~!っと怒られるわけっす。 ところで、このエラーいつだれが出してるんですかね? ってことで、調べてたんだけど、たぶんRouting(コレだ!っていう資料を見つけられなかった)。 WebServerじゃないと思うんだけどどうでしょう。 だってね。ASP.NET WebFormで以下のように書くとこれはちゃんととれるんだもん。
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
var url = Request.QueryString["url"];
}
}
何がまずいのかな~、と。
URL Encodingに書かれてる、使っちゃいけない文字も含まれて無いし。だけど、MVCのRoutingってcontrollerとかactionとかっていうデータを構築してくれて、GetVirtualPathで勝手にURLエンコードした文字列返してくれるじゃないっすか。
VirtualPathData.VirtualPath プロパティ (System.Web.Routing)
その辺については特に書かれてないんだけど。 でも、Routeを登録するときにワイルドカード指定できるでしょ。 ワイルドカード内のスラッシュ'/'はエンコードしないじゃないですか。 もしやと、思って、UrlEncodeしないで試してみたんですよね。 もちろん':'は使えないんで除外します。
そしたらちゃんとリクエスト受け付けてくれるんですよ('/'を2個連続はダメだけど)。 http://localhost/Proxy/http/farm1.static.flickr.com/131/353753310_1ed04f694c_m.jpg このままだとアックションで取得出来るurlが"http/"で始まるんでちょっと感じ悪い。 ので、ルートの定義をちょっと変更。
routes.MapRoute(null,
"Proxy/{scheme}/{*url}",
new { controller = "WebRequest", action = "Proxy" },
new { scheme = @"(http|https)" }
);
みたいな。 アクションの定義も。
public ActionResult Proxy(string scheme, string url){...}
みたいな。 このルートを使うようにHtml.ActionLinkを書いて出力させると、以下のように。
<a href="/Proxy/http/farm1.static.flickr.com/131/353753310_1ed04f694c_m.jpg/">Flickr</a>
ふむ。
UrlEncodeしないとまずい文字を含めた、場合にどうなるかを試してみるのに、このUrlの最後に"/\<'09 in オレ>"をくっつけてみる。出力結果は↓。
<a href="/Proxy/http/farm1.static.flickr.com/131/353753310_1ed04f694c_m.jpg/%5C%3C'09%20in%20%E3%82%AA%E3%83%AC%3E">Flickr</a>
ちゃんとUrlEncodeしてくれてる。 けど、これだとまた"Bad Request"。 まぁ、'\'とか'<','>'をエンコードしてるとはいえ、使っちゃってるのがいけないんだな、と。 そこはUrlEncodeしてるんだから通して欲しいけどね。ってことで、使用不可の文字を使ってる場合は、UrlEncodeしててもBad Requestになるので気をつけよう。
<% = Html.ActionLink("Flickr", "Proxy", "WebRequest", new { scheme = "http", url = @"farm1.static.flickr.com/131/353753310_1ed04f694c_m.jpg/'09 in オレ" }, null)%>
↑こんな感じで、ActionLinkやUrl.Actionを使うのがいいみたい。 って、ことで実行結果は。
ASP.NET MVCは関係無いね。