fixed SPRNET-1118, updated refdocs

This commit is contained in:
eeichinger
2009-04-17 13:32:28 +00:00
parent fb0cb23a7f
commit 7f4315bde3
6 changed files with 259 additions and 152 deletions

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE book [
<!ENTITY aop SYSTEM "aop.xml">
<!ENTITY aop-aspect-library SYSTEM "aop-aspect-library.xml">
@@ -53,16 +53,16 @@
<!ENTITY xml-custom SYSTEM "xml-custom.xml">
<!ENTITY xsd SYSTEM "xsd.xml">
]>
<book xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://docbook.org/ns/docbook/xi"
version="5.0"
<book xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://docbook.org/ns/docbook/xi"
version="5.0"
xml:lang="en">
<info>
<title>The Spring.NET Framework</title>
<subtitle>Reference Documentation</subtitle>
<releaseinfo>Version 1.2.0</releaseinfo>
<pubdate>Last Updated Novermber 10, 2008 <ulink url="http://www.springframework.net/doc-latest/reference/html/index.html">(Latest documentation)</ulink></pubdate>
<releaseinfo>Version 1.2.1</releaseinfo>
<pubdate>Last Updated April xx, 2009 <ulink url="http://www.springframework.net/doc-latest/reference/html/index.html">(Latest documentation)</ulink></pubdate>
<authorgroup>
<author>
<firstname>Mark</firstname>
@@ -80,6 +80,10 @@
<firstname>Bruno</firstname>
<surname>Baia</surname>
</author>
<author>
<firstname>Erich</firstname>
<surname>Eichinger</surname>
</author>
<author>
<firstname>Federico</firstname>
<surname>Spinazzi</surname>

View File

@@ -692,7 +692,17 @@ bool userInfoIsValid = userInfoValidator.Validate(userInfo, errors);
&lt;/object&gt;
&lt;v:group id="tripValidator"&gt;
// our validation rules
&lt;v:required id="departureAirportValidator" test="StartingFrom.AirportCode"&gt;
&lt;!-- write error message to 2 providers --&gt;
&lt;v:message id="error.departureAirport.required" providers="departureAirportErrors, errorSummary"/&gt;
&lt;/v:required&gt;
&lt;v:group id="destinationAirportValidator"&gt;
&lt;v:required test="ReturningFrom.AirportCode"&gt;
&lt;!-- write error message to 2 providers --&gt;
&lt;v:message id="error.destinationAirport.required" providers="destinationAirportErrors, errorSummary"/&gt;
&lt;/v:required&gt;
&lt;/v:group&gt;
&lt;/v:group&gt;
&lt;/objects&gt;</programlisting>
@@ -719,83 +729,30 @@ bool userInfoIsValid = userInfoValidator.Validate(userInfo, errors);
<literal>&lt;spring:validationSummary/&gt;</literal> controls to the
ASP.NET form:</para>
<programlisting language="myxml">&lt;%@ Page Language="c#" MasterPageFile="~/Web/StandardTemplate.master" Inherits="TripForm" CodeFile="TripForm.aspx.cs" %&gt;
&lt;%@ Register TagPrefix="spring" Namespace="Spring.Web.UI.Controls" Assembly="Spring.Web" %&gt;
&lt;asp:Content ID="head" ContentPlaceHolderID="head" runat="server"&gt;
&lt;script language="javascript" type="text/javascript"&gt;
&lt;!--
function showReturnCalendar(isVisible)
{
document.getElementById('&lt;%= returningOnDate.ClientID %&gt;').style.visibility = isVisible? '': 'hidden';
document.getElementById('returningOnCalendar').style.visibility = isVisible? '': 'hidden';
}
--&gt;
&lt;/script&gt;
&lt;/asp:Content&gt;
&lt;asp:Content ID="body" ContentPlaceHolderID="body" runat="server"&gt;
&lt;div style="text-align: center"&gt;
&lt;h4&gt;&lt;asp:Label ID="caption" runat="server"&gt;&lt;/asp:Label&gt;&lt;/h4&gt;
&lt;spring:ValidationSummary ID="validationSummary" runat="server" /&gt;
<programlisting language="myxml">&lt;!-- code snippet taken from the SpringAir sample application --&gt;
&lt;%@ Page Language="c#" MasterPageFile="~/Web/StandardTemplate.master" Inherits="TripForm" CodeFile="TripForm.aspx.cs" %&gt;
&lt;!-- render all error messages sent to 'errorSummary' provider --&gt;
&lt;spring:ValidationSummary ID="summary" Provider="errorSummary" runat="server" /&gt;
&lt;table&gt;
&lt;tr class="formLabel"&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td colspan="3"&gt;
&lt;spring:RadioButtonGroup ID="tripMode" runat="server"&gt;
&lt;asp:RadioButton ID="OneWay" onclick="showReturnCalendar(false);" runat="server" /&gt;
&lt;asp:RadioButton ID="RoundTrip" onclick="showReturnCalendar(true);" runat="server" /&gt;
&lt;/spring:RadioButtonGroup&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="formLabel" align="right"&gt;
&lt;td&gt;
&lt;asp:Label ID="leavingFrom" runat="server" /&gt;&lt;/td&gt;
&lt;td nowrap="nowrap"&gt;
&lt;td&gt;
&lt;asp:DropDownList ID="leavingFromAirportCode" AutoCallBack="true" runat="server" /&gt;
&lt;spring:ValidationError id="departureAirportErrors" runat="server" /&gt;
&lt;!-- render error messages sent to 'departureAirportErrors' provider --&gt;
&lt;spring:ValidationError ID="leavingFromError" Provider="departureAirportErrors" runat="server" /&gt;
&lt;/td&gt;
&lt;td class="formLabel" align="right"&gt;
&lt;td&gt;
&lt;asp:Label ID="goingTo" runat="server" /&gt;&lt;/td&gt;
&lt;td nowrap="nowrap"&gt;
&lt;td&gt;
&lt;asp:DropDownList ID="goingToAirportCode" AutoCallBack="true" runat="server" /&gt;
&lt;spring:ValidationError id="destinationAirportErrors" runat="server" /&gt;
&lt;!-- render error messages sent to 'destinationAirportErrors' provider --&gt;
&lt;spring:ValidationError ID="goingToError" Provider="destinationAirportErrors" runat="server" /&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="formLabel" align="right"&gt;
&lt;asp:Label ID="leavingOn" runat="server" /&gt;&lt;/td&gt;
&lt;td nowrap="nowrap"&gt;
&lt;spring:Calendar ID="leavingFromDate" runat="server" Width="75px" AllowEditing="true" Skin="system" /&gt;
&lt;spring:ValidationError id="departureDateErrors" runat="server" /&gt;
&lt;/td&gt;
&lt;td class="formLabel" align="right"&gt;
&lt;asp:Label ID="returningOn" runat="server" /&gt;&lt;/td&gt;
&lt;td nowrap="nowrap"&gt;
&lt;div id="returningOnCalendar"&gt;
&lt;spring:Calendar ID="returningOnDate" runat="server" Width="75px" AllowEditing="true" Skin="system" /&gt;
&lt;spring:ValidationError id="returnDateErrors" runat="server" /&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class="buttonBar" colspan="4"&gt;
&lt;br/&gt;
&lt;asp:Button ID="findFlights" runat="server"/&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;script language="javascript" type="text/javascript"&gt;
if (document.getElementById('&lt;%= tripMode.ClientID %&gt;').value == 'OneWay')
showReturnCalendar(false);
else
showReturnCalendar(true);
&lt;/script&gt;
&lt;/asp:Content&gt;</programlisting>
</programlisting>
<section>
<title>Rendering Validation Errors</title>
@@ -927,5 +884,50 @@ bool userInfoIsValid = userInfoValidator.Validate(userInfo, errors);
<para>It's as simple as that!</para>
</section>
</section>
<section>
<title>How Validate() and Validation Controls play together</title>
<para> Validation Controls (ValidationSummary, ValidationError) need to
somehow get the list of errors collected during validation. Both,
Spring.Web.UI.Page and Spring.Web.UI.UserControl come with a
ValidationErrors property and implement IValidationContainer.
ValidationControls will automatically pick the IValidationContainer
control they are placed on:</para>
<para><programlisting language="myxml">// ASPX / ASCX Template Code
&lt;%@ Control Language="c#"%&gt;
&lt;!-- render all error messages sent to 'errorSummary' provider --&gt;
&lt;spring:ValidationSummary ID="summary" Provider="errorSummary" runat="server" /&gt;
&lt;asp:DropDownList ID="leavingFromAirportCode" AutoCallBack="true" runat="server" /&gt;
&lt;!-- render error messages sent to 'departureAirportErrors' provider --&gt;
&lt;spring:ValidationError ID="leavingFromError" Provider="departureAirportErrors" runat="server" /&gt;
&lt;script language="C#" runat="server"&gt;
public void SearchForFlights(object sender, EventArgs e)
{
if (Validate(Controller.Trip, tripValidator))
{
Process.SetView(Controller.SearchForFlights());
}
}
&lt;/script&gt;
</programlisting>If you need to render errors from a UserControl not in the
hierarchy of your Validation control, you can specify the name of the
target validation container control:</para>
<para><programlisting language="myxml">// ASPX / ASCX Template Code
&lt;%@ Page Language="c#" %&gt;
&lt;%@ Register TagPrefix="user" TagName="EmployeeInfoEditor" Src="EmployeeInfoEditor.ascx" %&gt;
&lt;spring:ValidationSummary ID="summary" Provider="summary" ValidationContainerName="editor" runat="server" /&gt;
&lt;user:EmployeeInfoEditor ID="editor" runat="server" /&gt;
</programlisting></para>
</section>
</section>
</chapter>

View File

@@ -18,20 +18,14 @@
#endregion
#region Imports
using System;
using System.Collections;
using System.Diagnostics;
using System.Web.UI;
using System.Web.UI.WebControls;
using Spring.Context;
using Spring.Util;
using Spring.Validation;
using Spring.Web.UI.Validation;
#endregion
namespace Spring.Web.UI.Controls
{
/// <summary>
@@ -40,9 +34,11 @@ namespace Spring.Web.UI.Controls
/// <author>Erich Eichinger</author>
public abstract class AbstractValidationControl : Control
{
private string provider;
private string validationContainerName;
private string _provider;
private string _validationContainerName;
private IValidationErrorsRenderer renderer;
private IValidationErrors _validationErrors;
private IMessageSource _messageSource;
#if !NET_2_0
private bool initialized;
@@ -70,21 +66,51 @@ namespace Spring.Web.UI.Controls
{
return this.Site.DesignMode;
}
return (this.Context == null) && initialized;
return initialized && (this.Context == null);
}
}
#endif
/// <summary>
/// If set, <see cref="ValidationContainer"/> will resolve to the named control specified
/// Set a particular message source to be used for
/// resolving error messages to display texts.
/// </summary>
/// <remarks>
/// If not set, the control will probe the control hierarchy
/// for containing controls implementing <see cref="IValidationContainer"/>
/// and use the container's <see cref="IValidationContainer.MessageSource"/>.
/// </remarks>
public IMessageSource MessageSource
{
get { return _messageSource; }
set { _messageSource = value; }
}
/// <summary>
/// Allows to set a particular instance of the validation errors
/// collection to render.
/// </summary>
/// <remarks>
/// If not set, the control will probe the control hierarchy for
/// containing controls implementing <see cref="IValidationContainer"/>
/// and use the container's <see cref="IValidationContainer.ValidationErrors"/>
/// </remarks>
public IValidationErrors ValidationErrors
{
get { return _validationErrors; }
set { _validationErrors = value; }
}
/// <summary>
/// If set, <see cref="FindValidationContainer"/> will resolve to the named control specified
/// by this property. The behavior of name resolution is identical to
/// <see cref="System.Web.UI.WebControls.BaseValidator.ControlToValidate"/>, except that if the name
/// starts with "::", the resolution will start at the page level instead of relative to this
/// control
/// </summary>
public virtual string ValidationContainerName
public string ValidationContainerName
{
get { return validationContainerName; }
set { validationContainerName = value; }
get { return _validationContainerName; }
set { _validationContainerName = value; }
}
/// <summary>
@@ -95,20 +121,20 @@ namespace Spring.Web.UI.Controls
{
get
{
if (this.provider == null)
if (this._provider == null)
{
this.provider = this.ID;
if (this.provider == null)
this._provider = this.ID;
if (this._provider == null)
{
this.provider = string.Empty;
this._provider = string.Empty;
}
}
return this.provider;
return this._provider;
}
set
{
AssertUtils.ArgumentNotNull(value, "Provider");
this.provider = value;
this._provider = value;
}
}
@@ -137,17 +163,6 @@ namespace Spring.Web.UI.Controls
}
}
/// <summary>
/// Gets the MessageSource to be used for resolve error messages
/// </summary>
/// <remarks>
/// By default, returns <see cref="ValidationContainer"/>'s MessageSource.
/// </remarks>
protected virtual IMessageSource MessageSource
{
get { return ValidationContainer == null ? null : ValidationContainer.MessageSource; }
}
/// <summary>
/// Create the default <see cref="IValidationErrorsRenderer"/>
/// for this ValidationControl if none is configured.
@@ -155,49 +170,109 @@ namespace Spring.Web.UI.Controls
protected abstract IValidationErrorsRenderer CreateValidationErrorsRenderer();
/// <summary>
/// Gets the <see cref="IValidationContainer"/>, who's <see cref="IValidationContainer.ValidationErrors"/>
/// shall be rendered by this control.
/// Gets the MessageSource to be used for resolve error messages
/// </summary>
protected virtual IValidationContainer ValidationContainer
/// <remarks>
/// By default, returns <see cref="FindValidationContainer"/>'s MessageSource.
/// </remarks>
/// <returns>the <see cref="IMessageSource"/> to resolve message texts. May be <c>null</c></returns>
protected virtual IMessageSource ResolveMessageSource()
{
get
IMessageSource messageSource = this.MessageSource;
if (messageSource == null)
{
// is an explicit container specified?
if (ValidationContainerName != null)
{
Control start = this.NamingContainer;
string containerName = this.ValidationContainerName;
// shall we do a global search?
if (containerName.StartsWith("::"))
{
containerName = containerName.Substring(2);
start = this.Page;
}
IValidationContainer container = start.FindControl(containerName) as IValidationContainer;
if (container == null)
{
throw new ArgumentException(string.Format("Validation Container Control specified by {0} does not exist or does not implement IValidationContainer", this.ValidationContainerName));
}
return container;
}
for (Control parent = this.Parent; parent != null; parent = parent.Parent)
{
IValidationContainer container = parent as IValidationContainer;
if (container != null
&& container.ValidationErrors != null)
{
return container;
}
}
return null;
IValidationContainer validationContainer = FindValidationContainer();
messageSource = (validationContainer == null)
? null
: validationContainer.MessageSource;
}
return messageSource;
}
/// <summary>
/// Resolves the <see cref="ValidationContainer"/>'s list of validation errors to a list
/// Gets the list of validation errors to render
/// </summary>
/// <returns>the <see cref="IValidationErrors"/> to render. May be <c>null</c></returns>
protected virtual IValidationErrors ResolveValidationErrors()
{
IValidationErrors validationErrors = this.ValidationErrors;
if (validationErrors == null)
{
IValidationContainer container = this.FindValidationContainer();
if (container != null)
{
validationErrors = container.ValidationErrors;
}
}
return validationErrors;
}
/// <summary>
/// Gets the <see cref="IValidationContainer"/>, who's <see cref="IValidationContainer.ValidationErrors"/>
/// shall be rendered by this control.
/// </summary>
/// <remarks>
/// First, it tries to resolve the specified <see cref="ValidationContainerName"/>, if any. If no explicit name
/// is set, will probe the control hierarchy for controls implementing <see cref="IValidationContainer"/>.
/// </remarks>
protected virtual IValidationContainer FindValidationContainer()
{
// is an explicit container specified?
if (ValidationContainerName != null && ValidationContainerName.Length > 0)
{
Control start = this.NamingContainer;
string containerName = this.ValidationContainerName;
// shall we do a global search?
if (containerName.StartsWith("::"))
{
containerName = containerName.Substring(2);
start = this.Page;
}
IValidationContainer container = start as IValidationContainer;
if (containerName.Length > 0)
{
container = start.FindControl(containerName) as IValidationContainer;
}
if (container == null)
{
throw new ArgumentException(
string.Format(
"Validation Container Control specified by {0} does not exist or does not implement IValidationContainer",
this.ValidationContainerName));
}
return container;
}
for (Control parent = this.Parent; parent != null; parent = parent.Parent)
{
IValidationContainer container = parent as IValidationContainer;
if (container != null
&& container.ValidationErrors != null)
{
return container;
}
}
return null;
}
/// <summary>
/// Resolves the list of validation errors either explicitely specified using
/// <see cref="ValidationErrors"/> or obtained from the containing <see cref="IValidationContainer"/>
/// resolved by <see cref="FindValidationContainer"/> to a list
/// of <see cref="string"/> elements containing the error messages to be rendered.
/// </summary>
/// <remarks>
/// <para>
/// The list of validation errors may either be explicitely specified using <see cref="ValidationErrors"/>
/// or will automatically be obtained from the containing <see cref="IValidationContainer"/> resolved by
/// <see cref="FindValidationContainer"/>.
/// </para>
/// <para>
/// Error Messages are resolved using either an explicitely specified <see cref="MessageSource"/> or the
/// <see cref="IMessageSource"/> obtained from the validation container.
/// </para>
/// </remarks>
/// <returns>a list containing <see cref="string"/> elements. May return <c>null</c></returns>
protected virtual IList ResolveErrorMessages()
{
@@ -210,19 +285,14 @@ namespace Spring.Web.UI.Controls
return errorMessages;
}
IValidationContainer container = this.ValidationContainer;
if (container == null)
{
return null;
}
IValidationErrors validationErrors = container.ValidationErrors;
IValidationErrors validationErrors = ResolveValidationErrors();
if (validationErrors == null)
{
return null;
}
IMessageSource messageSource = this.ResolveMessageSource();
errorMessages = validationErrors.GetResolvedErrors(this.Provider, this.MessageSource);
errorMessages = validationErrors.GetResolvedErrors(this.Provider, messageSource);
return errorMessages;
}

View File

@@ -1263,12 +1263,17 @@ namespace Spring.Web.UI
}
/// <summary>
/// Gets the validation errors container.
/// Gets or sets the validation errors container.
/// </summary>
/// <value>The validation errors container.</value>
public virtual IValidationErrors ValidationErrors
{
get { return validationErrors; }
set
{
AssertUtils.ArgumentNotNull(value, "ValidationErrors");
validationErrors = value;
}
}
/// <summary>

View File

@@ -683,12 +683,17 @@ namespace Spring.Web.UI
}
/// <summary>
/// Gets the validation errors container.
/// Gets or sets the validation errors container.
/// </summary>
/// <value>The validation errors container.</value>
public virtual IValidationErrors ValidationErrors
{
get { return validationErrors; }
set
{
AssertUtils.ArgumentNotNull(value, "ValidationErrors");
validationErrors = value;
}
}
/// <summary>

View File

@@ -63,7 +63,7 @@ namespace Spring.Web.UI.Controls
}
[Test]
public void ResolvesAndRendersValidationErrors()
public void ResolvesAndRendersValidationErrorsUsingValidationContainer()
{
TestValidationControl vc = new TestValidationControl();
vc.ID = "TestControl";
@@ -79,6 +79,27 @@ namespace Spring.Web.UI.Controls
Assert.AreEqual("Resolved Message Text", vc.LastErrorsRendered[0]);
}
[Test]
public void ResolvesAndRendersValidationErrorsUsingExplicitlySpecifiedErrorsAndMessageSource()
{
TestValidationControl vc = new TestValidationControl();
vc.ID = "TestControl";
Page page = new Page();
page.Controls.Add(vc);
ValidationErrors errors = new ValidationErrors();
errors.AddError(vc.Provider, new ErrorMessage("msgId"));
vc.ValidationErrors = errors;
StaticMessageSource msgSrc = new StaticMessageSource();
msgSrc.AddMessage("msgId", CultureInfo.CurrentUICulture, "Resolved Message Text");
vc.MessageSource = msgSrc;
vc.TestRender(null);
Assert.AreEqual("Resolved Message Text", vc.LastErrorsRendered[0]);
}
[Test]
public void ThrowsIfCreateValidationErrorsRendererReturnsNull()
{
@@ -305,12 +326,12 @@ namespace Spring.Web.UI.Controls
public IMessageSource TheMessageSource
{
get { return base.MessageSource; }
get { return base.ResolveMessageSource(); }
}
public IValidationContainer TheValidationContainer
{
get { return base.ValidationContainer; }
get { return base.FindValidationContainer(); }
}
public bool TheDesignMode