// Copyright (c) 2008, NTT DATA Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Configuration;
using TERASOLUNA.Fw.Common.Logging;

namespace TERASOLUNA.Fw.Web
{
    /// <summary>
    /// Webアプリケーションで使用するUtilityクラスです。
    /// </summary>
    /// <remarks>
    /// Webアプリケーションで使用する各種機能を提供するUtilityクラスです。
    /// </remarks>
    public abstract class WebUtils
    {
        /// <summary>
        /// <see cref="ILog"/> 実装クラスのインスタンスです。
        /// </summary>
        /// <remarks>
        /// ログ出力に利用します。
        /// </remarks>
        private static ILog _log = LogFactory.GetLogger(typeof(WebUtils));

        /// <summary>
        /// 処理結果IDを格納するキーです。
        /// </summary>
        /// <remarks>
        /// この定数の値は "TERASOLUNA_PageID" です。
        /// </remarks>
        internal static readonly string PAGE_ID = "TERASOLUNA_PageID";

        /// <summary>
        /// クエリ文字列のキーと値を保持するディクショナリを格納するキーです。
        /// </summary>
        /// <remarks>
        /// この定数の値は "TERASOLUNA_QueryParams" です。
        /// </remarks>
        internal static readonly string QUERY_PARAMETERS = "TERASOLUNA_QueryParams";

        /// <summary>
        /// web.config ファイル内の system.web 要素内の customErrors 要素名。
        /// </summary>
        /// <remarks>
        /// この定数の値は "system.web/customErrors" です。
        /// </remarks>
        private static readonly string CUSTOM_ERRORS_PATH = "system.web/customErrors";

        /// <summary>
        /// customErrors 要素の DefaultRedirect 属性名。
        /// </summary>
        /// <remarks>
        /// この定数の値は "DefaultRedirect" です。
        /// </remarks>
        private static readonly string DEFAULT_REDIRECT = "DefaultRedirect";

        /// <summary>
        /// 指定したページ ID の画面へ遷移します。
        /// </summary>
        /// <param name="pageID">画面遷移設定ファイルに設定した、遷移先ページ ID。</param>
        /// <remarks>
        /// <para>
        /// web.config に <see cref="HttpModule.TransitionListenerImpl"/> が定義されていた場合、
        /// サーバー側の処理完了時に画面遷移処理をおこないます。
        /// 画面遷移処理は <see cref="WebUtils.Transit(String)"/> でページ ID がセットされている場合に、
        /// 画面遷移設定ファイルからページ ID に対応した遷移先 URL を取得します。
        /// 遷移先 URL を取得後、クライアントブラウザに遷移先 URL へのリダイレクト命令を送ります。
        /// </para>
        /// <para>
        /// 1つのイベントハンドラ内で2度以上 <see cref="WebUtils.Transit(String)"/> を呼んだ場合、
        /// 最後に呼んだ <see cref="WebUtils.Transit(String)"/> のページ IDが有効となります。
        /// </para>
        /// <para>
        /// web.config に <see cref="HttpModule.TransitionListenerImpl"/> の定義が必要です。
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="pageID"/> が null 参照です。
        /// </exception>
        public static void Transit(string pageID)
        {
            if (pageID == null)
            {
                ArgumentNullException exception = new ArgumentNullException("pageID");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "pageID"), exception);
                }
                throw exception;
            }
            if (pageID.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "pageID");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }
            HttpContext.Current.Items[PAGE_ID] = pageID;
        }

        /// <summary>
        /// 指定したページ ID の画面へ遷移します。
        /// また、画面遷移時に遷移先ページの URL に複数のクエリ文字列を追加します。
        /// </summary>
        /// <param name="pageID">画面遷移設定ファイルに設定した、遷移先ページ ID。</param>
        /// <param name="queries">遷移先URLに追加するクエリ文字列のキー文字列/値のコレクション。</param>
        /// <remarks>
        /// <para>
        /// web.config に <see cref="HttpModule.TransitionListenerImpl"/> が定義されていた場合、
        /// サーバー側の処理完了時に画面遷移処理をおこないます。
        /// 画面遷移処理は <see cref="WebUtils.Transit(String)"/> でページ ID がセットされている場合に、
        /// 画面遷移設定ファイルからページ ID に対応した遷移先 URL を取得します。
        /// 遷移先 URL を取得後、遷移先 URL にクエリ文字列を追加し、クライアントブラウザにリダイレクト命令を送ります。
        /// </para>
        /// <para>
        /// 1つのイベントハンドラ内で2度以上 <see cref="WebUtils.Transit(String)"/> を呼んだ場合、
        /// 最後に呼んだ <see cref="WebUtils.Transit(String)"/> のページ IDが有効となります。
        /// </para>
        /// <para>
        /// web.config に <see cref="HttpModule.TransitionListenerImpl"/> の定義が必要です。
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="pageID"/> が null 参照です。
        /// </item>
        /// <item>
        /// <paramref name="queries"/> が null 参照です。
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="pageID"/> が空文字列です。
        /// </exception>
        public static void Transit(string pageID, IDictionary<string, string> queries)
        {
            if (queries == null)
            {
                ArgumentNullException exception = new ArgumentNullException("queries");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "queries"), exception);
                }
                throw exception;
            }

            // null を空文字列に変換
            IDictionary<string, string> queryParams = new Dictionary<string, string>();
            foreach (string key in queries.Keys)
            {
                if (queries[key] == null)
                {
                    queryParams.Add(key, string.Empty);
                }
                else
                {
                    queryParams.Add(key, queries[key]);
                }
            }

            HttpContext.Current.Items[QUERY_PARAMETERS] = queryParams;
            Transit(pageID);
        }

        /// <summary>
        /// 指定したページ ID の画面へ遷移します。
        /// また、画面遷移時に遷移先ページの URL に1つののクエリ文字列を追加します。
        /// </summary>
        /// <param name="pageID">画面遷移設定ファイルに設定した、遷移先ページ ID。</param>
        /// <param name="queryKey">遷移先 URL に追加するクエリ文字列のキー文字列。</param>
        /// <param name="queryValue">遷移先 URL に追加するクエリ文字列の値文字列。</param>
        /// <remarks>
        /// <para>
        /// web.config に <see cref="HttpModule.TransitionListenerImpl"/> が定義されていた場合、
        /// サーバー側の処理完了時に画面遷移処理をおこないます。
        /// 画面遷移処理は <see cref="WebUtils.Transit(String)"/> でページ ID がセットされている場合に、
        /// 画面遷移設定ファイルからページ ID に対応した遷移先 URL を取得します。
        /// 遷移先 URL を取得後、遷移先 URL にクエリ文字列を追加し、クライアントブラウザにリダイレクト命令を送ります。
        /// </para>
        /// <para>
        /// 1つのイベントハンドラ内で2度以上 <see cref="WebUtils.Transit(String)"/> を呼んだ場合、
        /// 最後に呼んだ <see cref="WebUtils.Transit(String)"/> のページ IDが有効となります。
        /// </para>
        /// <para>
        /// web.config に <see cref="HttpModule.TransitionListenerImpl"/> の定義が必要です。
        /// </para>
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="pageID"/> が null 参照です。
        /// </item>
        /// <item>
        /// <paramref name="queryKey"/> が null 参照です。
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="pageID"/> が空文字列です。
        /// </item>
        /// <item>
        /// <paramref name="queryKey"/> が空文字列です。
        /// </item>
        /// </list>
        /// </exception>
        public static void Transit(string pageID, string queryKey, string queryValue)
        {
            if (queryKey == null)
            {
                ArgumentNullException exception = new ArgumentNullException("queryKey");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "queryKey"), exception);
                }
                throw exception;
            }
            if (queryKey.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "queryKey");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }
            if (queryValue == null)
            {
                queryValue = string.Empty;
            }

            IDictionary<string, string> queries = new Dictionary<string, string>();
            queries.Add(queryKey, queryValue);
            Transit(pageID, queries);            
        }

        /// <summary>
        /// 画面遷移機能で利用するページ ID を <see cref="HttpContext"/> から取得します。
        /// </summary>
        /// <returns>
        /// 存在する場合はページ ID の文字列。それ以外は null 参照。
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// 取得したページ ID が <see cref="String"/> ではない場合。
        /// </exception>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public static string GetPageID()
        {
            object pageID = HttpContext.Current.Items[WebUtils.PAGE_ID];

            if (pageID == null)
            {
                return null; 
            }
            string strPageID = pageID as string;
            if (strPageID == null)
            {
                InvalidOperationException exception = new InvalidOperationException(string.Format(Properties.Resources.E_INVALID_TYPE, "RESULT_ID"));
                if (_log.IsErrorEnabled)
                {
                    _log.Error(exception.Message, exception);
                }
                throw exception;
            }
            else
            {
                return strPageID;
            }
        }

        /// <summary>
        /// 現在のページの仮想アプリケーションルートパス以降のパスを取得します。
        /// </summary>
        /// <returns>現在のページの仮想アプリケーションルートパスより後のパス。</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public static string GetCurrentPagePath()
        {
            HttpRequest req = HttpContext.Current.Request;

            return _GetCurrentPagePath(req.ApplicationPath, req.CurrentExecutionFilePath);
        }

        /// <summary>
        /// 現在のページの仮想アプリケーションルートパス以降のパスを取得します。
        /// </summary>
        /// <param name="appPath">現在のページの仮想アプリケーションルートパス。</param>
        /// <param name="filePath">現在のページのパス。</param>
        /// <returns>現在のページの仮想アプリケーションルートパスより後のパス。</returns>
        /// <exception cref="ArgumentNullException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="appPath"/> が null 参照です。
        /// </item>
        /// <item>
        /// <paramref name="filePath"/> が null 参照です。
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="appPath"/> が空文字列です。
        /// </item>
        /// <item>
        /// <paramref name="filePath"/> が空文字列です。
        /// </item>
        /// <item>
        /// アプリケーションルートパス <paramref name="appPath"/> が不正です。
        /// <paramref name="appPath"/> の文字列長が <paramref name="filePath"/> の文字列長よりも長いです。
        /// </item>
        /// </list>
        /// </exception>
        private static string _GetCurrentPagePath(string appPath, string filePath)
        {
            if (appPath == null)
            {
                ArgumentNullException exception = new ArgumentNullException("appPath");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "appPath"), exception);
                }
                throw exception;
            }
            if (appPath.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "appPath");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }
            if (filePath == null)
            {
                ArgumentNullException exception = new ArgumentNullException("filePath");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "filePath"), exception);
                }
                throw exception;
            }
            if (filePath.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "filePath");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }
            if (appPath.Length > filePath.Length)
            {
                string message = string.Format(Properties.Resources.E_INVALID_FILE_PATH, appPath, filePath);
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }

            string currentPagePath = filePath;

            if (!("/".Equals(appPath)))
            {
                currentPagePath = filePath.Substring(appPath.Length);
            }

            return currentPagePath;
        }

        /// <summary>
        /// 現在のリクエスト先 URL が web.config 内の customErrors で定義されているページへのリクエストかどうか判断します。
        /// </summary>
        /// <returns>customErrors で定義されたページへのリクエストの場合 true。それ以外の場合 false。</returns>
        /// <remarks>現在のリクエスト先 URL が web.config 内の customErrors で定義されているページへのリクエストかどうか判断します。</remarks>
        /// <exception cref="ArgumentNullException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="appPath"/> が null 参照です。
        /// </item>
        /// <item>
        /// <paramref name="path"/> が null 参照です。
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="appPath"/> が空文字列です。
        /// </item>
        /// <item>
        /// <paramref name="path"/> が空文字列です。
        /// </item>
        /// </list>
        /// </exception>
        public static bool IsInCustomErrorPages()
        {
            HttpRequest req = HttpContext.Current.Request;

            return _IsInCustomErrorPages(req.ApplicationPath, req.Path);
        }

        /// <summary>
        /// 現在のリクエスト先 URL が web.config 内の customErrors で定義されているページへのリクエストかどうか判断します。
        /// </summary>
        /// <param name="appPath">現在のページの仮想アプリケーションルートパス。</param>
        /// <param name="path">現在のページのパス。</param>
        /// <returns>customErrors で定義されたページへのリクエストの場合は true。それ以外の場合は false。</returns>
        /// <remarks>現在のリクエスト先 URL が web.config 内の customErrors で定義されているページへのリクエストかどうか判断します。</remarks>
        /// <exception cref="ArgumentNullException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="appPath"/> が null 参照です。
        /// </item>
        /// <item>
        /// <paramref name="path"/> が null 参照です。
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="appPath"/> が空文字列です。
        /// </item>
        /// <item>
        /// <paramref name="path"/> が空文字列です。
        /// </item>
        /// </list>
        /// </exception>
        private static bool _IsInCustomErrorPages(string appPath, string path)
        {
            if (appPath == null)
            {
                ArgumentNullException exception = new ArgumentNullException("appPath");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT,  "appPath"), exception);
                }
                throw exception;
            }

            if (appPath.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "appPath");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }

            if (path == null)
            {
                ArgumentNullException exception = new ArgumentNullException("path");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "path"), exception);
                }
                throw exception;
            }

            if (path.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "path");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }

            bool ret = false;

            CustomErrorsSection ces =
                (CustomErrorsSection)WebConfigurationManager.GetSection(CUSTOM_ERRORS_PATH);
            Hashtable customErrs = new Hashtable();

            String lowerAppPath = appPath.ToLower();
            if (ces.DefaultRedirect != null)
            {
                customErrs[DEFAULT_REDIRECT] = lowerAppPath + "/" + ces.DefaultRedirect.ToLower();
            }
            if (ces.Errors.Count > 0)
            {
                foreach (CustomError ce in ces.Errors)
                {
                    customErrs[ce.StatusCode.ToString()] = lowerAppPath + "/" + ce.Redirect.ToLower();
                }
            }

            ret = customErrs.ContainsValue(path.ToLower());

            return ret;
        }

        /// <summary>
        /// URL にクエリ文字列を付加します。
        /// </summary>
        /// <remarks>
        /// URL がクエリ文字列を含む形式の場合は、クエリ文字列にトークンのパラメータを付加します。
        /// </remarks>
        /// <param name="url">クエリ文字列を付加する URL の文字列。</param>
        /// <param name="key">クエリ文字列として付加するキー。</param>
        /// <param name="value">クエリ文字列として付加する値。</param>
        /// <returns>トークンのクエリ文字列を付加した URL。</returns>
        /// <exception cref="ArgumentNullException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="url"/> が null 参照です。
        /// </item>
        /// <item>
        /// <paramref name="key"/> が null 参照です。
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="url"/> が空文字列です。
        /// </item>
        /// <item>
        /// <paramref name="key"/> が空文字列です。
        /// </item>
        /// </list>
        /// </exception>
        public static string AppendParameter(string url, string key, string value)
        {

            if (url == null)
            {
                ArgumentNullException exception = new ArgumentNullException("url");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "url"), exception);
                }
                throw exception;
            }
            if (url.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "url");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }
            if (key == null)
            {
                ArgumentNullException exception = new ArgumentNullException("key");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "key"), exception);
                }
                throw exception;
            }
            if (key.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "key");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }
            if (value == null)
            {
                value = string.Empty;
            }

            Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);
            return AppendParameter(uri, key, value);
        }

        /// <summary>
        /// URL にトークンのクエリ文字列を付加します。
        /// </summary>
        /// <remarks>
        /// 第一引数の URL がクエリ文字列を含む形式の場合は、クエリ文字列にトークンのパラメータを付加します。
        /// </remarks>
        /// <param name="url">クエリ文字列を付加する URL。</param>
        /// <param name="key">クエリ文字列として付加するキー。</param>
        /// <param name="value">クエリ文字列として付加する値。</param>
        /// <returns>トークンのクエリ文字列を付加した URL。</returns>
        /// <exception cref="ArgumentNullException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="url"/> が null 参照です。
        /// </item>
        /// <item>
        /// <paramref name="key"/> が null 参照です。
        /// </item>
        /// </list>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// 以下のような場合に例外をスローします。
        /// <list type="bullet">
        /// <item>
        /// <paramref name="key"/> が空文字列です。
        /// </item>
        /// </list>
        /// </exception>
        public static string AppendParameter(Uri url, string key, string value)
        {
            if (url == null)
            {
                ArgumentNullException exception = new ArgumentNullException("url");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "url"), exception);
                }
                throw exception;
            }
            if (key == null)
            {
                ArgumentNullException exception = new ArgumentNullException("key");
                if (_log.IsErrorEnabled)
                {
                    _log.Error(string.Format(
                        Properties.Resources.E_NULL_ARGUMENT, "key"), exception);
                }
                throw exception;
            }
            if (key.Length == 0)
            {
                string message = string.Format(Properties.Resources.E_EMPTY_STRING, "key");
                ArgumentException exception = new ArgumentException(message);
                if (_log.IsErrorEnabled)
                {
                    _log.Error(message, exception);
                }
                throw exception;
            }
            if (value == null)
            {
                value = string.Empty;
            }

            string ret;

            if (url.IsAbsoluteUri)
            {
                // 絶対URIの場合はUriBuilderを使用して、トークンを追加する。
                UriBuilder builder = new UriBuilder(url);
                if (url.Query.Length > 1)
                {
                    builder.Query = builder.Query.Substring(1) + string.Format("&{0}={1}", key, value);
                }
                else
                {
                    builder.Query = string.Format("{0}={1}", key, value);
                }

                ret = builder.Uri.AbsoluteUri;
            }
            else
            {
                // 相対URIの場合はUriBuilderは使用できないので、
                // 渡されたオリジナルUriを元に追加する。
                if (url.OriginalString.IndexOf("?") < 0)
                {
                    ret = url.OriginalString + string.Format("?{0}={1}", key, value);
                }
                else
                {
                    ret = url.OriginalString + string.Format("&{0}={1}", key, value);
                }
            }

            return ret;
        }

        /// <summary>
        /// 画面遷移管理機能で利用するクエリパラメータを取得します。
        /// </summary>
        /// <returns>クエリパラメータのキーと値を保持するディクショナリ。</returns>
        /// <remarks>
        /// 返却値として、画面遷移管理機能がHTTPコンテキストに設定したディクショナリを返却します。
        /// </remarks>
        internal static Dictionary<string, string> GetQueryParameters()
        {
            return HttpContext.Current.Items[QUERY_PARAMETERS] as Dictionary<string, string>;
        }
    }
}
