UPDATE, December 15, 2013 Version 4.0.4.97 is the latest build. We plan to release the final version in a couple of weeks.
UPDATE, November 20, 2013 Version 4.0.4.87 fixes the reported bug in
ParameterAttribute type. This version replaces all previous versions. It will act as a full version until February 01, 2014. Download it from the References section at the bottom of this article.
UPDATE, November 03, 2013 Version 4.0.4.37 fixes the reported bug that prevented Web Rule to work with Linq to Entity 5.0 in certain scenarios. This version replaces all previous versions. Download it from the References section at the bottom of this article.
UPDATE, October 29, 2013 Version 4.0.4.27, released on October 29, fixes all reported bugs. It replaces the previous version 4.0.3.77. Download it from the References section at the bottom of this article.
We are quite happy to announce the final beta release of the upcoming version 4.0 of Web Rule. The version number of this beta is 4.0.3.77, and it's available for download in the References section of this article.
But before I get into the details, I would like to introduce our newly established
Facebook and
Google+ pages as well as the re-energized
Twitter account. Beginning from this release we are going to have a much stronger social media presence. Please
like us and
subscribe to our news. Thank you!
Now let's talk about the release. In addition to all new features introduced in the two earlier betas which we discussed in detail
here and
here, this version includes much anticipated support for the
IEnumerable and
IQueryable interfaces. It also introduces major enhancements to the world's best business rules user interface. In short, Web Rule now
supports collections!
In a nutshell, the support for the
IEnumerable interface means that rule authors can now create rule conditions using collection and array fields declared in source objects. Web Rule 4.0 supports arrays and any .NET type that implements
IEnumerable, except for those types that implement
IDictionary.
Now, let's talk about collections in general, and how Web Rule handles them. Web Rule 4.0 divides all collections and arrays into two major categories: 1) collections of
reference types and 2) collections of
value types. Let me demonstrate this in a code example:
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using CodeEffects.Rule.Attributes;
namespace CodeEffects.Rule.Harness
{
// The generic base for our source object
public class TestBase<T>
{
// Generic collection; the classes that inherit from
// this base define its type and its UI behavior
public List<T> BaseListItems { get; set; }
// Generic array; the same as above
public T[] BaseArrayItems { get; set; }
// Dictionaries are not supported by Web Rule
// and will be completely ignored
public Dictionary<int, string> Dictionary { get; set; }
}
// Our test source object is set to use its base members
[Source(DeclaredMembersOnly = false)]
public class TestSource : TestBase<TestClass>
{
// Value typed generic collection
public List<int> Integers { get; set; }
// Reference typed generic collection
public EnumerableQuery<TestClass> EnumerableTestClasses { get; set; }
// Non-generic collection
public StringCollection Strings { get; set; }
// Collections whose underlying type cannot be determined at design time
// must define it using the new CollectionItemType property of the Field
// attribute. Otherwise they will be completely ignored
[Field(CollectionItemType = typeof(TimeSpan))]
public ArrayList TimeSpans { get; set; }
// Value typed arrays
public double[] Doubles { get; set; }
// Reference typed arrays
public TestClass[] TestClasses { get; set; }
// Declaring a couple of regular fields in order to have
// something other than collections in the editor
public int Id { get; set; }
public string Name { get; set; }
}
public class TestClass
{
public int Id { get; set; }
public string Name { get; set; }
// Nested collections are fully supported in 4.0
public List<DateTime> Dates { get; set; }
}
}
- Value Typed Collections
First, let's discuss the value typed arrays, and collections and why Web Rule handles them differently from the reference typed ones.
Value typed collections represent arrays of simple values, which are now searchable inside of our business rules. This means that a rule has the ability to check if a collection contains a certain value, or check if that value is at a certain position inside of the collection. It is also possible to apply aggregate functions to the values in these collections such as sum, average and count inside of our rules.
The simplest way to make value type collections searchable is to utilize plain operators such as contains, does not contain, starts with, does not end with, is empty, and so on. This will look very familiar to rule authors who have created conditions using regular fields and values, as Web Rule implements the value typed collections exactly like it implements fields. We could run the rule editor with our TestSource as its source object to see that Web Rule uses them as if they were regular fields and in-rule methods (with all reference typed collections commented out for now):
But they use slightly different operators:
Notice that there are no is and is not operators here. This is because using the equality operators with value typed collections in a business rule doesn't make any practical sense. Of course, you can use your own Help XML to change the default English labels of these operators.
Setting values when creating searchable conditions is the same as setting values for regular fields:
As you can see, if your source object declares only value typed arrays and/or collections, rule authors will not see many differences in the rule editor from what they used to in 3.x. Obviously, if you need more than the built-in operators have to offer you can always write your own in-rule method and implement anything within the bounds of the .NET framework.
It was very difficult to determine how to make aggregation of collections both flexible and powerful, considering all of the different forms of aggregation on all the different types of potential object and values types. In the end, we added support for passing IEnumerable and array parameters to in-rule methods, enabling developers to customize their own aggregation functions for their own unique needs. This is a powerful enhancement to previous versions, which only allowed parameters of type System.Object, value types, and the source object type.
Let's add a couple of these methods to our TestSource class:public int Count<T>(List<T> list)
{
return list.Count;
}
[Method(DisplayName = "Average Time")]
public TimeSpan AverageTime(TimeSpan[] times)
{
// Just returning an instance of a TimeSpan but you
// could do all kinds of fancy things here :)
return TimeSpan.MinValue;
}
And let's run the editor again:
Notice that our second method AverageTime() didn't show up in the menu. This is because Web Rule is smart enough to know that our source object doesn't declare any arrays of System.TimeSpan, and therefore there is no reason to bother the rule author with menu items that (s)he would be unable to use. Let us add such an array and see how it changes our menu:public TimeSpan[] Times { get; set; }
Because the param of our Count() method is generic, the method accepts any List parameters of any underlying type. But if that parameter would be declared as a list of doubles, for example, then the editor would only allow users to input lists of doubles.
- Reference Typed Collections
In Web Rule 4.0 aggregate values on the reference typed collections can be obtained in the same way as with the value typed ones. Simply declare a method that accepts either generic or typed collection(s) and returns the desired result. But making those collections searchable inside of your rules is a totally different story.
For value typed collections we used simple operators in order to access their items. That is possible because each item in those collections is just a primitive value type, and comparisons on them is a trivial matter. In reference typed collections, however, each member is a complex object, and it is necessary to be able to interrogate the members of that object in order to make the entire collection searchable and the whole thing truly usable.
Web Rule solves that problem by implementing an industry-unique method of making the underlying types searchable from inside the business rule. Allow me to illustrate this in detail:
First, we need to uncomment all reference typed collections in our TestSource class. Next, let's add the FieldAttribute to the EnumerableTestClasses collection and set the display name of the collection itself and each of its items. Although this step is optional, it's useful to have those values set in one of our collections in order to demonstrate some new display features:// Reference typed collection
[Field(DisplayName = "Enumerable Test Classes", CollectionItemName = "Enumerable Test Class")]
public EnumerableQuery<TestClass> EnumerableTestClasses { get; set; }
Now run the editor. This time the fields menu will contain several new items:
Notice that the list of operators remains pretty much unchanged. This is because the basic operations are still the same for this type of collection, we just perform them differently. Select the one labeled Exists.... The editor now displays a menu that lists all our reference typed collections and arrays. Because we set the FieldAttribute.DisplayName value for our EnumerableTestClasses collection it is displayed as Enumerable Test Classes:
Select that collection, and see how Web Rule prepares the editor for the search of the collection's underlying type. It now uses the value of FieldAttribute.CollectionItemName that we set earlier to display this field. If that value were not set, then the editor would use the DisplayName, and if the DisplayName is not set then the declared name of the collection is used:
So, now to search our collection for specific item(s) right within the rule all we have to do is to build the search criteria inside of the parentheses which serve as the scope borders for the underlying type of the collection:
When you save the rule, Web Rule stores that search in the same Rule XML as a separate evaluation type rule. You can split those rules into separate documents and reuse them as stand alone rules much like you use the reusable rules.
Web Rule also supports nested collections. If we add a reference type collection to our TestClass object...public class TestClass
{
public int Id { get; set; }
public string Name { get; set; }
// Nested collections are fully supported in 4.0
public List<DateTime> Dates { get; set; }
[Field(DisplayName = "Queued Exceptions", CollectionItemName = "Queued Exception")]
public Queue<System.Exception> Exceptions { get; set; }
}
... we can then use nested search criteria of any complexity:
There are a couple of general things that you should keep in mind when dealing with collections in Web Rule.
- Case sensitivity. The default collation used by instances of SqlServer provide case insensitive data selects. The default LINQ providers that come with .NET, LINQ to SQL, and LINQ to Entity are aware of that and offer no implementation of System.String method overloads that can provide case sensitivity by taking the System.StringComparison enum as a parameter. Therefore, the value of the FieldAttribute.StringComparison property will be ignored on all IQueryable collections, even if they are used for in-memory (not T-SQL) data filtering. Set proper collations in your SqlServer instance if your project requires case sensitive data selection. IEnumerable collections work as expected.
- The Last... operators and IQueryable interface. The default LINQ providers don't offer implementations of the Last has... and Last does not have... operators used in Web Rule. Therefore, the only possible way to implement those operators when rule-based data filtering is used with IQueryable collections in LINQ to SQL or LINQ to Entity providers is to locate the last item of the collection after the entire table is loaded into the server's memory. This might cause performance issues. The IEnumerable collections use the native .NET string methods and work as expected with all new operators. If uncertain, please test your rule before deploying it to production.
- Null reference collections. This beta expects all collections to be initialized. For example, the is empty operator returns true if the collection is empty but it throws exception if it is null. The support for null as empty is planned for the final release of 4.0.
As you can see, the possibilities with this new approach of drilling into underlying objects are endless. The final release of version 4.0 will include the updated Web Rule documentation where we are going to provide as much detail on this subject as we can. Until then please ask as many questions as you need, express concerns, and send feedback using our Support page, or just leave comments here. We'll try to answer each one in a timely fashion.
As always, we would like to THANK YOU for your feedback and patience!