kikki's tech note

技術ブログです。UnityやSpine、MS製品など技術色々について解説しています。

ASP.NET MVCの環境でRedirectかつPOSTする方法

本章では、ASP.NET MVCでサーバー側でリダイレクトしつつPOSTする方法について、共有します。

はじめに

外部サイトにリダイレクトする場面は、GETで直接サイトに飛ぶケースが多いです。しかし、外部サイトのAPIを利用したシングル・サインオン等の処理では、POSTする必要があります。もし、POSTする値を利用ユーザに見せたくない場合は、サーバーで処理を行う必要があります。
そのため、サーバーでPOSTに必要な値を作りつつ、リダイレクトする方法についてお伝えします。

手法

方法としては、「ActionResult」を継承したクラスを用意します。そしてリダイレクトの代わりにPOSTに必要な値を含む「html」の「form」を作り、「ExecuteResult」メソッドの中で「Response」に対して外部サイトからのレスポンスを返すよう設定します。
そして今回、日本での古いサイト*1にも対応できるよう、エンコードも設定できるよう調整します。

コード

以下が利用するライブラリです。

    public class EncodedActionResult : ActionResult
    {
        public string Url { get; private set; }

        public Dictionary<string, object> PostData { get; private set; }

        public string Encoding { get; private set; }

        private string BuildPostForm(string Url, Dictionary<string, object> PostData, string Encoding = null)
        {
            string formId = "__PostForm";

            StringBuilder strForm = new StringBuilder();
            strForm.AppendLine(@"<html>");
            strForm.AppendLine(@"<head>");
            strForm.AppendLine(@"<meta http-equiv='content-type' content='text/html; charset=" + Encoding + "'>");
            strForm.AppendLine(@"</head>");

            strForm.AppendLine(@"<body onload=""document.charset='" + Encoding + @"';document.forms[0].submit();"">");
            strForm.AppendLine(string.Format(@"<form id='{0}' name='{0}' action='{1}' method='POST' accept-charset='" + Encoding + "'>", formId, Url));
            foreach (var item in PostData)
            {
                strForm.AppendLine(string.Format(@"<input type='hidden' name='{0}' value='{1}'/>", item.Key, item.Value));
            }
            strForm.AppendLine(@"</form>");
            strForm.AppendLine(@"</body>");
            strForm.AppendLine(@"</html>");

            return strForm.ToString();
        }

        public static EncodedActionResult RedirectAndPost(string url, Dictionary<string, object> postData, string encoding = null)
        {
            return new EncodedActionResult(url, postData, encoding);
        }

        public override void ExecuteResult(ControllerContext context)
        {
            var strHtml = this.BuildPostForm(this.Url, this.PostData, this.Encoding);
            context.HttpContext.Response.Write(strHtml);
        }

        public EncodedActionResult(string url, Dictionary<string, object> postData, string encoding = null)
        {
            this.Url = url;
            this.PostData = postData ?? new Dictionary<string, object>();
            this.Encoding = encoding ?? "utf-8";
        }
    }

利用例は、以下の通りです。

var result = EncodedActionResult.RedirectAndPost("http://google.co.jp/hogehoge", new Dictionary<string, object>{{"HOGEHOGE", "hogehoge" }}, "shift_jis");
return (ActionResult)result;

これでユーザにPOSTしている値を知られることなく、外部サイトへのリダイレクトができます。
リダイレクト後のURLも外部サイトのURLそのままであるため、ユーザにも優しい仕様です。

筆休め

ユーザに情報を秘匿しつつ外部サイトと連携する場面は、そう多くはないかもしれませんが、ポイントポイントで必要となることがあるので是非利用してみてください。

以上、「ASP.NET MVCの環境でRedirectかつPOSTする方法」でした。

*1:Shift-JISがデフォルトエンコードといったサイト

※無断転載禁止 Copyright (C) 2015 kikkisnrdec All Rights Reserved.