namespace ZetaLib.Web.Common
{
#region Using directives.
// ----------------------------------------------------------------------
using System;
using System.Web;
using System.Collections;
using System.Collections.Specialized;
using System.Web.UI;
using System.Collections.Generic;
using ZetaLib.Core.Common;
using ZetaLib.Core.Collections;
using ZetaLib.Web.Base;
using System.Diagnostics;
// ----------------------------------------------------------------------
#endregion
/////////////////////////////////////////////////////////////////////////
/// <summary>
/// Class for parsing URL parameters (parameters).
/// </summary>
[DebuggerDisplay( @"{AllUrlTilde}" )]
public class QueryString :
ICloneable
{
#region Construction.
// ------------------------------------------------------------------
/// <summary>
/// Constructor.
/// </summary>
public QueryString()
{
if ( HttpContext.Current != null &&
HttpContext.Current.Handler != null &&
HttpContext.Current.Handler is Page )
{
currentPage =
HttpContext.Current.Handler as Page;
FromUrl( currentPage );
}
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="currentPage">The current page.</param>
public QueryString(
Page currentPage )
{
FromUrl( currentPage );
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="url">The URL.</param>
public QueryString(
string url )
{
FromUrl( url );
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="uri">The URI.</param>
public QueryString(
Uri uri )
{
FromUrl( uri.AbsoluteUri );
}
// ------------------------------------------------------------------
#endregion
#region Public properties.
// ------------------------------------------------------------------
/// <summary>
/// Access the parameters collection.
/// </summary>
/// <value>The parameters.</value>
public QueryStringItemCollection Parameters
{
get
{
return qs;
}
}
/// <summary>
/// Get an array of all parameter names.
/// </summary>
/// <value>The parameter names.</value>
public string[] ParameterNames
{
get
{
if ( qs.HasKeys() )
{
return qs.AllKeys;
}
else
{
return null;
}
}
}
/// <summary>
/// Get an array of all parameter values.
/// </summary>
/// <value>The parameter values.</value>
public string[] ParameterValues
{
get
{
if ( qs.HasKeys() )
{
List<string> result = new List<string>();
foreach ( string key in qs.Keys )
{
string value = qs[key];
if ( !string.IsNullOrEmpty( value ) )
{
result.Add( value );
}
}
if ( result.Count <= 0 )
{
return null;
}
else
{
return result.ToArray();
}
}
else
{
return null;
}
}
}
/// <summary>
/// Get an array of all parameter name/value pairs.
/// </summary>
/// <value>The parameter pairs.</value>
public StringPair[] ParameterPairs
{
get
{
if ( qs.HasKeys() )
{
List<StringPair> result = new List<StringPair>();
foreach ( string key in qs.Keys )
{
string value = qs[key];
if ( string.IsNullOrEmpty( value ) )
{
result.Add( new StringPair( key ) );
}
else
{
result.Add( new StringPair( key, value ) );
}
}
if ( result.Count <= 0 )
{
return null;
}
else
{
return result.ToArray();
}
}
else
{
return null;
}
}
}
/// <summary>
/// Access an parameter value by the parameter name.
/// </summary>
/// <value></value>
public string this[string index]
{
get
{
return qs[index];
}
set
{
qs[index] = value;
}
}
/// <summary>
/// Get the complete string including the BeforeUrl and
/// all current parameters.
/// </summary>
/// <value>All URL.</value>
public string AllUrl
{
get
{
return BeforeUrl + Make();
}
set
{
FromUrl( value );
}
}
/// <summary>
/// Gets/sets the short version of an URL where the base path is
/// replaced with a tile ("~").
/// </summary>
/// <value>All URL tilde.</value>
public string AllUrlTilde
{
get
{
return PageBase.MakeTildeUrl( AllUrl );
}
set
{
AllUrl = PageBase.ReplaceTildeComplete( value );
}
}
/// <summary>
/// Get the complete string including the BeforeUrl and
/// all current parameters. Returns as an Uri class.
/// </summary>
/// <value>All URI.</value>
public Uri AllUri
{
get
{
return new Uri( BeforeUrl + Make() );
}
set
{
FromUrl( value );
}
}
/// <summary>
/// The URL that comes before the actual name-value pair parameters.
/// </summary>
/// <value>The before URL.</value>
public string BeforeUrl
{
get
{
return PageBase.ReplaceTilde( beforeUrl );
}
set
{
beforeUrl = value;
}
}
/// <summary>
/// The URL that comes before the actual name-value pair parameters.
/// </summary>
/// <value>The before URL tilde.</value>
public string BeforeUrlTilde
{
get
{
return PageBase.MakeTildeUrl( BeforeUrl );
}
set
{
BeforeUrl = PageBase.ReplaceTildeComplete( value );
}
}
/// <summary>
/// The URL that comes before the actual name-value pair parameters.
/// </summary>
/// <value>The before URI.</value>
public Uri BeforeUri
{
get
{
return new Uri( beforeUrl );
}
set
{
QueryString temp = new QueryString( value );
beforeUrl = temp.BeforeUrl;
}
}
/// <summary>
/// The single string from the current name-value pairs inside
/// this class. Equivalent to the Make() function.
/// </summary>
/// <value>The raw parameters.</value>
public string RawParameters
{
get
{
return Make();
}
set
{
FromUrl( Combine( BeforeUrl, value ) );
}
}
// ------------------------------------------------------------------
#endregion
#region Public operations.
// ------------------------------------------------------------------
/// <summary>
/// Combines an existing URL and a query string. Takes care
/// of worrying about whether to add "&..." or "?...".
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="queryString">The query string.</param>
/// <returns>Returns the complete URL.</returns>
public static string Combine(
string url,
string queryString )
{
string result = url.TrimEnd( '?', '&' );
if ( result.IndexOf( @"?" ) >= 0 )
{
return url + @"&" + queryString;
}
else
{
return url + @"?" + queryString;
}
}
/// <summary>
/// Check whether a parameter with a given name exists.
/// </summary>
/// <param name="parameterName">The name of the parameter
/// to check for.</param>
/// <returns>
/// Returns TRUE if the parameter is present and
/// has a non-empty value, returns FALSE otherwise.
/// </returns>
public bool HasParameter(
string parameterName )
{
if ( parameterName == null ||
parameterName.Trim().Length <= 0 )
{
return false;
}
else
{
parameterName = parameterName.Trim();
string v = this[parameterName];
if ( v == null || v.Trim().Length <= 0 )
{
return false;
}
else
{
return true;
}
}
}
/// <summary>
/// Set or replace a single parameter.
/// </summary>
/// <param name="name">The name of the parameter to set.</param>
/// <param name="val">The value of the parameter to set.</param>
public void SetParameter(
string name,
string val )
{
if ( val == null || val.Trim().Length <= 0 )
{
RemoveParameter( name );
}
else
{
qs[name] = val;
}
}
/// <summary>
/// Removes an parameter (if exists) with the given name.
/// </summary>
/// <param name="parameterName">Name of the parameter.</param>
public void RemoveParameter(
string parameterName )
{
qs.Remove( parameterName );
}
/// <summary>
/// Removes the parameters with the given names (if exists).
/// </summary>
/// <param name="parameterNames">The collection of parameters
/// to remove.</param>
public void RemoveParameters(
IEnumerable<string> parameterNames )
{
if ( parameterNames != null )
{
foreach ( string parameterName in parameterNames )
{
RemoveParameter( parameterName );
}
}
}
/// <summary>
/// Removes the parameters with the given names (if exists).
/// </summary>
/// <param name="parameterNames">The collection of parameters
/// to remove.</param>
public void RemoveParameters(
IEnumerable parameterNames )
{
if ( parameterNames != null )
{
foreach ( string parameterName in parameterNames )
{
RemoveParameter( parameterName );
}
}
}
/// <summary>
/// Removes all parameters.
/// </summary>
public void RemoveAllParameters()
{
qs.Clear();
}
/// <summary>
/// Get an parameter value by a given name.
/// </summary>
/// <param name="name">The name of the parameter value
/// to retrieve.</param>
/// <returns>
/// Returns an empty string (NOT null) if the parameter
/// is not found.
/// </returns>
public string GetParameter(
string name )
{
string result = qs[name];
if ( result == null || result.Length <= 0 )
{
if ( currentPage != null &&
currentPage.Request != null &&
currentPage.Request.Form != null )
{
result = currentPage.Request.Form[name];
}
// try session, also.
if ( result == null || result.Length <= 0 )
{
if ( currentPage != null &&
currentPage.Session != null )
{
object o = currentPage.Session[name];
if ( o != null )
{
result = o.ToString();
}
}
}
// Try cookies, also.
if ( result == null || result.Length <= 0 )
{
if ( currentPage != null &&
currentPage.Request != null &&
currentPage.Request.Cookies != null )
{
HttpCookie c = currentPage.Request.Cookies[name];
if ( c != null )
{
result = c.Value;
}
}
}
}
if ( result == null )
{
result = string.Empty;
}
return result;
}
/// <summary>
/// Pack the current parameters into a new dictionary object.
/// </summary>
/// <returns>Returns the new dictionary object</returns>
public IDictionary ToDictionary()
{
if ( Parameters == null || Parameters.Count <= 0 )
{
return new Hashtable();
}
else
{
Hashtable result = new Hashtable();
foreach ( string key in Parameters )
{
result[key] = Parameters[key];
}
return result;
}
}
/// <summary>
/// Deletes the current content of the Parameters collection
/// and fills with the content of the passed dictionary.
/// </summary>
/// <param name="dictionary">The dictionary to copy from.</param>
public void FromDictionary(
IDictionary dictionary )
{
if ( dictionary == null )
{
throw new ArgumentNullException( @"dictionary" );
}
else
{
RemoveAllParameters();
foreach ( string key in dictionary.Keys )
{
SetParameter( key, dictionary[key].ToString() );
}
}
}
/// <summary>
/// Redirects to the currently contained URL.
/// </summary>
public void Redirect()
{
Redirect( RedirectMethod.Standard );
}
/// <summary>
/// Redirects to the currently contained URL.
/// </summary>
/// <param name="method">The method.</param>
public void Redirect(
RedirectMethod method )
{
HttpResponse response = HttpContext.Current.Response;
if ( method == RedirectMethod.Standard )
{
response.Redirect( AllUrl, true );
}
else if ( method == RedirectMethod.Status301 )
{
response.Clear();
response.StatusCode = 301;
response.StatusDescription = @"Moved Permanently";
response.RedirectLocation = AllUrl;
response.Write( @"<html><head><title>Object moved</title></head><body>" + Environment.NewLine );
response.Write( "<h2>Object moved to <a href=\"" + HttpUtility.HtmlAttributeEncode( AllUrl ) + "\">here</a>.</h2>\r\n" );
response.Write( @"</body></html>" + Environment.NewLine );
response.End();
}
else
{
throw new ArgumentException(
string.Format(
"Unknown redirect method '{0}'.",
method ),
@"method" );
}
}
// ------------------------------------------------------------------
#endregion
#region Reading from an URL.
// ------------------------------------------------------------------
/// <summary>
/// Parse a query string and insert the found parameters
/// into the collection of this class.
/// </summary>
/// <param name="page">The page.</param>
public void FromUrl(
Page page )
{
if ( page != null )
{
currentPage = page;
FromUrl( currentPage.Request.RawUrl );
}
}
/// <summary>
/// Parse a query string and insert the found parameters
/// into the collection of this class.
/// </summary>
/// <param name="uri">The URI.</param>
public void FromUrl(
Uri uri )
{
if ( uri != null )
{
FromUrl( uri.AbsoluteUri );
}
}
/// <summary>
/// Parse a query string and insert the found parameters
/// into the collection of this class.
/// </summary>
/// <param name="url">The URL.</param>
public void FromUrl(
string url )
{
if ( url != null )
{
url = PageBase.ReplaceTilde( url );
qs.Clear();
// store the part before, too.
int qPos = url.IndexOf( @"?" );
if ( qPos >= 0 )
{
BeforeUrl = url.Substring( 0, qPos - 0 );
url = url.Substring( qPos + 1 );
}
else
{
BeforeUrl = url;
}
if ( url.Length > 0 && url.Substring( 0, 1 ) == @"?" )
{
url = url.Substring( 1 );
}
// Break the values.
string[] pairs = url.Split( '&' );
foreach ( string pair in pairs )
{
string a = string.Empty;
string b = string.Empty;
string[] singular = pair.Split( '=' );
int j = 0;
foreach ( string one in singular )
{
if ( j == 0 )
{
a = one;
}
else
{
b = one;
}
j++;
}
// Store.
SetParameter( a, HttpUtility.UrlDecode( b ) );
}
}
}
// ------------------------------------------------------------------
#endregion
#region Making a string from the parameters.
// ------------------------------------------------------------------
/// <summary>
/// Build a single string from the current name-value pairs inside
/// this class. Equivalent to the Parameters property.
/// </summary>
/// <returns>
/// Returns the complete query string, but WITHOUT the BeforeUrl.
/// </returns>
public string Make()
{
string result = "?";
foreach ( string name in qs )
{
string val = qs[name];
if ( val != null && val.Length > 0 )
{
if ( name != null && name.Length > 0 )
{
result += name + @"=" + HttpUtility.UrlEncode( val ) + @"&";
}
else
{
// Allow for "no-names".
result += HttpUtility.UrlEncode( val ) + @"&";
}
}
}
//return result;
return result.TrimEnd( '?', '&' );
}
/// <summary>
/// Build a single string from the current name-value pairs inside
/// this class. Replace/add the name-value pairs passed as
/// parameters to this function.
/// </summary>
/// <param name="name1">The name1.</param>
/// <param name="value1">The value1.</param>
/// <returns>
/// Returns the complete query string, but WITHOUT the BeforeUrl.
/// </returns>
public string Make(
string name1,
string value1 )
{
return Make(
name1, value1,
string.Empty, string.Empty,
string.Empty, string.Empty,
string.Empty, string.Empty,
string.Empty, string.Empty );
}
/// <summary>
/// Build a single string from the current name-value pairs inside
/// this class. Replace/add the name-value pair(s) passed as
/// parameters to this function.
/// </summary>
/// <param name="name1">The name1.</param>
/// <param name="value1">The value1.</param>
/// <param name="name2">The name2.</param>
/// <param name="value2">The value2.</param>
/// <returns>
/// Returns the complete query string, but WITHOUT the BeforeUrl.
/// </returns>
public string Make(
string name1,
string value1,
string name2,
string value2 )
{
return Make(
name1, value1,
name2, value2,
string.Empty, string.Empty,
string.Empty, string.Empty,
string.Empty, string.Empty );
}
/// <summary>
/// Build a single string from the current name-value pairs inside
/// this class. Replace/add the name-value pair(s) passed as
/// parameters to this function.
/// </summary>
/// <param name="name1">The name1.</param>
/// <param name="value1">The value1.</param>
/// <param name="name2">The name2.</param>
/// <param name="value2">The value2.</param>
/// <param name="name3">The name3.</param>
/// <param name="value3">The value3.</param>
/// <returns>
/// Returns the complete query string, but WITHOUT the BeforeUrl.
/// </returns>
public string Make(
string name1,
string value1,
string name2,
string value2,
string name3,
string value3 )
{
return Make(
name1, value1,
name2, value2,
name3, value3,
string.Empty, string.Empty,
string.Empty, string.Empty );
}
/// <summary>
/// Build a single string from the current name-value pairs inside
/// this class. Replace/add the name-value pair(s) passed as
/// parameters to this function.
/// </summary>
/// <param name="name1">The name1.</param>
/// <param name="value1">The value1.</param>
/// <param name="name2">The name2.</param>
/// <param name="value2">The value2.</param>
/// <param name="name3">The name3.</param>
/// <param name="value3">The value3.</param>
/// <param name="name4">The name4.</param>
/// <param name="value4">The value4.</param>
/// <returns>
/// Returns the complete query string, but WITHOUT the BeforeUrl.
/// </returns>
public string Make(
string name1,
string value1,
string name2,
string value2,
string name3,
string value3,
string name4,
string value4 )
{
return Make(
name1, value1,
name2, value2,
name3, value3,
name4, value4,
string.Empty, string.Empty );
}
/// <summary>
/// Build a single string from the current name-value pairs inside
/// this class. Replace/add the name-value pair(s) passed as
/// parameters to this function.
/// </summary>
/// <param name="name1">The name1.</param>
/// <param name="value1">The value1.</param>
/// <param name="name2">The name2.</param>
/// <param name="value2">The value2.</param>
/// <param name="name3">The name3.</param>
/// <param name="value3">The value3.</param>
/// <param name="name4">The name4.</param>
/// <param name="value4">The value4.</param>
/// <param name="name5">The name5.</param>
/// <param name="value5">The value5.</param>
/// <returns>
/// Returns the complete query string, but WITHOUT the BeforeUrl.
/// </returns>
public string Make(
string name1,
string value1,
string name2,
string value2,
string name3,
string value3,
string name4,
string value4,
string name5,
string value5 )
{
QueryString clone = Clone() as QueryString;
clone.SetParameter( name1, value1 );
clone.SetParameter( name2, value2 );
clone.SetParameter( name3, value3 );
clone.SetParameter( name4, value4 );
clone.SetParameter( name5, value5 );
return clone.Make();
}
// ------------------------------------------------------------------
#endregion
#region Making a string from the parameters, including BeforeUrl.
// ------------------------------------------------------------------
/// <summary>
/// Build a single string from the current name-value pairs inside
/// this class.
/// </summary>
/// <returns>
/// Returns the complete query string, WITH the BeforeUrl.
/// </returns>
public string MakeAll()
{
return BeforeUrl + Make();
}
/// <summary>
/// Build a single string from the current name-value pairs inside
/// this class. Replace/add the name-value pairs passed as
/// parameters to this function.
/// </summary>
/// <param name="name1">The name1.</param>
/// <param name="value1">The value1.</param>
/// <returns>
/// Returns the complete query string, WITH the BeforeUrl.
/// </returns>
public string MakeAll(
string name1,
string value1 )
{
return MakeAll(
name1, value1,
string.Empty, string.Empty,
string.Empty, string.Empty,
string.Empty, string.Empty,
string.Empty, string.Empty );
}
/// <summary>
/// Build a single string from the current name-value pairs inside
/// this class. Replace/add the name-value pair(s) passed as
/// parameters to this function.
/// </summary>
/// <param name="name1">The name1.</param>
/// <param name="value1">The value1.</param>
/// <param name="name2">The name2.</param>
/// <param name="value2">The value2.</param>
/// <returns>
/// Returns the complete query string, WITH the BeforeUrl.
/// </returns>
public string MakeAll(
string name1,
string value1,
string name2,
string value2 )
{
return MakeAll(
name1, value1,
name2, value2,
string.Empty, string.Empty,
string.Empty, string.Empty,
string.Empty, string.Empty );
}
/// <summary>
/// Build a single string from the current name-value pairs inside
/// this class. Replace/add the name-value pair(s) passed as
/// parameters to this function.
/// </summary>
/// <param name="name1">The name1.</param>
/// <param name="value1">The value1.</param>
/// <param name="name2">The name2.</param>
/// <param name="value2">The value2.</param>
/// <param name="name3">The name3.</param>
/// <param name="value3">The value3.</param>
/// <returns>
/// Returns the complete query string, WITH the BeforeUrl.
/// </returns>
public string MakeAll(
string name1,
string value1,
string name2,
string value2,
string name3,
string value3 )
{
return MakeAll(
name1, value1,
name2, value2,
name3, value3,
string.Empty, string.Empty,
string.Empty, string.Empty );
}
/// <summary>
/// Build a single string from the current name-value pairs inside
/// this class. Replace/add the name-value pair(s) passed as
/// parameters to this function.
/// </summary>
/// <param name="name1">The name1.</param>
/// <param name="value1">The value1.</param>
/// <param name="name2">The name2.</param>
/// <param name="value2">The value2.</param>
/// <param name="name3">The name3.</param>
/// <param name="value3">The value3.</param>
/// <param name="name4">The name4.</param>
/// <param name="value4">The value4.</param>
/// <returns>
/// Returns the complete query string, WITH the BeforeUrl.
/// </returns>
public string MakeAll(
string name1,
string value1,
string name2,
string value2,
string name3,
string value3,
string name4,
string value4 )
{
return MakeAll(
name1, value1,
name2, value2,
name3, value3,
name4, value4,
string.Empty, string.Empty );
}
/// <summary>
/// Build a single string from the current name-value pairs inside
/// this class. Replace/add the name-value pair(s) passed as
/// parameters to this function.
/// </summary>
/// <param name="name1">The name1.</param>
/// <param name="value1">The value1.</param>
/// <param name="name2">The name2.</param>
/// <param name="value2">The value2.</param>
/// <param name="name3">The name3.</param>
/// <param name="value3">The value3.</param>
/// <param name="name4">The name4.</param>
/// <param name="value4">The value4.</param>
/// <param name="name5">The name5.</param>
/// <param name="value5">The value5.</param>
/// <returns>
/// Returns the complete query string, WITH the BeforeUrl.
/// </returns>
public string MakeAll(
string name1,
string value1,
string name2,
string value2,
string name3,
string value3,
string name4,
string value4,
string name5,
string value5 )
{
return BeforeUrl + Make(
name1, value1,
name2, value2,
name3, value3,
name4, value4,
name5, value5 );
}
// ------------------------------------------------------------------
#endregion
#region ICloneable member.
// ------------------------------------------------------------------
/// <summary>
/// Makes a deep copy.
/// </summary>
/// <returns>
/// A new object that is a copy of this instance.
/// </returns>
public object Clone()
{
QueryString dst = new QueryString();
dst.currentPage = this.currentPage;
dst.beforeUrl = this.beforeUrl;
// Clone.
foreach ( string key in this.qs.Keys )
{
dst.qs[key] = this.qs[key];
}
return dst;
}
// ------------------------------------------------------------------
#endregion
#region Collection class for the parameters.
// ------------------------------------------------------------------
/// <summary>
/// Collection class for the parameters.
/// </summary>
public class QueryStringItemCollection :
NameValueCollection
{
#region Public methods.
/// <summary>
/// Construct only in this class.
/// </summary>
internal QueryStringItemCollection()
{
}
#endregion
}
// ------------------------------------------------------------------
#endregion
#region Private variables.
// ------------------------------------------------------------------
/// <summary>
/// The URL that comes before the actual name-value pair parameters.
/// </summary>
private string beforeUrl = string.Empty;
/// <summary>
/// The page that is currently loaded.
/// </summary>
private Page currentPage = null;
/// <summary>
/// The collection to store the name-value pairs.
/// </summary>
private QueryStringItemCollection qs =
new QueryStringItemCollection();
// ------------------------------------------------------------------
#endregion
}
/////////////////////////////////////////////////////////////////////////
}