diff --git a/src/Spring/Spring.Core/Validation/ErrorMessage.cs b/src/Spring/Spring.Core/Validation/ErrorMessage.cs
index ee25e528..a44a0d1d 100644
--- a/src/Spring/Spring.Core/Validation/ErrorMessage.cs
+++ b/src/Spring/Spring.Core/Validation/ErrorMessage.cs
@@ -167,6 +167,11 @@ namespace Spring.Validation
/// Resolved error message.
public string GetMessage(IMessageSource messageSource)
{
+ if (messageSource == null)
+ {
+ return Id;
+ }
+
if (Parameters == null)
{
return messageSource.GetMessage(Id);
diff --git a/src/Spring/Spring.Core/Validation/ValidationErrors.cs b/src/Spring/Spring.Core/Validation/ValidationErrors.cs
index be4449f3..de96ecd6 100644
--- a/src/Spring/Spring.Core/Validation/ValidationErrors.cs
+++ b/src/Spring/Spring.Core/Validation/ValidationErrors.cs
@@ -262,6 +262,8 @@ namespace Spring.Validation
///
public IList GetResolvedErrors(string provider, IMessageSource messageSource)
{
+ AssertUtils.ArgumentNotNull(provider, "provider");
+
IList messages = new ArrayList();
IList errors = (IList) errorMap[provider];
diff --git a/src/Spring/Spring.Web/Web/UI/Controls/AbstractValidationControl.cs b/src/Spring/Spring.Web/Web/UI/Controls/AbstractValidationControl.cs
index 7a3b7b2b..7ee5acf0 100644
--- a/src/Spring/Spring.Web/Web/UI/Controls/AbstractValidationControl.cs
+++ b/src/Spring/Spring.Web/Web/UI/Controls/AbstractValidationControl.cs
@@ -20,9 +20,12 @@
#region Imports
+using System;
using System.Collections;
using System.Web.UI;
using Spring.Context;
+using Spring.Util;
+using Spring.Validation;
using Spring.Web.UI.Validation;
#endregion
@@ -42,17 +45,25 @@ namespace Spring.Web.UI.Controls
/// Gets or sets the provider.
///
/// The provider.
- public string Provider
+ public virtual string Provider
{
get
{
if (this.provider == null)
{
- return this.ID;
+ this.provider = this.ID;
+ if (this.provider == null)
+ {
+ this.provider = string.Empty;
+ }
}
return this.provider;
}
- set { this.provider = value; }
+ set
+ {
+ AssertUtils.ArgumentNotNull(value, "Provider");
+ this.provider = value;
+ }
}
///
@@ -69,10 +80,15 @@ namespace Spring.Web.UI.Controls
if (this.renderer == null)
{
this.renderer = CreateValidationErrorsRenderer();
+ AssertUtils.ArgumentNotNull(this.renderer, "Renderer", "CreateValidationErrorsRenderer must not return null");
}
return this.renderer;
}
- set { this.renderer = value; }
+ set
+ {
+ AssertUtils.ArgumentNotNull(value, "Renderer");
+ this.renderer = value;
+ }
}
///
@@ -83,7 +99,7 @@ namespace Spring.Web.UI.Controls
///
protected virtual IMessageSource MessageSource
{
- get { return ValidationContainer.MessageSource; }
+ get { return ValidationContainer==null ? null : ValidationContainer.MessageSource; }
}
///
@@ -108,6 +124,7 @@ namespace Spring.Web.UI.Controls
return container;
}
}
+// throw new NotSupportedException(string.Format("Controls of Type {0} must be placed on a container control implementing IValidationContainer", this.GetType().Name));
return null;
}
}
@@ -116,11 +133,31 @@ namespace Spring.Web.UI.Controls
/// Resolves the 's list of validation errors to a list
/// of elements containing the error messages to be rendered.
///
- /// a list containing elements
+ /// a list containing elements. May return null
protected virtual IList ResolveErrorMessages()
{
IList errorMessages;
- errorMessages = this.ValidationContainer.ValidationErrors.GetResolvedErrors(this.Provider, this.MessageSource);
+
+ // good catch - idea & patch from Roberto Paterlini
+ if (DesignMode)
+ {
+ errorMessages = new string[] { GetType().Name + ":" + ID };
+ return errorMessages;
+ }
+
+ IValidationContainer container = this.ValidationContainer;
+ if (container == null)
+ {
+ return null;
+ }
+
+ IValidationErrors validationErrors = container.ValidationErrors;
+ if (validationErrors == null)
+ {
+ return null;
+ }
+
+ errorMessages = validationErrors.GetResolvedErrors(this.Provider, this.MessageSource);
return errorMessages;
}
@@ -130,8 +167,11 @@ namespace Spring.Web.UI.Controls
///
protected override void Render(HtmlTextWriter writer)
{
- IList errorMessages = ResolveErrorMessages();
- Renderer.RenderErrors(Page as Spring.Web.UI.Page, writer, errorMessages);
+ IList errorMessages;
+
+ errorMessages = ResolveErrorMessages();
+
+ Renderer.RenderErrors(Page as Spring.Web.UI.Page, writer, errorMessages);
}
}
}
\ No newline at end of file
diff --git a/test/Spring/Spring.Core.Tests/Validation/ValidationErrorsTests.cs b/test/Spring/Spring.Core.Tests/Validation/ValidationErrorsTests.cs
index ea62791a..fd10cb36 100644
--- a/test/Spring/Spring.Core.Tests/Validation/ValidationErrorsTests.cs
+++ b/test/Spring/Spring.Core.Tests/Validation/ValidationErrorsTests.cs
@@ -44,6 +44,14 @@ namespace Spring.Validation
private ErrorMessage ErrorMessageTwo = new ErrorMessage("This Is Eva Green", null);
private ErrorMessage ErrorMessageOne = new ErrorMessage("Kissing Leads To Brain Disease", null);
+ [Test]
+ public void ResolveErrorsWithoutMessageSource()
+ {
+ ValidationErrors errors = new ValidationErrors();
+ errors.AddError(string.Empty, ErrorMessageOne);
+ IList resolvedErrors = errors.GetResolvedErrors(string.Empty, null);
+ Assert.AreEqual(ErrorMessageOne.Id, (string)resolvedErrors[0]);
+ }
[Test]
public void ContainsNoErrorsDirectlyAfterInstantiation()
{
diff --git a/test/Spring/Spring.Web.Tests/Web/UI/Controls/AbstractValidationControlTests.cs b/test/Spring/Spring.Web.Tests/Web/UI/Controls/AbstractValidationControlTests.cs
index b22eee81..6d152b69 100644
--- a/test/Spring/Spring.Web.Tests/Web/UI/Controls/AbstractValidationControlTests.cs
+++ b/test/Spring/Spring.Web.Tests/Web/UI/Controls/AbstractValidationControlTests.cs
@@ -21,10 +21,16 @@
#region Imports
using System;
+using System.Collections;
+using System.Globalization;
using System.Web.UI;
using NUnit.Framework;
using Rhino.Mocks;
using Spring.Context;
+using Spring.Context.Support;
+using Spring.Util;
+using Spring.Validation;
+using Spring.Web.UI.Validation;
#endregion
@@ -37,42 +43,89 @@ namespace Spring.Web.UI.Controls
[TestFixture]
public class AbstractValidationControlTests
{
- public class TestValidationControl : AbstractValidationControl
+ [Test]
+ public void DefaultsToControlIDOrStringEmptyAsProviderName()
{
- private IValidationContainer _vc;
+ TestValidationControl vc;
- public TestValidationControl()
- {
- }
+ vc = new TestValidationControl(null);
+ Assert.AreEqual(string.Empty, vc.Provider);
- public TestValidationControl(IValidationContainer testVc)
- {
- _vc = testVc;
- }
+ vc = new TestValidationControl(null);
+ vc.ID = "TestControl";
+ Assert.AreEqual(vc.ID, vc.Provider);
- protected override Spring.Web.UI.Validation.IValidationErrorsRenderer CreateValidationErrorsRenderer()
- {
- throw new Exception("The method or operation is not implemented.");
- }
+ vc = new TestValidationControl(null);
+ vc.ID = "TestControl";
+ vc.Provider = "TestProvider";
- protected override IValidationContainer ValidationContainer
- {
- get
- {
- if (_vc != null) return _vc;
- return base.ValidationContainer;
- }
- }
+ Assert.AreEqual("TestProvider", vc.Provider);
+ }
- public IMessageSource TheMessageSource
- {
- get { return base.MessageSource; }
- }
+ [Test]
+ public void ResolvesAndRendersValidationErrors()
+ {
+ TestValidationControl vc = new TestValidationControl();
+ vc.ID = "TestControl";
- public IValidationContainer TheValidationContainer
+ Page page = new Page();
+ page.Controls.Add(vc);
+ page.ValidationErrors.AddError(vc.Provider, new ErrorMessage("msgId"));
+ StaticMessageSource msgSrc = new StaticMessageSource();
+ msgSrc.AddMessage("msgId", CultureInfo.CurrentUICulture, "Resolved Message Text");
+ page.MessageSource = msgSrc;
+
+ vc.TestRender(null);
+ Assert.AreEqual("Resolved Message Text", vc.LastErrorsRendered[0]);
+ }
+
+ [Test]
+ public void ThrowsIfCreateValidationErrorsRendererReturnsNull()
+ {
+ TestValidationControl vc = new TestValidationControl(null);
+ vc.ID = "TestControl";
+
+ Page page = new Page();
+ page.Controls.Add(vc);
+ page.ValidationErrors.AddError(vc.Provider, new ErrorMessage("msgId"));
+
+ try
{
- get { return base.ValidationContainer; }
+ vc.TestRender(null);
+ Assert.Fail();
}
+ catch (ArgumentNullException ane)
+ {
+ Assert.AreEqual("Renderer", ane.ParamName);
+ }
+ }
+
+ [Test]
+ public void NoExceptionWhenNoValidationContainer()
+ {
+ TestValidationControl vc = new TestValidationControl();
+ Assert.IsFalse(vc.TheDesignMode);
+ Assert.IsNull(vc.TheMessageSource);
+ Assert.IsNull(vc.TheValidationContainer);
+
+ vc.TestRender(null);
+ }
+
+ [Test]
+ public void NoExceptionWhenNoErrors()
+ {
+ Page page = new Page();
+ page.MessageSource = new StaticMessageSource();
+ TestValidationControl vc = new TestValidationControl();
+ page.Controls.Add(vc);
+
+ // assert assumptions
+ Assert.IsFalse(vc.TheDesignMode);
+ Assert.AreSame(page, vc.TheValidationContainer);
+ Assert.AreSame( page.MessageSource, vc.TheMessageSource );
+ Assert.AreEqual(0, page.ValidationErrors.GetResolvedErrors(vc.Provider, vc.TheMessageSource).Count);
+
+ vc.TestRender(null);
}
[Test]
@@ -116,13 +169,82 @@ namespace Spring.Web.UI.Controls
{
MockRepository mocks = new MockRepository();
IMessageSource messageSource = (IMessageSource)mocks.DynamicMock(typeof(IMessageSource));
- IValidationContainer container = (IValidationContainer)mocks.DynamicMock(typeof(IValidationContainer));
- TestValidationControl ctl = new TestValidationControl(container);
+ // IValidationContainer container = (IValidationContainer)mocks.DynamicMock(typeof(IValidationContainer));
- Expect.Call(container.MessageSource).Return(messageSource);
- mocks.ReplayAll();
+ Page page = new Page();
+ page.MessageSource = messageSource;
+ TestValidationControl ctl = new TestValidationControl();
+ page.Controls.Add(ctl);
Assert.AreEqual(messageSource, ctl.TheMessageSource);
}
+
+ #region TestValidationControl
+
+ private class TestValidationControl : AbstractValidationControl
+ {
+ public class CapturingRenderer : IValidationErrorsRenderer
+ {
+ public IList LastErrorsRendered;
+ private readonly IValidationErrorsRenderer _inner;
+
+ public CapturingRenderer(IValidationErrorsRenderer inner)
+ {
+ _inner = inner;
+ }
+
+ public void RenderErrors(Page page, HtmlTextWriter writer, IList errors)
+ {
+ LastErrorsRendered = errors;
+ if (_inner != null)
+ {
+ _inner.RenderErrors(page, writer, errors);
+ }
+ }
+ }
+
+ private readonly IValidationErrorsRenderer _ver;
+
+ public TestValidationControl()
+ : this(new CapturingRenderer(null))
+ { }
+
+ public TestValidationControl(IValidationErrorsRenderer renderer)
+ {
+ _ver =renderer;
+ }
+
+ public void TestRender(HtmlTextWriter writer)
+ {
+ base.Render(writer);
+ }
+
+ protected override IValidationErrorsRenderer CreateValidationErrorsRenderer()
+ {
+ return _ver;
+ }
+
+ public IList LastErrorsRendered
+ {
+ get { return ((CapturingRenderer)_ver).LastErrorsRendered; }
+ }
+
+ public IMessageSource TheMessageSource
+ {
+ get { return base.MessageSource; }
+ }
+
+ public IValidationContainer TheValidationContainer
+ {
+ get { return base.ValidationContainer; }
+ }
+
+ public bool TheDesignMode
+ {
+ get { return base.DesignMode; }
+ }
+ }
+
+ #endregion
}
}
\ No newline at end of file