SPRNET-1038

added missing validation to SpringAir "SuggestedFlights" view
This commit is contained in:
eeichinger
2008-09-22 17:10:59 +00:00
parent 1f0516b867
commit 2f5e5c701f
13 changed files with 935 additions and 835 deletions

View File

@@ -9,6 +9,8 @@ Spring.Core
3. Removed getter property of IResourceLoader in IResourceLoaderAware
4. AbstractBinding.IsValid property changed to method AbstractBinding.IsValid( IValidationErrors )
Spring.Services
---------------
1. Removed WebServiceProxyFactory.ClientProtocolType property (obsolete)

View File

@@ -3,10 +3,12 @@
<asp:Content ID="body" ContentPlaceHolderID="body" runat="server">
<h4 align="center">
<asp:Label ID="caption" runat="server" /></h4>
<spring:ValidationSummary ID="validationSummary" Provider="summary" runat="server" />
<asp:Label ID="caption" runat="server" /></h4>
<br />
<table cellspacing="0" cellpadding="0" width="90%" align="center" border="0">
<tr>
<td>&nbsp;<spring:ValidationSummary ID="validationSummary" Provider="summary" runat="server" /><br/></td>
</tr>
<tr>
<td>
<input id="outboundFlight" type="hidden" name="outboundFlight" runat="server" />

View File

@@ -82,9 +82,9 @@ public partial class SuggestedFlights : Page
protected override void LoadModel(object savedModel)
{
IDictionary model = (IDictionary)savedModel;
flights = (FlightSuggestions) model["flights"];
outboundFlightIndex = (int) model["outboundFlightIndex"];
returnFlightIndex = (int) model["returnFlightIndex"];
flights = (FlightSuggestions)model["flights"];
outboundFlightIndex = (int)model["outboundFlightIndex"];
returnFlightIndex = (int)model["returnFlightIndex"];
}
protected override object SaveModel()
@@ -103,12 +103,12 @@ public partial class SuggestedFlights : Page
}
#endregion
#region Page Lifecycle Methods
protected override void OnInitializeControls(EventArgs e)
protected override void OnLoad(EventArgs e)
{
base.OnInitializeControls(e);
base.OnLoad(e);
if (!IsPostBack)
{
@@ -142,13 +142,24 @@ public partial class SuggestedFlights : Page
protected void BookFlights(object sender, EventArgs e)
{
FlightCollection flightsToBook = GetFlightsToBook();
Itinerary itinerary = new Itinerary(flightsToBook);
// TODO: forward to next logical page and get user details...
ReservationConfirmation confirmation = bookingAgent.Book(
new Reservation(new Passenger(1, "Aleksandar", "Seovic"), itinerary));
Session[Constants.ReservationConfirmationKey] = confirmation;
SetResult(ReservationConfirmed);
if ((flights.HasOutboundFlights && !HasOutboundFlight))
{
this.ValidationErrors.AddError("summary", new ErrorMessage("error.outboundFlight.required"));
}
if ((flights.HasReturnFlights && !HasReturnFlight))
{
this.ValidationErrors.AddError("summary", new ErrorMessage("error.returnFlight.required"));
}
if (this.ValidationErrors.IsEmpty)
{
FlightCollection flightsToBook = GetFlightsToBook();
Itinerary itinerary = new Itinerary(flightsToBook);
// TODO: forward to next logical page and get user details...
ReservationConfirmation confirmation = bookingAgent.Book(
new Reservation(new Passenger(1, "Aleksandar", "Seovic"), itinerary));
Session[Constants.ReservationConfirmationKey] = confirmation;
SetResult(ReservationConfirmed);
}
}
private FlightCollection GetFlightsToBook()
@@ -169,5 +180,10 @@ public partial class SuggestedFlights : Page
get { return this.returnFlightIndex != NoFlightSelected; }
}
private bool HasOutboundFlight
{
get { return this.outboundFlightIndex != NoFlightSelected; }
}
#endregion
}

View File

@@ -1,180 +1,236 @@
using System;
using System.Collections;
using Spring.Threading;
using Spring.Util;
using Spring.Validation;
namespace Spring.DataBinding
{
/// <summary>
/// Abstract base class for <see cref="IBinding"/> implementations.
/// </summary>
/// <author>Aleksandar Seovic</author>
public abstract class AbstractBinding : IBinding
{
#region Fields
// each Binding instance needs its own ID
private readonly string BINDING_ID = Guid.NewGuid().ToString("N");
private BindingDirection direction = BindingDirection.Bidirectional;
private ErrorMessage errorMessage;
private string[] errorProviders;
#endregion
#region Properties
/// <summary>
/// Gets or sets a flag specifying whether this binding is valid.
/// </summary>
/// <value>
/// <c>true</c> if this binding evaluated without errors;
/// <c>false</c> otherwise.
/// </value>
public bool IsValid
{
get
{
object val = LogicalThreadContext.GetData(GetIsValidKey());
return val == null || (bool)val;
}
set
{
LogicalThreadContext.SetData(GetIsValidKey(), value);
}
}
/// <summary>
/// Gets or sets the <see cref="BindingDirection"/>.
/// </summary>
/// <value>The binding direction.</value>
public BindingDirection Direction
{
get { return direction; }
set { direction = value; }
}
/// <summary>
/// Gets the error message.
/// </summary>
/// <value>The error message.</value>
public ErrorMessage ErrorMessage
{
get { return errorMessage; }
}
/// <summary>
/// Gets the error providers.
/// </summary>
public string[] ErrorProviders
{
get { return errorProviders; }
}
#endregion
#region IBinding Implementation
/// <summary>
/// Binds source object to target object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
public void BindSourceToTarget(object source, object target, IValidationErrors validationErrors)
{
BindSourceToTarget(source, target, validationErrors, null);
}
/// <summary>
/// Binds target object to source object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
public void BindTargetToSource(object source, object target, IValidationErrors validationErrors)
{
BindTargetToSource(source, target, validationErrors, null);
}
/// <summary>
/// Binds source object to target object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public abstract void BindSourceToTarget(object source, object target, IValidationErrors validationErrors, IDictionary variables);
/// <summary>
/// Binds target object to source object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public abstract void BindTargetToSource(object source, object target, IValidationErrors validationErrors, IDictionary variables);
/// <summary>
/// Sets error message that should be displayed in the case
/// of a non-fatal binding error.
/// </summary>
/// <param name="messageId">
/// Resource ID of the error message.
/// </param>
/// <param name="errorProviders">
/// List of error providers message should be added to.
/// </param>
public void SetErrorMessage(string messageId, params string[] errorProviders)
{
AssertUtils.ArgumentHasText(messageId, "messageId");
if (errorProviders == null || errorProviders.Length == 0)
{
throw new ArgumentException("At least one error provider has to be specified.", "providers");
}
this.errorMessage = new ErrorMessage(messageId, null);
this.errorProviders = errorProviders;
}
#endregion
#region Private Methods
private string GetIsValidKey()
{
return "Binding." + BINDING_ID + ".IsValid";
}
#endregion
}
using System;
using System.Collections;
using Spring.Collections;
using Spring.Util;
using Spring.Validation;
namespace Spring.DataBinding
{
/// <summary>
/// Abstract base class for <see cref="IBinding"/> implementations.
/// </summary>
/// <author>Aleksandar Seovic</author>
public abstract class AbstractBinding : IBinding
{
#region Fields
/// <summary>
/// The name of the always filled error provider
/// </summary>
public static readonly string ALL_BINDINGERRORS_PROVIDER = "__all_bindingerrors";
// each Binding instance needs its own ID
private readonly string BINDING_ID = Guid.NewGuid().ToString("N");
private BindingDirection direction = BindingDirection.Bidirectional;
private BindingErrorMessage errorMessage;
private string[] errorProviders;
#endregion
#region Properties
/// <summary>
/// Gets or sets a flag specifying whether this binding is valid.
/// </summary>
/// <value>
/// <c>true</c> if this binding evaluated without errors;
/// <c>false</c> otherwise.
/// </value>
public bool IsValid(IValidationErrors errors)
{
if (errors == null) return true;
IList errorList = errors.GetErrors(ALL_BINDINGERRORS_PROVIDER);
return (errorList == null) || (!errorList.Contains(this.ErrorMessage));
}
/// <summary>
/// Marks this binding's state as invalid for this validationErrors collection.
/// Returns false if <paramref name="validationErrors"/> is null.
/// </summary>
/// <param name="validationErrors"></param>
/// <returns>false, if validationErrors is null</returns>
protected bool SetInvalid(IValidationErrors validationErrors)
{
if (validationErrors != null)
{
foreach (string provider in this.ErrorProviders)
{
validationErrors.AddError(provider, this.ErrorMessage);
}
return true;
}
return false;
}
///<summary>
/// Gets the unique ID of this binding instance.
///</summary>
public string Id
{
get { return BINDING_ID; }
}
/// <summary>
/// Gets or sets the <see cref="BindingDirection"/>.
/// </summary>
/// <value>The binding direction.</value>
public BindingDirection Direction
{
get { return direction; }
set { direction = value; }
}
/// <summary>
/// Gets the error message.
/// </summary>
/// <value>The error message.</value>
public BindingErrorMessage ErrorMessage
{
get { return errorMessage; }
}
/// <summary>
/// Gets the error providers.
/// </summary>
public string[] ErrorProviders
{
get { return errorProviders; }
}
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Object"></see> class.
/// </summary>
protected AbstractBinding()
{
this.errorMessage = new BindingErrorMessage( this.Id, "Binding-Error");
this.errorProviders = new string[] { ALL_BINDINGERRORS_PROVIDER };
}
#region IBinding Implementation
/// <summary>
/// Binds source object to target object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
public virtual void BindSourceToTarget(object source, object target, IValidationErrors validationErrors)
{
BindSourceToTarget(source, target, validationErrors, null);
}
/// <summary>
/// Binds target object to source object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
public virtual void BindTargetToSource(object source, object target, IValidationErrors validationErrors)
{
BindTargetToSource(source, target, validationErrors, null);
}
/// <summary>
/// Binds source object to target object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public abstract void BindSourceToTarget(object source, object target, IValidationErrors validationErrors, IDictionary variables);
/// <summary>
/// Binds target object to source object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public abstract void BindTargetToSource(object source, object target, IValidationErrors validationErrors, IDictionary variables);
/// <summary>
/// Sets error message that should be displayed in the case
/// of a non-fatal binding error.
/// </summary>
/// <param name="messageId">
/// Resource ID of the error message.
/// </param>
/// <param name="errorProviders">
/// List of error providers message should be added to.
/// </param>
public void SetErrorMessage(string messageId, params string[] errorProviders)
{
AssertUtils.ArgumentHasText(messageId, "messageId");
if (errorProviders == null || errorProviders.Length == 0)
{
throw new ArgumentException("At least one error provider has to be specified.", "providers");
}
this.errorMessage = new BindingErrorMessage(this.BINDING_ID, messageId, null);
Set providers = new HashedSet();
providers.Add(ALL_BINDINGERRORS_PROVIDER);
providers.AddAll(errorProviders);
errorProviders = new string[providers.Count];
providers.CopyTo(errorProviders, 0);
this.errorProviders = errorProviders;
}
#endregion
///<summary>
///Determines whether the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>.
///</summary>
///<returns>
///true if the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>; otherwise, false.
///</returns>
///<param name="obj">The <see cref="T:System.Object"></see> to compare with the current <see cref="T:System.Object"></see>. </param><filterpriority>2</filterpriority>
public override bool Equals(object obj)
{
AbstractBinding other = obj as AbstractBinding;
return (other != null) && (this.Id == other.Id);
}
///<summary>
///Serves as a hash function for a particular type. <see cref="M:System.Object.GetHashCode"></see> is suitable for use in hashing algorithms and data structures like a hash table.
///</summary>
///<returns>
///A hash code for the current <see cref="T:System.Object"></see>.
///</returns>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
}
}

View File

@@ -1,252 +1,226 @@
using System;
using System.Collections;
using Spring.Globalization;
using Spring.Validation;
namespace Spring.DataBinding
{
/// <summary>
/// Abstract base class for simple, one-to-one <see cref="IBinding"/> implementations.
/// </summary>
/// <author>Aleksandar Seovic</author>
public abstract class AbstractSimpleBinding : AbstractBinding
{
#region Fields
private IFormatter formatter;
#endregion
#region Constructor(s)
/// <summary>
/// Initialize a new instance of <see cref="AbstractSimpleBinding"/> without any <see cref="IFormatter"/>
/// </summary>
protected AbstractSimpleBinding()
{
}
/// <summary>
/// Initialize a new instance of <see cref="AbstractSimpleBinding"/> with the
/// specified <see cref="IFormatter"/>.
/// </summary>
protected AbstractSimpleBinding(IFormatter formatter)
{
this.formatter = formatter;
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the <see cref="IFormatter"/> to use.
/// </summary>
/// <value>The formatter to use.</value>
public IFormatter Formatter
{
get { return formatter; }
set { formatter = value; }
}
#endregion
#region IBinding Implementation
/// <summary>
/// Binds source object to target object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public override void BindSourceToTarget(object source, object target, IValidationErrors validationErrors,
IDictionary variables)
{
if (this.IsValid
&&
(this.Direction == BindingDirection.Bidirectional || this.Direction == BindingDirection.SourceToTarget))
{
try
{
DoBindSourceToTarget(source, target, variables);
this.IsValid = true;
}
catch (Exception)
{
this.IsValid = false;
if (this.ErrorMessage != null && validationErrors != null)
{
foreach (string provider in this.ErrorProviders)
{
validationErrors.AddError(provider, this.ErrorMessage);
}
}
else
{
throw;
}
}
}
}
/// <summary>
/// Concrete implementation if source to target binding.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
protected virtual void DoBindSourceToTarget(object source, object target, IDictionary variables)
{
object value = this.GetSourceValue(source, variables);
if (this.Formatter != null && value is string)
{
value = this.Formatter.Parse((string) value);
}
this.SetTargetValue(target, value, variables);
}
/// <summary>
/// Binds target object to source object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public override void BindTargetToSource(object source, object target, IValidationErrors validationErrors,
IDictionary variables)
{
if (this.IsValid
&&
(this.Direction == BindingDirection.Bidirectional || this.Direction == BindingDirection.TargetToSource))
{
try
{
DoBindTargetToSource(source, target, variables);
this.IsValid = true;
}
catch (Exception)
{
this.IsValid = false;
if (this.ErrorMessage != null && validationErrors != null)
{
foreach (string provider in this.ErrorProviders)
{
validationErrors.AddError(provider, this.ErrorMessage);
}
}
else
{
throw;
}
}
}
}
/// <summary>
/// Concrete implementation of target to source binding.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
protected virtual void DoBindTargetToSource(object source, object target, IDictionary variables)
{
object value = this.GetTargetValue(target, variables);
if (this.Formatter != null)
{
value = this.Formatter.Format(value);
}
this.SetSourceValue(source, value, variables);
}
#endregion
#region Abstract Methods
/// <summary>
/// Gets the source value for the binding.
/// </summary>
/// <param name="source">
/// Source object to extract value from.
/// </param>
/// <param name="variables">
/// Variables for expression evaluation.
/// </param>
/// <returns>
/// The source value for the binding.
/// </returns>
protected abstract object GetSourceValue(object source, IDictionary variables);
/// <summary>
/// Sets the source value for the binding.
/// </summary>
/// <param name="source">
/// The source object to set the value on.
/// </param>
/// <param name="value">
/// The value to set.
/// </param>
/// <param name="variables">
/// Variables for expression evaluation.
/// </param>
protected abstract void SetSourceValue(object source, object value, IDictionary variables);
/// <summary>
/// Gets the target value for the binding.
/// </summary>
/// <param name="target">
/// Source object to extract value from.
/// </param>
/// <param name="variables">
/// Variables for expression evaluation.
/// </param>
/// <returns>
/// The target value for the binding.
/// </returns>
protected abstract object GetTargetValue(object target, IDictionary variables);
/// <summary>
/// Sets the target value for the binding.
/// </summary>
/// <param name="target">
/// The target object to set the value on.
/// </param>
/// <param name="value">
/// The value to set.
/// </param>
/// <param name="variables">
/// Variables for expression evaluation.
/// </param>
protected abstract void SetTargetValue(object target, object value, IDictionary variables);
#endregion
}
using System;
using System.Collections;
using Spring.Globalization;
using Spring.Validation;
namespace Spring.DataBinding
{
/// <summary>
/// Abstract base class for simple, one-to-one <see cref="IBinding"/> implementations.
/// </summary>
/// <author>Aleksandar Seovic</author>
public abstract class AbstractSimpleBinding : AbstractBinding
{
#region Fields
private IFormatter formatter;
#endregion
#region Constructor(s)
/// <summary>
/// Initialize a new instance of <see cref="AbstractSimpleBinding"/> without any <see cref="IFormatter"/>
/// </summary>
protected AbstractSimpleBinding()
{
}
/// <summary>
/// Initialize a new instance of <see cref="AbstractSimpleBinding"/> with the
/// specified <see cref="IFormatter"/>.
/// </summary>
protected AbstractSimpleBinding(IFormatter formatter)
{
this.formatter = formatter;
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the <see cref="IFormatter"/> to use.
/// </summary>
/// <value>The formatter to use.</value>
public IFormatter Formatter
{
get { return formatter; }
set { formatter = value; }
}
#endregion
#region IBinding Implementation
/// <summary>
/// Binds source object to target object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public override void BindSourceToTarget(object source, object target, IValidationErrors validationErrors,
IDictionary variables)
{
if (this.IsValid(validationErrors)
&& (this.Direction == BindingDirection.Bidirectional || this.Direction == BindingDirection.SourceToTarget))
{
try
{
DoBindSourceToTarget(source, target, variables);
}
catch (Exception)
{
if (!SetInvalid(validationErrors)) throw;
}
}
}
/// <summary>
/// Concrete implementation if source to target binding.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
protected virtual void DoBindSourceToTarget(object source, object target, IDictionary variables)
{
object value = this.GetSourceValue(source, variables);
if (this.Formatter != null && value is string)
{
value = this.Formatter.Parse((string)value);
}
this.SetTargetValue(target, value, variables);
}
/// <summary>
/// Binds target object to source object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public override void BindTargetToSource(object source, object target, IValidationErrors validationErrors,
IDictionary variables)
{
if (this.IsValid(validationErrors)
&& (this.Direction == BindingDirection.Bidirectional || this.Direction == BindingDirection.TargetToSource))
{
try
{
DoBindTargetToSource(source, target, variables);
}
catch (Exception)
{
if (!SetInvalid(validationErrors)) throw;
}
}
}
/// <summary>
/// Concrete implementation of target to source binding.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
protected virtual void DoBindTargetToSource(object source, object target, IDictionary variables)
{
object value = this.GetTargetValue(target, variables);
if (this.Formatter != null)
{
value = this.Formatter.Format(value);
}
this.SetSourceValue(source, value, variables);
}
#endregion
#region Abstract Methods
/// <summary>
/// Gets the source value for the binding.
/// </summary>
/// <param name="source">
/// Source object to extract value from.
/// </param>
/// <param name="variables">
/// Variables for expression evaluation.
/// </param>
/// <returns>
/// The source value for the binding.
/// </returns>
protected abstract object GetSourceValue(object source, IDictionary variables);
/// <summary>
/// Sets the source value for the binding.
/// </summary>
/// <param name="source">
/// The source object to set the value on.
/// </param>
/// <param name="value">
/// The value to set.
/// </param>
/// <param name="variables">
/// Variables for expression evaluation.
/// </param>
protected abstract void SetSourceValue(object source, object value, IDictionary variables);
/// <summary>
/// Gets the target value for the binding.
/// </summary>
/// <param name="target">
/// Source object to extract value from.
/// </param>
/// <param name="variables">
/// Variables for expression evaluation.
/// </param>
/// <returns>
/// The target value for the binding.
/// </returns>
protected abstract object GetTargetValue(object target, IDictionary variables);
/// <summary>
/// Sets the target value for the binding.
/// </summary>
/// <param name="target">
/// The target object to set the value on.
/// </param>
/// <param name="value">
/// The value to set.
/// </param>
/// <param name="variables">
/// Variables for expression evaluation.
/// </param>
protected abstract void SetTargetValue(object target, object value, IDictionary variables);
#endregion
}
}

View File

@@ -1,261 +1,261 @@
using System.Collections;
using Spring.Globalization;
using Spring.Validation;
namespace Spring.DataBinding
{
/// <summary>
/// Base implementation of the <see cref="IBindingContainer"/>.
/// </summary>
/// <author>Aleksandar Seovic</author>
public class BaseBindingContainer : IBindingContainer
{
#region Fields
private IList bindings = new ArrayList();
#endregion
#region Constructor(s)
/// <summary>
/// Creates a new instance of <see cref="BaseBindingContainer"/>.
/// </summary>
public BaseBindingContainer()
{}
#endregion
#region Properties
/// <summary>
/// Gets a list of bindings for this container.
/// </summary>
/// <value>
/// A list of bindings for this container.
/// </value>
protected IList Bindings
{
get { return bindings; }
}
#endregion
#region IBindingContainer Implementation
/// <summary>
/// Gets a value indicating whether this instance has bindings.
/// </summary>
/// <value>
/// <c>true</c> if this instance has bindings; otherwise, <c>false</c>.
/// </value>
public bool HasBindings
{
get { return bindings.Count > 0; }
}
/// <summary>
/// Adds the binding.
/// </summary>
/// <param name="binding">
/// Binding definition to add.
/// </param>
/// <returns>
/// Added <see cref="IBinding"/> instance.
/// </returns>
public IBinding AddBinding(IBinding binding)
{
bindings.Add(binding);
return binding;
}
/// <summary>
/// Adds the <see cref="SimpleExpressionBinding"/> binding with a default
/// binding direction of <see cref="BindingDirection.Bidirectional"/>.
/// </summary>
/// <param name="sourceExpression">
/// The source expression.
/// </param>
/// <param name="targetExpression">
/// The target expression.
/// </param>
/// <returns>
/// Added <see cref="SimpleExpressionBinding"/> instance.
/// </returns>
public IBinding AddBinding(string sourceExpression, string targetExpression)
{
return AddBinding(sourceExpression, targetExpression, BindingDirection.Bidirectional, null);
}
/// <summary>
/// Adds the <see cref="SimpleExpressionBinding"/> binding.
/// </summary>
/// <param name="sourceExpression">
/// The source expression.
/// </param>
/// <param name="targetExpression">
/// The target expression.
/// </param>
/// <param name="direction">
/// Binding direction.
/// </param>
/// <returns>
/// Added <see cref="SimpleExpressionBinding"/> instance.
/// </returns>
public IBinding AddBinding(string sourceExpression, string targetExpression, BindingDirection direction)
{
return AddBinding(sourceExpression, targetExpression, direction, null);
}
/// <summary>
/// Adds the <see cref="SimpleExpressionBinding"/> binding with a default
/// binding direction of <see cref="BindingDirection.Bidirectional"/>.
/// </summary>
/// <param name="sourceExpression">
/// The source expression.
/// </param>
/// <param name="targetExpression">
/// The target expression.
/// </param>
/// <param name="formatter">
/// <see cref="IFormatter"/> to use for value formatting and parsing.
/// </param>
/// <returns>
/// Added <see cref="SimpleExpressionBinding"/> instance.
/// </returns>
public IBinding AddBinding(string sourceExpression, string targetExpression, IFormatter formatter)
{
return AddBinding(sourceExpression, targetExpression, BindingDirection.Bidirectional, formatter);
}
/// <summary>
/// Adds the <see cref="SimpleExpressionBinding"/> binding.
/// </summary>
/// <param name="sourceExpression">
/// The source expression.
/// </param>
/// <param name="targetExpression">
/// The target expression.
/// </param>
/// <param name="direction">
/// Binding direction.
/// </param>
/// <param name="formatter">
/// <see cref="IFormatter"/> to use for value formatting and parsing.
/// </param>
/// <returns>
/// Added <see cref="SimpleExpressionBinding"/> instance.
/// </returns>
public virtual IBinding AddBinding(string sourceExpression, string targetExpression,
BindingDirection direction, IFormatter formatter)
{
SimpleExpressionBinding binding = new SimpleExpressionBinding(sourceExpression, targetExpression);
binding.Direction = direction;
binding.Formatter = formatter;
bindings.Add(binding);
return binding;
}
#endregion
#region IBinding Implementation
/// <summary>
/// Binds source object to target object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
public void BindSourceToTarget(object source, object target, IValidationErrors validationErrors)
{
BindSourceToTarget(source, target, validationErrors, null);
}
/// <summary>
/// Binds source object to target object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public virtual void BindSourceToTarget(object source, object target, IValidationErrors validationErrors,
IDictionary variables)
{
foreach (IBinding binding in bindings)
{
binding.BindSourceToTarget(source, target, validationErrors);
}
}
/// <summary>
/// Binds target object to source object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
public void BindTargetToSource(object source, object target, IValidationErrors validationErrors)
{
BindTargetToSource(source, target, validationErrors, null);
}
/// <summary>
/// Binds target object to source object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public virtual void BindTargetToSource(object source, object target, IValidationErrors validationErrors,
IDictionary variables)
{
foreach (IBinding binding in bindings)
{
binding.BindTargetToSource(source, target, validationErrors);
}
}
/// <summary>
/// Sets error message that should be displayed in the case
/// of a non-fatal binding error.
/// </summary>
/// <param name="messageId">
/// Resource ID of the error message.
/// </param>
/// <param name="errorProviders">
/// List of error providers message should be added to.
/// </param>
public virtual void SetErrorMessage(string messageId, params string[] errorProviders)
{}
#endregion
}
using System.Collections;
using Spring.Globalization;
using Spring.Validation;
namespace Spring.DataBinding
{
/// <summary>
/// Base implementation of the <see cref="IBindingContainer"/>.
/// </summary>
/// <author>Aleksandar Seovic</author>
public class BaseBindingContainer : IBindingContainer
{
#region Fields
private IList bindings = new ArrayList();
#endregion
#region Constructor(s)
/// <summary>
/// Creates a new instance of <see cref="BaseBindingContainer"/>.
/// </summary>
public BaseBindingContainer()
{ }
#endregion
#region Properties
/// <summary>
/// Gets a list of bindings for this container.
/// </summary>
/// <value>
/// A list of bindings for this container.
/// </value>
protected IList Bindings
{
get { return bindings; }
}
#endregion
#region IBindingContainer Implementation
/// <summary>
/// Gets a value indicating whether this instance has bindings.
/// </summary>
/// <value>
/// <c>true</c> if this instance has bindings; otherwise, <c>false</c>.
/// </value>
public bool HasBindings
{
get { return bindings.Count > 0; }
}
/// <summary>
/// Adds the binding.
/// </summary>
/// <param name="binding">
/// Binding definition to add.
/// </param>
/// <returns>
/// Added <see cref="IBinding"/> instance.
/// </returns>
public IBinding AddBinding(IBinding binding)
{
bindings.Add(binding);
return binding;
}
/// <summary>
/// Adds the <see cref="SimpleExpressionBinding"/> binding with a default
/// binding direction of <see cref="BindingDirection.Bidirectional"/>.
/// </summary>
/// <param name="sourceExpression">
/// The source expression.
/// </param>
/// <param name="targetExpression">
/// The target expression.
/// </param>
/// <returns>
/// Added <see cref="SimpleExpressionBinding"/> instance.
/// </returns>
public IBinding AddBinding(string sourceExpression, string targetExpression)
{
return AddBinding(sourceExpression, targetExpression, BindingDirection.Bidirectional, null);
}
/// <summary>
/// Adds the <see cref="SimpleExpressionBinding"/> binding.
/// </summary>
/// <param name="sourceExpression">
/// The source expression.
/// </param>
/// <param name="targetExpression">
/// The target expression.
/// </param>
/// <param name="direction">
/// Binding direction.
/// </param>
/// <returns>
/// Added <see cref="SimpleExpressionBinding"/> instance.
/// </returns>
public IBinding AddBinding(string sourceExpression, string targetExpression, BindingDirection direction)
{
return AddBinding(sourceExpression, targetExpression, direction, null);
}
/// <summary>
/// Adds the <see cref="SimpleExpressionBinding"/> binding with a default
/// binding direction of <see cref="BindingDirection.Bidirectional"/>.
/// </summary>
/// <param name="sourceExpression">
/// The source expression.
/// </param>
/// <param name="targetExpression">
/// The target expression.
/// </param>
/// <param name="formatter">
/// <see cref="IFormatter"/> to use for value formatting and parsing.
/// </param>
/// <returns>
/// Added <see cref="SimpleExpressionBinding"/> instance.
/// </returns>
public IBinding AddBinding(string sourceExpression, string targetExpression, IFormatter formatter)
{
return AddBinding(sourceExpression, targetExpression, BindingDirection.Bidirectional, formatter);
}
/// <summary>
/// Adds the <see cref="SimpleExpressionBinding"/> binding.
/// </summary>
/// <param name="sourceExpression">
/// The source expression.
/// </param>
/// <param name="targetExpression">
/// The target expression.
/// </param>
/// <param name="direction">
/// Binding direction.
/// </param>
/// <param name="formatter">
/// <see cref="IFormatter"/> to use for value formatting and parsing.
/// </param>
/// <returns>
/// Added <see cref="SimpleExpressionBinding"/> instance.
/// </returns>
public virtual IBinding AddBinding(string sourceExpression, string targetExpression,
BindingDirection direction, IFormatter formatter)
{
SimpleExpressionBinding binding = new SimpleExpressionBinding(sourceExpression, targetExpression);
binding.Direction = direction;
binding.Formatter = formatter;
bindings.Add(binding);
return binding;
}
#endregion
#region IBinding Implementation
/// <summary>
/// Binds source object to target object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
public virtual void BindSourceToTarget(object source, object target, IValidationErrors validationErrors)
{
BindSourceToTarget(source, target, validationErrors, null);
}
/// <summary>
/// Binds source object to target object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public virtual void BindSourceToTarget(object source, object target, IValidationErrors validationErrors,
IDictionary variables)
{
foreach (IBinding binding in bindings)
{
binding.BindSourceToTarget(source, target, validationErrors);
}
}
/// <summary>
/// Binds target object to source object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
public virtual void BindTargetToSource(object source, object target, IValidationErrors validationErrors)
{
BindTargetToSource(source, target, validationErrors, null);
}
/// <summary>
/// Binds target object to source object.
/// </summary>
/// <param name="source">
/// The source object.
/// </param>
/// <param name="target">
/// The target object.
/// </param>
/// <param name="validationErrors">
/// Validation errors collection that type conversion errors should be added to.
/// </param>
/// <param name="variables">
/// Variables that should be used during expression evaluation.
/// </param>
public virtual void BindTargetToSource(object source, object target, IValidationErrors validationErrors,
IDictionary variables)
{
foreach (IBinding binding in bindings)
{
binding.BindTargetToSource(source, target, validationErrors);
}
}
/// <summary>
/// Implemented as a NOOP for containers.
/// of a non-fatal binding error.
/// </summary>
/// <param name="messageId">
/// Resource ID of the error message.
/// </param>
/// <param name="errorProviders">
/// List of error providers message should be added to.
/// </param>
public virtual void SetErrorMessage(string messageId, params string[] errorProviders)
{ }
#endregion
}
}

View File

@@ -0,0 +1,112 @@
#region License
/*
* Copyright <20> 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 Spring.Util;
using Spring.Validation;
#endregion
namespace Spring.DataBinding
{
/// <summary>
/// Represents an ErrorMessage specific to a binding instance.
/// </summary>
/// <author>Erich Eichinger</author>
[Serializable]
public class BindingErrorMessage : ErrorMessage
{
private string _bindingId;
/// <summary>
/// Initializes a new instance of the <see cref="ErrorMessage"/> class.
/// </summary>
/// <param name="bindingId">the id of the binding this error message is associated with</param>
/// <param name="id">the message id</param>
/// <param name="parameters">optional parameters to this message</param>
public BindingErrorMessage(string bindingId, string id, params object[] parameters) : base(id, parameters)
{
AssertUtils.ArgumentNotNull(bindingId, "bindingId");
_bindingId = bindingId;
}
/// <summary>
/// Get the ID of the binding this message instance relates to.
/// </summary>
public string BindingId
{
get { return _bindingId; }
}
/// <summary>
/// Generates an object from its XML representation.
/// </summary>
/// <param name="reader">
/// The <see cref="T:System.Xml.XmlReader"></see> stream
/// from which the object is deserialized.
/// </param>
public override void ReadXml(System.Xml.XmlReader reader)
{
base.ReadXml(reader);
_bindingId = reader.GetAttribute("bindingId");
}
/// <summary>
/// Converts an object into its XML representation.
/// </summary>
/// <param name="writer">
/// The <see cref="T:System.Xml.XmlWriter"></see> stream
/// to which the object is serialized.
/// </param>
public override void WriteXml(System.Xml.XmlWriter writer)
{
base.WriteXml(writer);
writer.WriteAttributeString("bindingId", _bindingId);
}
///<summary>
///Determines whether the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>.
///</summary>
///<returns>
///true if the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>; otherwise, false.
///</returns>
///<param name="obj">The <see cref="T:System.Object"></see> to compare with the current <see cref="T:System.Object"></see>. </param><filterpriority>2</filterpriority>
public override bool Equals(object obj)
{
BindingErrorMessage other = obj as BindingErrorMessage;
return (other != null)
&& (this.BindingId == other.BindingId)
&& (base.Equals(obj));
}
///<summary>
///Serves as a hash function for a particular type. <see cref="M:System.Object.GetHashCode"></see> is suitable for use in hashing algorithms and data structures like a hash table.
///</summary>
///<returns>
///A hash code for the current <see cref="T:System.Object"></see>.
///</returns>
public override int GetHashCode()
{
return base.GetHashCode() + 31*this.BindingId.GetHashCode();
}
}
}

View File

@@ -787,6 +787,11 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "DataBinding\BindingErrorMessage.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "DataBinding\IBinding.cs"
SubType = "Code"
@@ -2024,6 +2029,15 @@
RelPath = "Objects\Factory\Xml\spring-objects-1.1.xsd"
BuildAction = "EmbeddedResource"
/>
<File
RelPath = "Objects\Factory\Xml\spring-objects-1.1.xsx"
DependentUpon = "spring-objects-1.1.xsd"
BuildAction = "None"
/>
<File
RelPath = "Objects\Factory\Xml\spring-objects-1.2.xsd"
BuildAction = "Content"
/>
<File
RelPath = "Objects\Factory\Xml\spring-tool-1.1.xsd"
BuildAction = "EmbeddedResource"

View File

@@ -333,6 +333,7 @@
<Compile Include="DataBinding\AbstractBinding.cs" />
<Compile Include="DataBinding\AbstractSimpleBinding.cs" />
<Compile Include="DataBinding\BaseBindingContainer.cs" />
<Compile Include="DataBinding\BindingErrorMessage.cs" />
<Compile Include="DataBinding\IBindingContainer.cs" />
<Compile Include="DataBinding\ListBinding.cs" />
<Compile Include="DataBinding\SimpleExpressionBinding.cs" />

View File

@@ -1,7 +1,7 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>9.0.21022</ProductVersion>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -349,6 +349,7 @@
<Compile Include="DataBinding\AbstractBinding.cs" />
<Compile Include="DataBinding\AbstractSimpleBinding.cs" />
<Compile Include="DataBinding\BaseBindingContainer.cs" />
<Compile Include="DataBinding\BindingErrorMessage.cs" />
<Compile Include="DataBinding\IBindingContainer.cs" />
<Compile Include="DataBinding\ListBinding.cs" />
<Compile Include="DataBinding\SimpleExpressionBinding.cs" />

View File

@@ -57,6 +57,16 @@ namespace Spring.Validation
this.parameters = parameters;
}
/// <summary>
/// Initializes a new instance of the <see cref="ErrorMessage"/> class copying values from another instance.
/// </summary>
/// <param name="other">Another Error message instance to copy values from.</param>
protected ErrorMessage(ErrorMessage other)
{
this.id = other.id;
this.parameters = other.parameters;
}
#endregion
#region Properties
@@ -110,7 +120,7 @@ namespace Spring.Validation
/// The <see cref="T:System.Xml.XmlReader"></see> stream
/// from which the object is deserialized.
/// </param>
public void ReadXml(XmlReader reader)
public virtual void ReadXml(XmlReader reader)
{
id = reader.GetAttribute("Id");
if (!reader.IsEmptyElement)
@@ -131,9 +141,9 @@ namespace Spring.Validation
/// The <see cref="T:System.Xml.XmlWriter"></see> stream
/// to which the object is serialized.
/// </param>
public void WriteXml(XmlWriter writer)
public virtual void WriteXml(XmlWriter writer)
{
writer.WriteAttributeString("Id", id.ToString());
writer.WriteAttributeString("Id", id);
if (parameters != null)
{
@@ -168,7 +178,32 @@ namespace Spring.Validation
}
#endregion
///<summary>
///Determines whether the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>.
///</summary>
///<returns>
///true if the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>; otherwise, false.
///</returns>
///<param name="obj">The <see cref="T:System.Object"></see> to compare with the current <see cref="T:System.Object"></see>. </param><filterpriority>2</filterpriority>
public override bool Equals(object obj)
{
ErrorMessage other = obj as ErrorMessage;
return (other != null)
&& (this.id == other.Id);
}
///<summary>
///Serves as a hash function for a particular type. <see cref="M:System.Object.GetHashCode"></see> is suitable for use in hashing algorithms and data structures like a hash table.
///</summary>
///<returns>
///A hash code for the current <see cref="T:System.Object"></see>.
///</returns>
public override int GetHashCode()
{
return id.GetHashCode();
}
#region Data members
private string id;

View File

@@ -187,9 +187,9 @@ namespace Spring.DataBinding
catch (TypeMismatchException)
{}
// make sure that the old value doesn't override current invalid value
// binding state is not remembered with ValidationErrors=null!
dbm.BindTargetToSource(source, target, null);
Assert.AreEqual(false, source["boolValue"]);
Assert.AreEqual(target.DOB, source["boolValue"]);
}
[Test]
@@ -209,9 +209,14 @@ namespace Spring.DataBinding
catch (TypeMismatchException)
{}
// make sure that the old value doesn't override current invalid value
dbm.BindSourceToTarget(st, st, null);
Assert.AreEqual(new DateTime(1856, 7, 9), st.DOB);
// binding state is not remembered with ValidationErrors=null!
try
{
dbm.BindSourceToTarget(st, st, null);
Assert.Fail("Binding custom Place to date type should throw an exception.");
}
catch (TypeMismatchException)
{}
}
[Test]
@@ -228,7 +233,7 @@ namespace Spring.DataBinding
dbm.AddBinding(binding);
dbm.BindSourceToTarget(source, target, errors);
Assert.IsFalse(binding.IsValid);
Assert.IsFalse(binding.IsValid(errors));
Assert.IsFalse(errors.IsEmpty);
Assert.AreEqual(1, errors.GetErrors("errors").Count);
@@ -250,7 +255,7 @@ namespace Spring.DataBinding
dbm.AddBinding(binding);
dbm.BindTargetToSource(st, st, errors);
Assert.IsFalse(binding.IsValid);
Assert.IsFalse(binding.IsValid(errors));
Assert.IsFalse(errors.IsEmpty);
Assert.AreEqual(1, errors.GetErrors("errors").Count);

View File

@@ -1,118 +0,0 @@
#region License
/*
* Copyright <20> 2002-2007 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.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using Spring.Util;
#endregion
namespace Spring.Web.UI.Controls
{
/// <summary>
/// This control allows for suppressing output of the 'action' attribute.
/// </summary>
/// <remarks>
/// the 'action' attribute rendered by the default <see cref="HtmlForm"/> control causes troubles
/// in case of URL-rewriting. See e.g. <a href="http://www.thescripts.com/forum/thread408777.html">'thescripts.com' forum</a>
/// and also <a href="http://opensource.atlassian.com/projects/spring/browse/SPRNET-560">JIRA SPRNET-560</a> for more info.
/// </remarks>
/// <author>Erich Eichinger</author>
/// <version>$Id: ValidationErrorTests.cs,v 1.1 2008/03/19 12:07:15 oakinger Exp $</version>
public class ValidationErrorTests : HtmlForm
{
private bool suppressAction = false;
private string action = null;
/// <summary>
/// Sets or Gets a value indicating if the 'action' attribute shall be rendered. Defaults to 'false'
/// </summary>
/// <remarks>
/// The following possibilites are available:
/// <list>
/// <item>If <see cref="SuppressAction"/> is 'true', rendering of the 'action' attribute is suppressed.</item>
/// <item>If <see cref="SuppressAction"/> is 'false' and <see cref="Action"/> is not set,
/// 'action' attribute will.be rendered to <see cref="HttpRequest.RawUrl"/>
/// </item>
/// <item>If <see cref="SuppressAction"/> is 'false' and <see cref="Action"/> is set,
/// 'action' attribute will.be rendered to <see cref="Action"/>
/// </item>
/// </list>
/// </remarks>
public bool SuppressAction
{
get { return this.suppressAction; }
set { this.suppressAction = value; }
}
/// <summary>
/// Sets or Gets an explicit url to be rendered
/// </summary>
/// <remarks>
/// The url specified here is only rendered, if <see cref="SuppressAction"/> is true.
/// </remarks>
public string Action
{
get { return this.action; }
set { this.action = value; }
}
/// <summary>
/// Renders attributes but performs 'action' suppressing logic.
/// </summary>
/// <param name="writer"></param>
protected override void RenderAttributes(HtmlTextWriter writer)
{
base.RenderAttributes(new ActionSupressingHtmlTextWriter(writer));
if (!this.suppressAction)
{
string url = (StringUtils.HasText(this.action)) ? this.action : Context.Request.RawUrl;
writer.WriteAttribute("action", url, true);
}
}
#region Nested type: ActionSupressingHtmlTextWriter
/// <summary>
/// This wrapper suppresses output of 'action' attributes.
/// </summary>
private class ActionSupressingHtmlTextWriter : HtmlTextWriter
{
public ActionSupressingHtmlTextWriter(HtmlTextWriter wrappedWriter)
: base(wrappedWriter.InnerWriter)
{
}
public override void WriteAttribute(string name, string value, bool fEncode)
{
if (string.Compare(name, "action", true) != 0)
{
base.WriteAttribute(name, value, fEncode);
}
}
}
#endregion
}
}