Skip to content

Commit c68040a

Browse files
committed
Merge branch 'feature/FilterByAttribute-key-validation' into develop
Previously, a common scenario for using the `[FilterByAttribute()]` attribute was to filter by content type. As `ContentType` is no longer stored as an attribute (4a9f5b7), this no longer works. To mitigate this, we previously introduced the new `[FilterByContentType()]` attribute (105cfdd). Legacy implementations that previously used `[FilterByAttribute("ContentType", …)]`, however, would not get an error. In fact, it might even appear that it is working if their database contains legacy values for `ContentType` in `Topic.Attributes`. To help avoid errors and confusion, while offering better guidance for migrations, the `[FilterByAttribute()]` attribute has been updated to throw an `ArgumentException` if the implementation attempts to set the `Key` to `ContentType`. In this case, it will advise migrating to `[FilterByContentType()]` instead. Unfortunately, this doesn't offer design-time feedback, but it will offer runtime guidance that the existing behavior isn't working.
2 parents 13b1114 + 5b5dae0 commit c68040a

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

OnTopic.Tests/TopicMappingServiceTest.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,25 @@ public async Task Map_FilterByAttribute_ReturnsFilteredCollection() {
967967

968968
}
969969

970+
/*==========================================================================================================================
971+
| TEST: MAP: FILTER BY INVALID ATTRIBUTE: THROWS EXCEPTION
972+
\-------------------------------------------------------------------------------------------------------------------------*/
973+
/// <summary>
974+
/// Attempts to map a view model that has an invalid <see cref="FilterByAttributeAttribute.Key"/> value of <c>ContentType
975+
/// </c>; throws an <see cref="ArgumentException"/>.
976+
/// </summary>
977+
[TestMethod]
978+
[ExpectedException(typeof(ArgumentException))]
979+
public async Task Map_FilterByInvalidAttribute_ThrowsExceptions() {
980+
981+
var topic = TopicFactory.Create("Test", "FilteredInvalid");
982+
983+
var target = await _mappingService.MapAsync<FilteredInvalidTopicViewModel>(topic).ConfigureAwait(false);
984+
985+
Assert.AreEqual<int>(2, target.Children.Count);
986+
987+
}
988+
970989
/*==========================================================================================================================
971990
| TEST: MAP: FILTER BY CONTENT TYPE: RETURNS FILTERED COLLECTION
972991
\-------------------------------------------------------------------------------------------------------------------------*/
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*==============================================================================================================================
2+
| Author Ignia, LLC
3+
| Client Ignia, LLC
4+
| Project Topics Library
5+
\=============================================================================================================================*/
6+
using OnTopic.Mapping.Annotations;
7+
using OnTopic.ViewModels;
8+
using OnTopic.ViewModels.Collections;
9+
10+
namespace OnTopic.Tests.ViewModels {
11+
12+
/*============================================================================================================================
13+
| VIEW MODEL: FILTERED TOPIC (INVALID)
14+
\---------------------------------------------------------------------------------------------------------------------------*/
15+
/// <summary>
16+
/// Provides a strongly-typed data transfer object for testing views properties annotated with the <see cref="
17+
/// FilterByAttributeAttribute"/>. Includes an invalid <see cref="FilterByAttributeAttribute"/>.
18+
/// </summary>
19+
/// <remarks>
20+
/// This is a sample class intended for test purposes only; it is not designed for use in a production environment.
21+
/// </remarks>
22+
public class FilteredInvalidTopicViewModel {
23+
24+
[FilterByAttribute("ContentType", "Page")]
25+
public TopicViewModelCollection<TopicViewModel> Children { get; } = new();
26+
27+
} //Class
28+
} //Namespace

OnTopic/Mapping/Annotations/FilterByAttributeAttribute.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
| Project Topics Library
55
\=============================================================================================================================*/
66

7+
using System;
8+
using OnTopic.Internal.Diagnostics;
9+
710
namespace OnTopic.Mapping.Annotations {
811

912
/*============================================================================================================================
@@ -30,9 +33,22 @@ public sealed class FilterByAttributeAttribute : System.Attribute {
3033
/// <param name="key">The key of the attribute to filter by.</param>
3134
/// <param name="value">The value of the attribute to filter by.</param>
3235
public FilterByAttributeAttribute(string key, string value) {
36+
37+
/*------------------------------------------------------------------------------------------------------------------------
38+
| Validate input
39+
\-----------------------------------------------------------------------------------------------------------------------*/
3340
TopicFactory.ValidateKey(key, false);
41+
Contract.Requires<ArgumentException>(
42+
!key.Equals("ContentType", StringComparison.OrdinalIgnoreCase),
43+
"The ContentType is not stored as an attribute. To filter by ContentType, use [FilterByContentType] instead."
44+
);
45+
46+
/*------------------------------------------------------------------------------------------------------------------------
47+
| Set properties
48+
\-----------------------------------------------------------------------------------------------------------------------*/
3449
Key = key;
3550
Value = value;
51+
3652
}
3753

3854
/*==========================================================================================================================

0 commit comments

Comments
 (0)