C#

Request.QueryStringについて

この文書はASPにおけるRequest.QueryStringに関する資料です。

JScriptでASPを動作させたときにRequest.QueryStringからどうやって値を取り出せばよいのか、判然としませんでした。

    var KeyValue = Request.QueryString("KeyName");

KeyValueにはオブジェクトへの参照が返ってきます。そしてクエリに"KeyName"がなければ文字列へのキャストは"undefined"を返します。Request.QueryStringは未定義値に似た動作をするオブジェクトを返してくるようです。

※JavaScriptの仕様では未定義のオブジェクトに対して"typeof"演算子を使うと"undefined"という文字列を返すので、混同していました。JavaScriptの理念ではnull値と未定義値を区別する必要はないはずです。

ここではふたつのクラスを考えます。ひとつは文字列配列と同様の動作をするクラスで、仮にこれをStringCollectionAと呼ぶことにします。StringCollectionAは以下のようなクラスだと思います。

    public calss StringCollectionA
    {
	    pirvate string[] items;

	    public int Count
	    {
		    get
		    {
			    return items != null ? items.Length : 0;
		    }
	    }

	    public string Item(int index)
	    {
		    return items[index - 1];
	    }

	    // C#ではC++のような()オペレータは使えませんが、JScriptでは使えるようなので便宜的にこうしました。
	    public string this(int index)
	    {
		    return items[index - 1];
	    }

	    public static implicit operator string(StringCollectionA obj)
	    {
		    return obj.items != null ? string.Join(", ", obj.items) : "undefined";
	    }
    }

Item()メソッドの引数は1オリジン(1から始まる)のインデックス値です。文字列への暗黙の型キャストは要素があればカンマで連結した文字列を、なければ"undefined"という文字列を返します。

もうひとつのクラスはRequest.QueryStringでStringCollectionAを値に持つハッシュテーブルだと考えられます。仮にこれをHashtableAとするとおそらく以下のようなクラスだと思います。

    public class HashtableA
    {
	    static private StringCollecitonA default_values = new StringCollectionA();

	    private string query_string;
	    private string[] keys;
	    private StringCollectionA[] values;

	    public int Count
	    {
		    get
		    {
			    return keys != null ? keys.Length : 0;
		    }
	    }

	    public string Key(int index)
	    {
		    return keys[index - 1];
	    }

	    public StringCollectionA Item(int index)
	    {
		    return values[index - 1];
	    }

	    public StringCollectionA this(string key)
	    {
		    get
		    {
			    for (int i = 0; i < keys.Length; i++)
			    {
				    if (keys[i] == key)
				    {
					    return values[i];
				    }
			    }

			    return default_values;
		    }
	    }

	    public static implicit operator string(HashtableA obj)
	    {
		    return obj.query_string;
	    }
    }

Key()とItem()の引数indexは1オリジンです。重要なことはインデクサの返すオブジェクトがnull値を取らないことで、必ず実体のあるオブジェクトを返します。KeyにないキーをRequest.QueryString()に与えると同じインスタンスへの参照を返してきます。

    Response.Write((new Object()) == (new Object()) + "<br>\n"); // 比較用
    Response.Write((Request.QueryString("nokey1") == Request.QueryString("nokey2")) + "<br>\n");

    ---- 結果 ----

    False
    True

結論として、クエリに指定されていない可能性も考慮して次のようにRequest.QueryStringを調べれば良いはずです。

    var Item = Request.QueryString("Arg1");
    var Arg1 = (Item.Count ? Item(1) : "");

重複したクエリとカンマを含むクエリを区別するために型キャストでなくItem()を使ったほうが良いです。型キャストではどちらも"val1, val2"となります。

    http://www.hoge.com/hoge.asp?arg1=val1&arg1=val2
    http://www.hoge.com/hoge.asp?arg1=val1,+val2

	    → サンプル