added xmldocs for new result navigation support: sprnet-1040, sprnet-1052, sprnet-958, sprnet-567
This commit is contained in:
@@ -123,6 +123,16 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Util\ISessionState.cs" />
|
||||
<Compile Include="Web\Support\DefaultResultFactory.cs" />
|
||||
<Compile Include="Web\Support\IHierarchicalWebNavigator.cs" />
|
||||
<Compile Include="Web\Support\IResult.cs" />
|
||||
<Compile Include="Web\Support\IResultFactory.cs" />
|
||||
<Compile Include="Web\Support\IResultWebNavigator.cs" />
|
||||
<Compile Include="Web\Support\IWebNavigable.cs" />
|
||||
<Compile Include="Web\Support\IWebNavigator.cs" />
|
||||
<Compile Include="Web\Support\ResultFactoryRegistry.cs" />
|
||||
<Compile Include="Web\Support\ResultWebNavigator.cs" />
|
||||
<Compile Include="Web\Support\WebFormsResultWebNavigator.cs" />
|
||||
<Compile Include="Web\UI\IValidationContainer.cs" />
|
||||
<Compile Include="Web\Support\MimeMediaType.cs" />
|
||||
<Compile Include="Web\Support\SharedStateResourceCache.cs">
|
||||
|
||||
@@ -133,6 +133,7 @@
|
||||
<Compile Include="Web\Support\IResultWebNavigator.cs" />
|
||||
<Compile Include="Web\Support\IWebNavigable.cs" />
|
||||
<Compile Include="Web\Support\IWebNavigator.cs" />
|
||||
<Compile Include="Web\Support\WebNavigableWebNavigatorAdapter.cs" />
|
||||
<Compile Include="Web\UI\IValidationContainer.cs" />
|
||||
<Compile Include="Web\Support\MimeMediaType.cs" />
|
||||
<Compile Include="Web\Support\SharedStateResourceCache.cs">
|
||||
@@ -269,7 +270,7 @@
|
||||
<Compile Include="Web\UI\Page.cs">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Web\Support\ResultWebNavigator.cs" />
|
||||
<Compile Include="Web\Support\DefaultResultWebNavigator.cs" />
|
||||
<Compile Include="Web\UI\UserControl.cs">
|
||||
<SubType>ASPXCodeBehind</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web.UI;
|
||||
|
||||
#endregion
|
||||
@@ -243,7 +244,7 @@ namespace Spring.Util
|
||||
|
||||
///<summary>
|
||||
/// Returns the 'logical' parent of the specified control. Technically when dealing with masterpages and control hierarchy,
|
||||
/// the order goes controls->masterpage->page. But one often wants the more logical order controls->page->masterpage.
|
||||
/// the order goes controls->masterpage->page. But one often wants the more logical order controls->page->masterpage.
|
||||
///</summary>
|
||||
///<param name="control">the control, who's parent is to be determined.</param>
|
||||
///<returns>the logical parent or <c>null</c> if the top of the hierarchy is reached.</returns>
|
||||
@@ -286,5 +287,21 @@ namespace Spring.Util
|
||||
return (control is System.Web.UI.MasterPage);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encode <paramref name="value"/> for use in URLs.
|
||||
/// </summary>
|
||||
/// <param name="value">the text to be encoded.</param>
|
||||
/// <returns>the url-encoded <paramref name="value"/></returns>
|
||||
/// <remarks>
|
||||
/// This method may be used outside of a current request. If executed within a
|
||||
/// request, <see cref="HttpServerUtility.UrlEncode(string)"/> is used.
|
||||
/// <see cref="HttpUtility.UrlEncode(string)"/> will be used otherwise.
|
||||
/// </remarks>
|
||||
public static string UrlEncode( string value )
|
||||
{
|
||||
HttpContext ctx = HttpContext.Current;
|
||||
return (ctx == null) ? HttpUtility.UrlEncode( value ) : ctx.Server.UrlEncode( value );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,25 @@
|
||||
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// This result factory implementation creates <see cref="Result"/> instances from a given string representation.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For a larger example illustrating the customization of result processing, <see cref="ResultFactoryRegistry"/>.
|
||||
/// </remarks>
|
||||
/// <seealso cref="ResultFactoryRegistry"/>
|
||||
/// <seealso cref="IResult"/>
|
||||
/// <seealso cref="Result"/>
|
||||
/// <seealso cref="DefaultResultWebNavigator"/>
|
||||
/// <author>Erich Eichinger</author>
|
||||
public class DefaultResultFactory : IResultFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a new <see cref="Result"/> from the specified <paramref name="resultText"/>.
|
||||
/// </summary>
|
||||
/// <param name="resultMode">the result mode.</param>
|
||||
/// <param name="resultText">the string representation of the result.</param>
|
||||
/// <returns>the <see cref="Result"/> instance created from <paramref name="resultText"/>.</returns>
|
||||
public IResult CreateResult(string resultMode, string resultText)
|
||||
{
|
||||
return new Result(resultMode, resultText);
|
||||
|
||||
253
src/Spring/Spring.Web/Web/Support/DefaultResultWebNavigator.cs
Normal file
253
src/Spring/Spring.Web/Web/Support/DefaultResultWebNavigator.cs
Normal file
@@ -0,0 +1,253 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Spring.Collections;
|
||||
using Spring.Core;
|
||||
using Spring.Util;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// The default implementation of the <see cref="IResultWebNavigator"/> interface.
|
||||
/// </summary>
|
||||
public class DefaultResultWebNavigator : IResultWebNavigator
|
||||
{
|
||||
private IWebNavigator _parentNavigator;
|
||||
private bool _ignoreCase;
|
||||
private IDictionary _results;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates, whether result names are treated case sensitive by this navigator.
|
||||
/// </summary>
|
||||
public bool IsCaseSensitive
|
||||
{
|
||||
get { return !_ignoreCase; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the parent of this navigator.
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException">if this navigator already has a parent.</exception>
|
||||
public virtual IWebNavigator ParentNavigator
|
||||
{
|
||||
get { return _parentNavigator; }
|
||||
set
|
||||
{
|
||||
if (_parentNavigator != null)
|
||||
{
|
||||
throw new InvalidOperationException("Can't set parent navigator because this navigator already has a parent");
|
||||
}
|
||||
_parentNavigator = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets map of result names to <see cref="IResult"/> instances or their textual representations.
|
||||
/// See <see cref="ResultFactoryRegistry"/> for information on parsing textual <see cref="IResult"/> representations.
|
||||
/// </summary>
|
||||
/// <seealso cref="IResult"/>
|
||||
/// <seealso cref="ResultFactoryRegistry"/>
|
||||
/// <seealso cref="IResultFactory"/>
|
||||
/// <seealso cref="DefaultResultFactory"/>
|
||||
public IDictionary Results
|
||||
{
|
||||
get
|
||||
{
|
||||
return _results;
|
||||
}
|
||||
set
|
||||
{
|
||||
_results = CreateResultsDictionary( value );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and initializes a new instance.
|
||||
/// </summary>
|
||||
public DefaultResultWebNavigator()
|
||||
: this( null, null, true )
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Creates and initializes a new instance.
|
||||
/// </summary>
|
||||
/// <param name="parent">the parent of this instance. May be null.</param>
|
||||
/// <param name="initialResults">a dictionary of result name to result mappings. May be null.</param>
|
||||
/// <param name="ignoreCase">sets, how this navigator treats case sensitivity of result names</param>
|
||||
public DefaultResultWebNavigator( IWebNavigator parent, IDictionary initialResults, bool ignoreCase )
|
||||
{
|
||||
this._parentNavigator = parent;
|
||||
this._ignoreCase = ignoreCase;
|
||||
this._results = CreateResultsDictionary( initialResults );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the dictionary instance to be used by this navigator component.
|
||||
/// </summary>
|
||||
/// <param name="initialResults">a dictionary of intitial result mappings</param>
|
||||
/// <returns>the dictionary, that will be used by this navigator.</returns>
|
||||
/// <remarks>
|
||||
/// Implementors may override this for creating custom dictionaries.
|
||||
/// </remarks>
|
||||
protected virtual IDictionary CreateResultsDictionary( IDictionary initialResults )
|
||||
{
|
||||
IDictionary newResults = (_ignoreCase) ? new CaseInsensitiveHashtable() : new Hashtable();
|
||||
if (initialResults != null)
|
||||
{
|
||||
foreach (DictionaryEntry entry in initialResults)
|
||||
{
|
||||
newResults[entry.Key.ToString()] = entry.Value;
|
||||
}
|
||||
}
|
||||
return newResults;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines, whether this navigator or one of its parents can
|
||||
/// navigate to the destination specified in <paramref name="destination"/>.
|
||||
/// </summary>
|
||||
/// <param name="destination">the name of the navigation destination</param>
|
||||
/// <returns>true, if this navigator can navigate to the destination.</returns>
|
||||
public virtual bool CanNavigateTo( string destination )
|
||||
{
|
||||
if (_results.Contains( destination ))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return (ParentNavigator != null) ? ParentNavigator.CanNavigateTo( destination ) : false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redirects user to a URL mapped to specified result name.
|
||||
/// </summary>
|
||||
/// <param name="destination">Name of the result.</param>
|
||||
/// <param name="sender">the instance that issued this request</param>
|
||||
/// <param name="context">The context to use for evaluating the SpEL expression in the Result.</param>
|
||||
public virtual void NavigateTo( string destination, object sender, object context )
|
||||
{
|
||||
IResult result = GetResult( destination );
|
||||
if (result == null)
|
||||
{
|
||||
if (ParentNavigator != null)
|
||||
{
|
||||
ParentNavigator.NavigateTo( destination, sender, context );
|
||||
return;
|
||||
}
|
||||
HandleUnknownDestination(destination, sender, context);
|
||||
return;
|
||||
}
|
||||
|
||||
// If no context, 'sender' is context
|
||||
if (context == null)
|
||||
{
|
||||
context = sender;
|
||||
}
|
||||
result.Navigate( context );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a redirect url string that points to the
|
||||
/// <see cref="Spring.Web.Support.Result.TargetPage"/> defined by this
|
||||
/// result evaluated using this Page for expression
|
||||
/// </summary>
|
||||
/// <param name="resultName">Name of the result.</param>
|
||||
/// <param name="sender">the instance that issued this request</param>
|
||||
/// <param name="context">The context to use for evaluating the SpEL expression in the Result</param>
|
||||
/// <returns>A redirect url string.</returns>
|
||||
public virtual string GetResultUri( string resultName, object sender, object context )
|
||||
{
|
||||
IResult result = GetResult( resultName );
|
||||
if (result == null)
|
||||
{
|
||||
if (ParentNavigator != null)
|
||||
{
|
||||
return result.GetRedirectUri( context );
|
||||
}
|
||||
return HandleUnknownDestination( resultName, sender, context );
|
||||
}
|
||||
|
||||
// If no context, 'sender' is context
|
||||
if (context == null)
|
||||
{
|
||||
context = sender;
|
||||
}
|
||||
return result.GetRedirectUri( context );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtain the named result instance from the <see cref="Results"/> dictionary. If necessary, the actual representation of the result
|
||||
/// will be converted to an <see cref="IResult"/> instance by this method.
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
protected IResult GetResult( string name )
|
||||
{
|
||||
object val = _results[name];
|
||||
if (val == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (val is IResult)
|
||||
{
|
||||
return (IResult)val;
|
||||
}
|
||||
else if (val is String)
|
||||
{
|
||||
return ResultFactoryRegistry.CreateResult( (string)val );
|
||||
}
|
||||
|
||||
return HandleUnknownResultType(name, val);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle an unknown result object.
|
||||
/// </summary>
|
||||
/// <param name="name">the name of the result</param>
|
||||
/// <param name="val">the result instance obtained from the <see cref="Results"/> dictionary</param>
|
||||
/// <remarks>
|
||||
/// By default, this method throws a <see cref="TypeMismatchException"/>.
|
||||
/// </remarks>
|
||||
protected virtual IResult HandleUnknownResultType(string name, object val)
|
||||
{
|
||||
throw new TypeMismatchException("Unable to create result object. Please use either String or Result instances to define results." );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle an unknown destination.
|
||||
/// </summary>
|
||||
/// <param name="destination">the destination that could not be resolved.</param>
|
||||
/// <param name="sender">the sender that issued the request</param>
|
||||
/// <param name="context">the context to be used for evaluating any dynamic parts of the destination</param>
|
||||
/// <returns>the uri as being returned from <see cref="GetResultUri"/></returns>
|
||||
/// <remarks>
|
||||
/// By default, this method throws a <see cref="ArgumentOutOfRangeException"/>.
|
||||
/// </remarks>
|
||||
protected virtual string HandleUnknownDestination( string destination, object sender, object context )
|
||||
{
|
||||
throw new ArgumentOutOfRangeException( "destination", string.Format( "No mapping found for the specified destination '{0}'.", destination ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,16 @@
|
||||
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// An extension of <see cref="IWebNavigator"/> that must be implemented by
|
||||
/// navigators that can be part of a hierarchy.
|
||||
/// </summary>
|
||||
/// <author>Erich Eichinger</author>
|
||||
public interface IHierarchicalWebNavigator : IWebNavigator
|
||||
{
|
||||
/// <summary>
|
||||
/// If any, get the parent navigator of the current navigator instance. May be null.
|
||||
/// </summary>
|
||||
IWebNavigator ParentNavigator { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,64 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System.Web;
|
||||
using Spring.Web.UI;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IResult"/> encapsulates concrete navigation logic. Usually executing a
|
||||
/// result will invoke <see cref="HttpResponse.Redirect(string)"/> or <see cref="HttpServerUtility.Transfer(string, bool)"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For a larger example illustrating the customization of result processing <see cref="ResultFactoryRegistry"/>.
|
||||
/// </remarks>
|
||||
/// <seealso cref="ResultFactoryRegistry"/>
|
||||
/// <seealso cref="IResult"/>
|
||||
/// <seealso cref="Result"/>
|
||||
/// <seealso cref="DefaultResultWebNavigator"/>
|
||||
/// <seealso cref="Page.SetResult(string, object)"/>
|
||||
/// <seealso cref="UserControl.SetResult(string, object)"/>
|
||||
/// <author>Erich Eichinger</author>
|
||||
public interface IResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Execute the result logic within the given <paramref name="context"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">the context to evaluate this request in.</param>
|
||||
void Navigate( object context );
|
||||
/// <summary>
|
||||
/// Returns an url representation of the result logic within the given <paramref name="context"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">the context to evaluate this request in.</param>
|
||||
/// <returns>the url corresponding to the result instance.</returns>
|
||||
/// <remarks>
|
||||
/// The returned url is not necessarily fully qualified nor absolute. Returned urls may be relative to the
|
||||
/// given context.<br/>
|
||||
/// To produce a client-usable url, consider applying e.g. <see cref="System.Web.UI.Control.ResolveUrl"/> or
|
||||
/// <see cref="System.Web.UI.Control.ResolveClientUrl"/> before writing the result url to the response.
|
||||
/// </remarks>
|
||||
string GetRedirectUri( object context );
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,51 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// A result factory is responsible for create an <see cref="IResult"/> instance from a given string representation.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For a larger example illustrating the customization of result processing, <see cref="ResultFactoryRegistry"/>.
|
||||
/// </remarks>
|
||||
/// <seealso cref="ResultFactoryRegistry"/>
|
||||
/// <seealso cref="IResult"/>
|
||||
/// <seealso cref="Result"/>
|
||||
/// <seealso cref="DefaultResultWebNavigator"/>
|
||||
/// <author>Erich Eichinger</author>
|
||||
public interface IResultFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Create an <see cref="IResult"/> instance from the given string representation.
|
||||
/// </summary>
|
||||
/// <param name="resultMode">the resultMode that caused triggering this factory.</param>
|
||||
/// <param name="resultText">the remainder string to be interpreted and converted into an <see cref="IResult"/>.</param>
|
||||
/// <returns>An <see cref="IResult"/> instance. Must never be null!</returns>
|
||||
/// <remarks>
|
||||
/// Note to implementors: This method must never return null. Instead exceptions should be thrown.
|
||||
/// </remarks>
|
||||
IResult CreateResult( string resultMode, string resultText );
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,22 @@ using System.Collections;
|
||||
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the interface, all hierarchical navigators capable of
|
||||
/// dealing with <see cref="IResult"/> instances must implement.
|
||||
/// </summary>
|
||||
public interface IResultWebNavigator : IHierarchicalWebNavigator
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the mappings of navigation destination names to <see cref="IResult"/>
|
||||
/// instances or their corresponding textual representations.<br/>
|
||||
/// See <see cref="ResultFactoryRegistry"/> for more information on how textual representations are resolved.
|
||||
/// </summary>
|
||||
/// <seealso cref="IWebNavigator"/>
|
||||
/// <seealso cref="IHierarchicalWebNavigator"/>
|
||||
/// <seealso cref="DefaultResultWebNavigator"/>
|
||||
/// <seealso cref="ResultFactoryRegistry"/>
|
||||
/// <seealso cref="DefaultResultFactory"/>
|
||||
IDictionary Results { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,15 @@
|
||||
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Any component participating in the navigation infrastructure must implement this interface.
|
||||
/// </summary>
|
||||
/// <author>Erich Eichinger</author>
|
||||
public interface IWebNavigable
|
||||
{
|
||||
/// <summary>
|
||||
/// Return the <see cref="IWebNavigator"/> associated with this component.
|
||||
/// </summary>
|
||||
IWebNavigator WebNavigator { get; }
|
||||
}
|
||||
}
|
||||
@@ -22,18 +22,44 @@
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Any component capable of navigating and participating in the navigation logic must implement this interface.
|
||||
/// </summary>
|
||||
/// <seealso cref="IHierarchicalWebNavigator"/>
|
||||
/// <seealso cref="IResultWebNavigator"/>
|
||||
/// <seealso cref="DefaultResultWebNavigator"/>
|
||||
/// <seealso cref="WebFormsResultWebNavigator"/>
|
||||
/// <author>Erich Eichinger</author>
|
||||
public interface IWebNavigator
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines, whether this navigator or one of its parents can
|
||||
/// navigate to the result specified in <paramref name="resultName"/>.
|
||||
/// navigate to the destination specified in <paramref name="destination"/>.
|
||||
/// </summary>
|
||||
/// <param name="resultName">the name of the result</param>
|
||||
/// <returns>true, if this navigator or one of its parents can navigate to the result.</returns>
|
||||
bool CanNavigateTo( string resultName );
|
||||
void NavigateTo( string resultName, object context );
|
||||
string GetResultUri( string resultName, object context );
|
||||
/// <param name="destination">the name of the navigation destination</param>
|
||||
/// <returns>true, if this navigator can navigate to the destination.</returns>
|
||||
bool CanNavigateTo( string destination );
|
||||
|
||||
/// <summary>
|
||||
/// Instruct the navigator to navigate to the specified navigation destination.
|
||||
/// </summary>
|
||||
/// <param name="destination">the destination to navigate to.</param>
|
||||
/// <param name="sender">the sender that issued the navigation request.</param>
|
||||
/// <param name="context">the context to evaluate this navigation request in.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">if this navigator cannot navigate to the specified <paramref name="destination"/> (<see cref="CanNavigateTo"/>).</exception>
|
||||
void NavigateTo( string destination, object sender, object context );
|
||||
|
||||
/// <summary>
|
||||
/// Creates an uri poiniting to the specified navigation destination.
|
||||
/// </summary>
|
||||
/// <param name="destination">the destination to navigate to.</param>
|
||||
/// <param name="sender">the sender that issued the navigation request.</param>
|
||||
/// <param name="context">the context to evaluate this navigation request in.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">if this navigator cannot navigate to the specified <paramref name="destination"/> (<see cref="CanNavigateTo"/>).</exception>
|
||||
string GetResultUri( string destination, object sender, object context );
|
||||
}
|
||||
}
|
||||
@@ -288,9 +288,9 @@ namespace Spring.Web.Support
|
||||
foreach (DictionaryEntry entry in this.parameters)
|
||||
{
|
||||
string value = entry.Value.ToString();
|
||||
if (IsRuntimeExpression( value ))
|
||||
if (IsSpELRuntimeExpression( value ))
|
||||
{
|
||||
contextDictionary[entry.Key] = ResolveRuntimeExpression( context, value );
|
||||
contextDictionary[entry.Key] = ResolveValueIfNecessary( context, value );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -333,8 +333,8 @@ namespace Spring.Web.Support
|
||||
resolvedParameters = new CaseInsensitiveHashtable();
|
||||
foreach (DictionaryEntry entry in this.Parameters)
|
||||
{
|
||||
object key = ResolveRuntimeExpressionIfNecessary( context, entry.Key.ToString() );
|
||||
object value = ResolveRuntimeExpressionIfNecessary( context, entry.Value.ToString() );
|
||||
object key = ResolveValueIfNecessary( context, entry.Key.ToString() );
|
||||
object value = ResolveValueIfNecessary( context, entry.Value.ToString() );
|
||||
resolvedParameters[key] = value;
|
||||
}
|
||||
}
|
||||
@@ -342,6 +342,12 @@ namespace Spring.Web.Support
|
||||
return BuildUrl( path, resolvedParameters );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct the actual url to be executed or returned.
|
||||
/// </summary>
|
||||
/// <param name="resolvedPath">the already evaluated <see cref="TargetPage"/></param>
|
||||
/// <param name="resolvedParameters">the already evaluated parameters.</param>
|
||||
/// <returns>the url to be returned by <see cref="GetRedirectUri"/></returns>
|
||||
protected virtual string BuildUrl( string resolvedPath, IDictionary resolvedParameters )
|
||||
{
|
||||
StringBuilder url = new StringBuilder( 256 );
|
||||
@@ -351,43 +357,63 @@ namespace Spring.Web.Support
|
||||
char separator = '?';
|
||||
foreach (DictionaryEntry entry in resolvedParameters)
|
||||
{
|
||||
url.Append( separator );
|
||||
url.Append( BuildUrlParameter( entry.Key.ToString(), entry.Value.ToString() ) );
|
||||
url.Append( separator );
|
||||
url = BuildUrlParameter( url, entry.Key.ToString(), entry.Value.ToString() );
|
||||
separator = '&';
|
||||
}
|
||||
}
|
||||
return url.ToString();
|
||||
}
|
||||
|
||||
protected virtual string BuildUrlParameter( string key, string value )
|
||||
/// <summary>
|
||||
/// Append the url parameter to the url being constructed.
|
||||
/// </summary>
|
||||
/// <param name="url">the <see cref="StringBuilder"/> containing the url constructed so far.</param>
|
||||
/// <param name="key">the parameter key</param>
|
||||
/// <param name="value">the parameter value</param>
|
||||
/// <returns>the <see cref="StringBuilder"/> to use for further url construction.</returns>
|
||||
protected virtual StringBuilder BuildUrlParameter( StringBuilder url, string key, string value )
|
||||
{
|
||||
return UrlEncode( key ) + "=" + UrlEncode( value );
|
||||
url.Append( WebUtils.UrlEncode( key ) )
|
||||
.Append( '=' )
|
||||
.Append( WebUtils.UrlEncode( value ) );
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
protected static string UrlEncode( string value )
|
||||
/// <summary>
|
||||
/// Evaluates <paramref name="value"/> within <paramref name="context"/> and returns the evaluation result.
|
||||
/// </summary>
|
||||
/// <param name="context">the context to be used for evaluation.</param>
|
||||
/// <param name="value">the string that might need evaluation</param>
|
||||
/// <returns>the evaluation result. Unodified <paramref name="value"/> if no evalution occured.</returns>
|
||||
protected virtual object ResolveValueIfNecessary( object context, string value )
|
||||
{
|
||||
HttpContext ctx = HttpContext.Current;
|
||||
return (ctx == null) ? HttpUtility.UrlEncode( value ) : ctx.Server.UrlEncode( value );
|
||||
return ResolveSpELRuntimeExpressionIfNecessary( context, value );
|
||||
}
|
||||
|
||||
protected object ResolveRuntimeExpressionIfNecessary( object context, string value )
|
||||
{
|
||||
if (IsRuntimeExpression( value ))
|
||||
{
|
||||
return ResolveRuntimeExpression( context, value );
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private static bool IsRuntimeExpression( string value )
|
||||
/// <summary>
|
||||
/// Checks, if value is a SpEL expression <c>${expression}</c> or <c>%{expression}</c>.
|
||||
/// </summary>
|
||||
private static bool IsSpELRuntimeExpression( string value )
|
||||
{
|
||||
// allow for 2 alternative prefixes (SPRNET-864)
|
||||
return (value.StartsWith( "${" ) || value.StartsWith( "%{" )) && value.EndsWith( "}" );
|
||||
}
|
||||
|
||||
private static object ResolveRuntimeExpression( object context, string value )
|
||||
/// <summary>
|
||||
/// If <paramref name="value"/> is a SpEL expression (<c>${expression}</c> or <c>%{expression}</c>), evaluates
|
||||
/// the value against <paramref name="context"/>.
|
||||
/// </summary>
|
||||
protected static object ResolveSpELRuntimeExpressionIfNecessary( object context, string value )
|
||||
{
|
||||
return ExpressionEvaluator.GetValue( context, value.Substring( 2, value.Length - 3 ) );
|
||||
AssertUtils.ArgumentNotNull(value, "value");
|
||||
|
||||
if (IsSpELRuntimeExpression( value ))
|
||||
{
|
||||
return ExpressionEvaluator.GetValue( context, value.Substring( 2, value.Length - 3 ) );
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -443,9 +469,14 @@ namespace Spring.Web.Support
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves dynamic expression contained in <see cref="TargetPage"/> if any by calling <see cref="ResolveValueIfNecessary"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">the context to be used for evaluating the expression</param>
|
||||
/// <returns>the evaluated expression</returns>
|
||||
protected string GetResolvedTargetPage( object context )
|
||||
{
|
||||
return ResolveRuntimeExpressionIfNecessary( context, TargetPage ).ToString();
|
||||
return ResolveValueIfNecessary( context, TargetPage ).ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -24,11 +24,65 @@ using System;
|
||||
using System.Collections;
|
||||
using Spring.Collections;
|
||||
using Spring.Util;
|
||||
using Spring.Web.UI;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// A result factory is responsible for create an <see cref="IResult"/> instance from a given string representation.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Factories get registered with the <see cref="ResultFactoryRegistry"/> for a certain <i>resultMode</i> string.
|
||||
/// <see cref="DefaultResultWebNavigator"/> uses <see cref="ResultFactoryRegistry"/> for converting strings into <see cref="IResult"/> instances
|
||||
/// implementing the corresponding navigation logic.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Result string representations are always of the form:<br/>
|
||||
/// <c>"<resultmode>:<textual result representation>"</c><br/>
|
||||
/// Calling <see cref="CreateResult"/> on the registry will cause the registry to first extract the leading <c>resultmode</c> to obtain
|
||||
/// the corresponding <see cref="IResultFactory"/> instance and handle the actual <see cref="IResult"/> instantiation by delegating to
|
||||
/// <see cref="IResultFactory.CreateResult"/>.
|
||||
/// </para>
|
||||
/// <example>
|
||||
/// The following example illustrates the usual flow:
|
||||
/// <code>
|
||||
/// class MySpecialResultLogic : IResult
|
||||
/// {
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// class MySpecialResultLogicFactory : IResultFactory
|
||||
/// {
|
||||
/// IResult Create( string mode, string expression ) { /* ... convert 'expression' into
|
||||
/// MySpecialResultLogic */ }
|
||||
/// }
|
||||
///
|
||||
/// // register with global factory
|
||||
/// ResultFactoryRegistry.RegisterResultFactory( "mySpecialMode", new MySpecialResultLogicFactory );
|
||||
///
|
||||
/// // configure your Results
|
||||
/// <object type="mypage.aspx">
|
||||
/// <property name="Results">
|
||||
/// <dictionary>
|
||||
/// <entry key="continue" value="mySpecialMode:<some MySpecialResultLogic string representation>" />
|
||||
/// </dictionary>
|
||||
/// </property>
|
||||
///
|
||||
/// // on your page call
|
||||
/// myPage.SetResult("continue");
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// </remarks>
|
||||
/// <seealso cref="ResultFactoryRegistry"/>
|
||||
/// <seealso cref="IResult"/>
|
||||
/// <seealso cref="Result"/>
|
||||
/// <seealso cref="DefaultResultWebNavigator"/>
|
||||
/// <seealso cref="Page.SetResult(string, object)"/>
|
||||
/// <seealso cref="UserControl.SetResult(string, object)"/>
|
||||
/// <author>Erich Eichinger</author>
|
||||
public class ResultFactoryRegistry
|
||||
{
|
||||
private static readonly IDictionary s_registeredFactories = new CaseInsensitiveHashtable();
|
||||
@@ -39,6 +93,9 @@ namespace Spring.Web.Support
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the factory registry to its defaults. Mainly used for unit testing.
|
||||
/// </summary>
|
||||
public static void Reset()
|
||||
{
|
||||
s_defaultFactory = null;
|
||||
@@ -52,21 +109,45 @@ namespace Spring.Web.Support
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current <see cref="IResultFactory"/> set by <see cref="SetDefaultFactory"/>. Will never be null.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default factory is responsible for handling any unknown result modes.
|
||||
/// </remarks>
|
||||
public static IResultFactory DefaultResultFactory
|
||||
{
|
||||
get { return s_defaultFactory; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a new default factory
|
||||
/// </summary>
|
||||
/// <param name="resultFactory">the new default factory instance. Must not be null.</param>
|
||||
/// <returns>the previous default factory.</returns>
|
||||
public static IResultFactory SetDefaultFactory(IResultFactory resultFactory)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(resultFactory, "resultFactory");
|
||||
|
||||
IResultFactory prevFactory = s_defaultFactory;
|
||||
s_defaultFactory = resultFactory;
|
||||
return prevFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a <see cref="IResultFactory"/> for the specified <paramref name="resultMode"/>.
|
||||
/// </summary>
|
||||
/// <param name="resultMode">the resultMode. Must not be null.</param>
|
||||
/// <param name="resultFactory">the factory respponsible for handling <paramref name="resultMode"/> results. Must not be null.</param>
|
||||
/// <returns>the factory previously registered for the specified <paramref name="resultMode"/>, if any.</returns>
|
||||
/// <remarks>
|
||||
/// See <see cref="ResultFactoryRegistry"/> overview for more information.
|
||||
/// </remarks>
|
||||
public static IResultFactory RegisterResultMode( string resultMode, IResultFactory resultFactory )
|
||||
{
|
||||
AssertUtils.ArgumentHasText(resultMode, "resultMode");
|
||||
AssertUtils.ArgumentNotNull(resultFactory, "resultFactory");
|
||||
|
||||
lock (s_registeredFactories.SyncRoot)
|
||||
{
|
||||
IResultFactory prevFactory = (IResultFactory) s_registeredFactories[resultMode];
|
||||
@@ -75,8 +156,28 @@ namespace Spring.Web.Support
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a result from the specified <paramref name="resultText"/> by extracting the result mode from
|
||||
/// the text and delegating to a corresponding <see cref="IResultFactory"/>, if any.
|
||||
/// </summary>
|
||||
/// <param name="resultText">the 'resultmode'-prefixed textual representation of the result instance to create.</param>
|
||||
/// <returns>
|
||||
/// the <see cref="IResult"/> instance corresponding to the textual <paramref name="resultText"/> represenation,
|
||||
/// created by the <see cref="IResultFactory"/>
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// if either <paramref name="resultText"/> is null or <see cref="IResultFactory.CreateResult"/> returned null.</exception>
|
||||
/// <remarks>
|
||||
/// This method guarantees that the return value will always be non-null.<br/>
|
||||
/// <paramref name="resultText"/> must always be of the form <c>"<resultmode>:<textual result representation>"</c>.
|
||||
/// The <c>resultmode</c> will be extracted and the corresponding <see cref="IResultFactory"/> (previously registered
|
||||
/// using <see cref="RegisterResultMode"/>) is called to actually create the <see cref="IResult"/> instance. If no factory matches
|
||||
/// <c>resultmode</c>, the call is handled to the <see cref="DefaultResultFactory"/>.
|
||||
/// </remarks>
|
||||
public static IResult CreateResult( string resultText )
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(resultText, "resultText");
|
||||
|
||||
IResultFactory resultFactory = null;
|
||||
string resultMode = null;
|
||||
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Spring.Collections;
|
||||
using Spring.Core;
|
||||
using Spring.Util;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
public class ResultWebNavigator : IResultWebNavigator
|
||||
{
|
||||
private IWebNavigator _parentNavigator;
|
||||
private bool _ignoreCase;
|
||||
private IDictionary _results;
|
||||
|
||||
public bool IsCaseSensitive
|
||||
{
|
||||
get { return !_ignoreCase; }
|
||||
}
|
||||
|
||||
public virtual IWebNavigator ParentNavigator
|
||||
{
|
||||
get { return _parentNavigator; }
|
||||
set
|
||||
{
|
||||
if (_parentNavigator != null)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull( _parentNavigator, "Parent", "Navigator already has a parent" );
|
||||
}
|
||||
_parentNavigator = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets map of result names to target URLs
|
||||
/// </summary>
|
||||
public IDictionary Results
|
||||
{
|
||||
get
|
||||
{
|
||||
return _results;
|
||||
}
|
||||
set
|
||||
{
|
||||
_results = CreateResultsDictionary(value);
|
||||
}
|
||||
}
|
||||
|
||||
public ResultWebNavigator()
|
||||
:this(null, null, true)
|
||||
{}
|
||||
|
||||
public ResultWebNavigator( IWebNavigator parent, IDictionary results, bool ignoreCase )
|
||||
{
|
||||
this._parentNavigator = parent;
|
||||
this._ignoreCase = ignoreCase;
|
||||
this._results = CreateResultsDictionary( results );
|
||||
}
|
||||
|
||||
protected virtual IDictionary CreateResultsDictionary( IDictionary initialResults )
|
||||
{
|
||||
IDictionary newResults = (_ignoreCase) ? new CaseInsensitiveHashtable() : new Hashtable();
|
||||
if (initialResults != null)
|
||||
{
|
||||
foreach(DictionaryEntry entry in initialResults)
|
||||
{
|
||||
newResults[entry.Key.ToString()] = entry.Value;
|
||||
}
|
||||
}
|
||||
return newResults;
|
||||
}
|
||||
|
||||
public virtual bool CanNavigateTo( string resultName )
|
||||
{
|
||||
if (_results.Contains( resultName ))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return (ParentNavigator != null) ? ParentNavigator.CanNavigateTo( resultName ) : false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redirects user to a URL mapped to specified result name.
|
||||
/// </summary>
|
||||
/// <param name="resultName">Name of the result.</param>
|
||||
/// <param name="context">The context to use for evaluating the SpEL expression in the Result.</param>
|
||||
public virtual void NavigateTo( string resultName, object context )
|
||||
{
|
||||
IResult result = GetResult( resultName );
|
||||
if (result == null)
|
||||
{
|
||||
if (ParentNavigator != null)
|
||||
{
|
||||
ParentNavigator.NavigateTo( resultName, context );
|
||||
return;
|
||||
}
|
||||
throw new ArgumentException( string.Format( "No result mapping found for the specified name '{0}'.", resultName ), "resultName" );
|
||||
}
|
||||
result.Navigate( context );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a redirect url string that points to the
|
||||
/// <see cref="Spring.Web.Support.Result.TargetPage"/> defined by this
|
||||
/// result evaluated using this Page for expression
|
||||
/// </summary>
|
||||
/// <param name="resultName">Name of the result.</param>
|
||||
/// <param name="context">The context to use for evaluating the SpEL expression in the Result</param>
|
||||
/// <returns>A redirect url string.</returns>
|
||||
public virtual string GetResultUri( string resultName, object context )
|
||||
{
|
||||
IResult result = GetResult( resultName );
|
||||
if (result == null)
|
||||
{
|
||||
if (ParentNavigator != null)
|
||||
{
|
||||
return result.GetRedirectUri( context );
|
||||
}
|
||||
throw new ArgumentException( string.Format( "No result mapping found for the specified name '{0}'.", resultName ), "resultName" );
|
||||
}
|
||||
return result.GetRedirectUri( context );
|
||||
}
|
||||
|
||||
protected IResult GetResult( string name )
|
||||
{
|
||||
object val = _results[name];
|
||||
if (val == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (val is IResult)
|
||||
{
|
||||
return (IResult)val;
|
||||
}
|
||||
else if (val is String)
|
||||
{
|
||||
return ResultFactoryRegistry.CreateResult( (string)val );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new TypeMismatchException(
|
||||
"Unable to create result object. Please use either String or Result instances to define results." );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Web.UI;
|
||||
using Spring.Util;
|
||||
@@ -32,20 +33,70 @@ namespace Spring.Web.Support
|
||||
/// An implementation of <see cref="IHierarchicalWebNavigator"/> specific for <see cref="Control"/>s.
|
||||
/// The navigator hierarchy equals the control hierarchy when using a <see cref="WebFormsResultWebNavigator"/>.
|
||||
/// </summary>
|
||||
public class WebFormsResultWebNavigator : ResultWebNavigator
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This implementation supports 2 different navigator hierarchies:
|
||||
/// <ul>
|
||||
/// <li>The default hierarchy defined by <see cref="IHierarchicalWebNavigator.ParentNavigator"/></li>
|
||||
/// <li>The hierarchy defined by a web form's <see cref="Control.Parent"/> hierarchy.</li>
|
||||
/// </ul>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This implementation always checks the standard hierarchy first and - if a destination cannot be resolved, falls back
|
||||
/// to the control hierarchy for resolving a specified navigation destination.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class WebFormsResultWebNavigator : DefaultResultWebNavigator
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds the result match from <see cref="FindNavigableParent"/>.
|
||||
/// </summary>
|
||||
protected class NavigableControlInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The matching control
|
||||
/// </summary>
|
||||
public readonly Control Control;
|
||||
/// <summary>
|
||||
/// The <see cref="IWebNavigator"/> instance associated with the control. May be null.
|
||||
/// </summary>
|
||||
public readonly IWebNavigator WebNavigator;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the new match instance.
|
||||
/// </summary>
|
||||
/// <param name="control">the matching control. Must not be null!</param>
|
||||
public NavigableControlInfo( Control control )
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(control, "control");
|
||||
|
||||
Control = control;
|
||||
|
||||
if (Control is IWebNavigable)
|
||||
{
|
||||
WebNavigator = ((IWebNavigable)Control).WebNavigator;
|
||||
}
|
||||
else if (Control is IWebNavigator)
|
||||
{
|
||||
WebNavigator = (IWebNavigator)control;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the next <see cref="IWebNavigator"/> up the control hierarchy,
|
||||
/// starting at the specified <paramref name="control"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method checks both, for controls implementing <see cref="IWebNavigator"/> or <see cref="IWebNavigable"/>. In addition
|
||||
/// when MasterPages are used, it interprets the control hierarchy as control->page->masterpage.
|
||||
/// when MasterPages are used, it interprets the control hierarchy as control->page->masterpage. (<see cref="WebUtils.GetLogicalParent"/>).
|
||||
/// </remarks>
|
||||
/// <param name="control">the control to start the search with.</param>
|
||||
/// <param name="includeSelf">include checking the control itself or start search with its parent.</param>
|
||||
/// <returns>If found, the next <see cref="IWebNavigator"/> up the hierarchy. <c>null</c> otherwise</returns>
|
||||
public static IWebNavigator FindWebNavigator( Control control, bool includeSelf )
|
||||
/// <param name="restrictToValidNavigatorsOnly">requires <see cref="IWebNavigable"/>s to hold a valid <see cref="IWebNavigable.WebNavigator"/> instance.</param>
|
||||
/// <returns>If found, the next <see cref="IWebNavigator"/> or <see cref="IWebNavigable"/>.
|
||||
/// <c>null</c> otherwise</returns>
|
||||
protected static NavigableControlInfo FindNavigableParent( Control control, bool includeSelf, bool restrictToValidNavigatorsOnly )
|
||||
{
|
||||
while (control != null)
|
||||
{
|
||||
@@ -58,40 +109,151 @@ namespace Spring.Web.Support
|
||||
|
||||
if (control is IWebNavigable || control is IWebNavigator)
|
||||
{
|
||||
return (control is IWebNavigable) ? ((IWebNavigable)control).WebNavigator : (IWebNavigator)control;
|
||||
NavigableControlInfo nci = new NavigableControlInfo(control);
|
||||
if (!restrictToValidNavigatorsOnly)
|
||||
{
|
||||
return nci;
|
||||
}
|
||||
if (nci.WebNavigator != null)
|
||||
{
|
||||
return nci;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Control _owner;
|
||||
private readonly Control _owner;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Control"/> that this <see cref="WebFormsResultWebNavigator"/> is associated with.
|
||||
/// </summary>
|
||||
public Control Owner
|
||||
{
|
||||
get { return _owner; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of a <see cref="IHierarchicalWebNavigator"/> for the specified control.
|
||||
/// </summary>
|
||||
/// <param name="owner">the control to be associated with this navigator.</param>
|
||||
/// <param name="results">a dictionary containing results</param>
|
||||
/// <param name="ignoreCase">determines, whether to interpret result names case-sensitive or not.</param>
|
||||
public WebFormsResultWebNavigator( Control owner, IDictionary results, bool ignoreCase )
|
||||
: base( null, results, ignoreCase )
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(owner, "owner");
|
||||
/// <param name="parent">the direct parent of this navigator</param>
|
||||
/// <param name="initialResults">a dictionary containing results</param>
|
||||
/// <param name="ignoreCase">specifies how to handle case for destination names.</param>
|
||||
public WebFormsResultWebNavigator( Control owner, IWebNavigator parent, IDictionary initialResults, bool ignoreCase )
|
||||
: base( parent, initialResults, ignoreCase )
|
||||
{
|
||||
AssertUtils.ArgumentNotNull( owner, "owner" );
|
||||
_owner = owner;
|
||||
}
|
||||
|
||||
public override IWebNavigator ParentNavigator
|
||||
/// <summary>
|
||||
/// Determines, whether this navigator or one of its parents can
|
||||
/// navigate to the destination specified in <paramref name="destination"/>.
|
||||
/// </summary>
|
||||
/// <param name="destination">the name of the navigation destination</param>
|
||||
/// <returns>true, if this navigator can navigate to the destination.</returns>
|
||||
public override bool CanNavigateTo( string destination )
|
||||
{
|
||||
return CheckCanNavigate( destination, true );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check, whether this navigator can navigate to the specified <paramref name="destination"/>.
|
||||
/// </summary>
|
||||
/// <param name="destination">the destination name to check.</param>
|
||||
/// <param name="includeControlHierarchy">
|
||||
/// whether the check shall include the <see cref="Owner"/> control hierarchy or
|
||||
/// the standard <see cref="IHierarchicalWebNavigator.ParentNavigator"/> hierarchy only.
|
||||
/// </param>
|
||||
protected bool CheckCanNavigate( string destination, bool includeControlHierarchy )
|
||||
{
|
||||
// check the default path
|
||||
if (base.CanNavigateTo( destination ))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// include checking the control hierarchy
|
||||
if (includeControlHierarchy)
|
||||
{
|
||||
NavigableControlInfo nci = FindNavigableParent( this._owner, false, true );
|
||||
if (nci != null)
|
||||
{
|
||||
// when delegating upwards, the control containing the matching result
|
||||
// will appear as sender - this makes dealing with expressions more "natural".
|
||||
return nci.WebNavigator.CanNavigateTo( destination );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a redirect url string that points to the
|
||||
/// <see cref="Spring.Web.Support.Result.TargetPage"/> defined by this
|
||||
/// result evaluated using this Page for expression
|
||||
/// </summary>
|
||||
/// <param name="destination">Name of the result.</param>
|
||||
/// <param name="sender">the instance that issued this request</param>
|
||||
/// <param name="context">The context to use for evaluating the SpEL expression in the Result</param>
|
||||
/// <returns>A redirect url string.</returns>
|
||||
public override string GetResultUri( string destination, object sender, object context )
|
||||
{
|
||||
if (this.CheckCanNavigate( destination, false ))
|
||||
{
|
||||
return base.GetResultUri( destination, sender, context );
|
||||
}
|
||||
|
||||
NavigableControlInfo nci = FindNavigableParent( this._owner, false, true );
|
||||
if (nci != null)
|
||||
{
|
||||
// when delegating upwards, the control containing the matching result
|
||||
// will appear as sender - this makes dealing with expressions more "natural".
|
||||
return nci.WebNavigator.GetResultUri( destination, nci.Control, context );
|
||||
}
|
||||
|
||||
return HandleUnknownDestination( destination, sender, context );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redirects user to a URL mapped to specified result name.
|
||||
/// </summary>
|
||||
/// <param name="destination">Name of the result.</param>
|
||||
/// <param name="sender">the instance that issued this request</param>
|
||||
/// <param name="context">The context to use for evaluating the SpEL expression in the Result.</param>
|
||||
public override void NavigateTo( string destination, object sender, object context )
|
||||
{
|
||||
if (this.CheckCanNavigate( destination, false ))
|
||||
{
|
||||
base.NavigateTo( destination, sender, context );
|
||||
return;
|
||||
}
|
||||
|
||||
NavigableControlInfo nci = FindNavigableParent( this._owner, false, true );
|
||||
if (nci != null)
|
||||
{
|
||||
// when delegating upwards, the control containing the matching result
|
||||
// will appear as sender - this makes dealing with expressions more "natural".
|
||||
nci.WebNavigator.NavigateTo( destination, nci.Control, context );
|
||||
return;
|
||||
}
|
||||
|
||||
HandleUnknownDestination( destination, sender, context );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the next available <see cref="IWebNavigator"/> within
|
||||
/// this <see cref="Owner"/> control's parent hierarchy.
|
||||
/// </summary>
|
||||
public IWebNavigator ParentControlNavigator
|
||||
{
|
||||
get
|
||||
{
|
||||
if (base.ParentNavigator == null)
|
||||
{
|
||||
base.ParentNavigator = FindWebNavigator(_owner, false);
|
||||
}
|
||||
return base.ParentNavigator;
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new System.NotSupportedException("cannot set parent navigator on a WebFormsResultWebNavigator");
|
||||
// nci.WebNavigator is guaranteed to be non-null!
|
||||
NavigableControlInfo nci = FindNavigableParent( this._owner, false, true );
|
||||
if (nci == null) return null;
|
||||
return nci.WebNavigator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Web.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Adapts a concrete <see cref="IWebNavigator"/> instance as a <see cref="IWebNavigable"/>.
|
||||
/// </summary>
|
||||
/// <author>Erich Eichinger</author>
|
||||
public class WebNavigableWebNavigatorAdapter : IWebNavigable
|
||||
{
|
||||
private readonly IWebNavigator _resultNavigator;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new adapter instance, wrapping the specified <paramref name="resultNavigator"/>
|
||||
/// into a <see cref="IWebNavigable"/> interface.
|
||||
/// </summary>
|
||||
/// <param name="resultNavigator">the <see cref="IWebNavigator"/> instance to be adapted. May be null.</param>
|
||||
public WebNavigableWebNavigatorAdapter(IWebNavigator resultNavigator)
|
||||
{
|
||||
_resultNavigator = resultNavigator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the wrapped <see cref="IWebNavigator"/> that was passed into <see cref="WebNavigableWebNavigatorAdapter(IWebNavigator)"/>.
|
||||
/// </summary>
|
||||
public IWebNavigator WebNavigator
|
||||
{
|
||||
get { return _resultNavigator; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,6 +90,13 @@ namespace Spring.Web.UI.Controls
|
||||
private bool _renderContainerTag;
|
||||
private string _visibleConditionExpression;
|
||||
|
||||
/// <summary>
|
||||
/// An optional SpEL expression to control this Panel's <see cref="Control.Visible"/> state.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This panel instance is the context for evaluating the given expression. If no expression is specified, visibility behavior
|
||||
/// reverts to standard behavior.
|
||||
/// </remarks>
|
||||
public string VisibleIf
|
||||
{
|
||||
get { return _visibleConditionExpression; }
|
||||
@@ -116,24 +123,38 @@ namespace Spring.Web.UI.Controls
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overridden to suppress rendering this control's tag
|
||||
/// Overridden to set <see cref="Control.Visible"/> according to <see cref="VisibleIf"/> if necessary.
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
protected override void Render(HtmlTextWriter writer)
|
||||
protected override void OnPreRender( EventArgs e )
|
||||
{
|
||||
bool visible = (_visibleConditionExpression != null)
|
||||
this.Visible = (_visibleConditionExpression != null)
|
||||
? Spring.Expressions.ExpressionEvaluator.GetValue(this, _visibleConditionExpression).Equals(true)
|
||||
: this.Visible;
|
||||
|
||||
if (!visible) return;
|
||||
base.OnPreRender( e );
|
||||
}
|
||||
|
||||
if (_renderContainerTag)
|
||||
///<summary>
|
||||
///Renders the HTML opening tag of the <see cref="Panel"></see> control to the specified writer.
|
||||
///</summary>
|
||||
///<param name="writer">An <see cref="T:System.Web.UI.HtmlTextWriter"></see> that represents the output stream to render HTML content on the client.</param>
|
||||
public override void RenderBeginTag( HtmlTextWriter writer )
|
||||
{
|
||||
if (this.RenderContainerTag)
|
||||
{
|
||||
base.Render(writer);
|
||||
base.RenderBeginTag( writer );
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Renders the HTML closing tag of the <see cref="Panel"></see> control to the specified writer.
|
||||
///</summary>
|
||||
///<param name="writer">An <see cref="T:System.Web.UI.HtmlTextWriter"></see> that represents the output stream to render HTML content on the client.</param>
|
||||
public override void RenderEndTag( HtmlTextWriter writer )
|
||||
{
|
||||
if (this.RenderContainerTag)
|
||||
{
|
||||
base.RenderContents(writer);
|
||||
base.RenderEndTag( writer );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -437,7 +437,7 @@ namespace Spring.Web.UI
|
||||
/// </remarks>
|
||||
protected virtual void InitializeNavigationSupport()
|
||||
{
|
||||
webNavigator = new WebFormsResultWebNavigator(this, null, true);
|
||||
webNavigator = new WebFormsResultWebNavigator(this, null, null, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -526,7 +526,7 @@ namespace Spring.Web.UI
|
||||
/// <param name="resultName">Result name.</param>
|
||||
protected void SetResult( string resultName )
|
||||
{
|
||||
WebNavigator.NavigateTo( resultName, this );
|
||||
WebNavigator.NavigateTo( resultName, this, null );
|
||||
}
|
||||
|
||||
|
||||
@@ -537,7 +537,7 @@ namespace Spring.Web.UI
|
||||
/// <param name="context">The context to use for evaluating the SpEL expression in the Result.</param>
|
||||
protected void SetResult( string resultName, object context )
|
||||
{
|
||||
WebNavigator.NavigateTo( resultName, context );
|
||||
WebNavigator.NavigateTo( resultName, this, context );
|
||||
}
|
||||
|
||||
|
||||
@@ -550,7 +550,7 @@ namespace Spring.Web.UI
|
||||
/// <returns>A redirect url string.</returns>
|
||||
protected string GetResultUrl( string resultName )
|
||||
{
|
||||
return ResolveUrl( WebNavigator.GetResultUri( resultName, this ) );
|
||||
return ResolveUrl( WebNavigator.GetResultUri( resultName, this, null ) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -563,7 +563,7 @@ namespace Spring.Web.UI
|
||||
/// <returns>A redirect url string.</returns>
|
||||
protected string GetResultUrl( string resultName, object context )
|
||||
{
|
||||
return ResolveUrl( WebNavigator.GetResultUri( resultName, context ) );
|
||||
return ResolveUrl( WebNavigator.GetResultUri( resultName, this, context ) );
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -136,6 +136,12 @@ namespace Spring.Web.UI
|
||||
|
||||
#region Page lifecycle methods
|
||||
|
||||
/// <summary>
|
||||
/// Creates and initializes the new page instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Calls <see cref="InitializeNavigationSupport"/>.
|
||||
/// </remarks>
|
||||
public Page()
|
||||
{
|
||||
InitializeNavigationSupport();
|
||||
@@ -1044,7 +1050,7 @@ namespace Spring.Web.UI
|
||||
/// </remarks>
|
||||
protected virtual void InitializeNavigationSupport()
|
||||
{
|
||||
webNavigator = new WebFormsResultWebNavigator( this, null, true );
|
||||
webNavigator = new WebFormsResultWebNavigator( this, null, null, true );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1136,7 +1142,7 @@ namespace Spring.Web.UI
|
||||
/// <param name="resultName">Result name.</param>
|
||||
protected void SetResult( string resultName )
|
||||
{
|
||||
WebNavigator.NavigateTo( resultName, this );
|
||||
WebNavigator.NavigateTo( resultName, this, null );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1146,7 +1152,7 @@ namespace Spring.Web.UI
|
||||
/// <param name="context">The context to use for evaluating the SpEL expression in the Result.</param>
|
||||
protected void SetResult( string resultName, object context )
|
||||
{
|
||||
WebNavigator.NavigateTo( resultName, context );
|
||||
WebNavigator.NavigateTo( resultName, this, context );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1158,7 +1164,7 @@ namespace Spring.Web.UI
|
||||
/// <returns>A redirect url string.</returns>
|
||||
protected string GetResultUrl( string resultName )
|
||||
{
|
||||
return ResolveUrl( WebNavigator.GetResultUri( resultName, this ) );
|
||||
return ResolveUrl( WebNavigator.GetResultUri( resultName, this, null ) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1171,7 +1177,7 @@ namespace Spring.Web.UI
|
||||
/// <returns>A redirect url string.</returns>
|
||||
protected string GetResultUrl( string resultName, object context )
|
||||
{
|
||||
return ResolveUrl( WebNavigator.GetResultUri( resultName, context ) );
|
||||
return ResolveUrl( WebNavigator.GetResultUri( resultName, this, context ) );
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -496,7 +496,7 @@ namespace Spring.Web.UI
|
||||
/// </remarks>
|
||||
protected virtual void InitializeNavigationSupport()
|
||||
{
|
||||
webNavigator = new WebFormsResultWebNavigator(this, null, true);
|
||||
webNavigator = new WebFormsResultWebNavigator(this, null, null, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -585,7 +585,7 @@ namespace Spring.Web.UI
|
||||
/// <param name="resultName">Result name.</param>
|
||||
protected void SetResult( string resultName )
|
||||
{
|
||||
WebNavigator.NavigateTo( resultName, this );
|
||||
WebNavigator.NavigateTo( resultName, this, null );
|
||||
}
|
||||
|
||||
|
||||
@@ -596,7 +596,7 @@ namespace Spring.Web.UI
|
||||
/// <param name="context">The context to use for evaluating the SpEL expression in the Result.</param>
|
||||
protected void SetResult( string resultName, object context )
|
||||
{
|
||||
WebNavigator.NavigateTo( resultName, context );
|
||||
WebNavigator.NavigateTo( resultName, this, context );
|
||||
}
|
||||
|
||||
|
||||
@@ -609,7 +609,7 @@ namespace Spring.Web.UI
|
||||
/// <returns>A redirect url string.</returns>
|
||||
protected string GetResultUrl( string resultName )
|
||||
{
|
||||
return ResolveUrl( WebNavigator.GetResultUri( resultName, this ) );
|
||||
return ResolveUrl( WebNavigator.GetResultUri( resultName, this, null ) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -622,7 +622,7 @@ namespace Spring.Web.UI
|
||||
/// <returns>A redirect url string.</returns>
|
||||
protected string GetResultUrl( string resultName, object context )
|
||||
{
|
||||
return ResolveUrl( WebNavigator.GetResultUri( resultName, context ) );
|
||||
return ResolveUrl( WebNavigator.GetResultUri( resultName, this, context ) );
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace Spring.Dao.Attributes
|
||||
{
|
||||
//Expected
|
||||
Assert.AreSame(persistenceException, ex.InnerException);
|
||||
} catch (PersistenceException ex)
|
||||
} catch (PersistenceException)
|
||||
{
|
||||
Assert.Fail("Should have been translated");
|
||||
}
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
<Compile Include="Web\Support\AbstractHandlerFactoryTests.cs" />
|
||||
<Compile Include="Web\Support\MimeMediaTypeTests.cs" />
|
||||
<Compile Include="Web\Support\PageHandlerFactoryTests.cs" />
|
||||
<Compile Include="Web\Support\ResultFactoryRegistryTests.cs" />
|
||||
<Compile Include="Web\Support\ResultTests.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace Spring.Web.UI
|
||||
}
|
||||
catch(ArgumentException ae)
|
||||
{
|
||||
string expected = string.Format("No result mapping found for the specified name '{0}'.", RESULTNAME);
|
||||
string expected = string.Format("No mapping found for the specified destination '{0}'.", RESULTNAME);
|
||||
string msg = ae.Message.Substring(0, expected.Length);
|
||||
Assert.AreEqual(expected, msg);
|
||||
}
|
||||
|
||||
@@ -105,8 +105,8 @@ namespace Spring.Web.UI
|
||||
|
||||
using (mocks.Ordered())
|
||||
{
|
||||
// context is the control, that SetResult() was called on
|
||||
theResult.Navigate(c111);
|
||||
// context is the control, that contains matching Result
|
||||
theResult.Navigate(c1);
|
||||
}
|
||||
mocks.ReplayAll();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user