Check a property is unique in list in FluentValidation - c#

I am trying to ensure that a list has unique SSN's. I am getting the "Property name could not be automatically determined for expression element => element. Please specify either a custom property name by calling 'WithName'" error. Would we know what I am doing wrong here?
using FluentValidation;
using FluentValidation.Validators;
public class PersonsValidator : AbstractValidator<Persons>
{
public PersonsValidator()
{
this.RuleFor(element => element)
.SetValidator(new SSNNumbersInHouseHoldShouldBeUnique<Persons>())
.WithName("SSN");
.WithMessage("SSN's in household should be unique");
}
}
public class SSNNumbersInHouseHoldShouldBeUnique<T> : PropertyValidator
{
public SSNNumbersInHouseHoldShouldBeUnique()
: base("SSN's in household should be unique")
{
}
protected override bool IsValid(PropertyValidatorContext context)
{
var persons = context.Instance as Persons;
try
{
if (persons == null)
{
return false;
}
var persons = persons.Where(element => element.SSN.Trim().Length > 0);
var allSSNs = persons.Select(element => element.SSN.Trim());
if (allSSNs.Count() > allSSNs.Distinct().Count())
{
return false;
}
return true;
}
catch (Exception ex)
{
return false;
}
}
}
public class Persons : List<Person>
{}
public class Person
{
public string SSN{ get; set; }
}

I was using FluentValidation version 4.6. According to Jeremy Skinner(author of FluentValidation), I need to be on at least 5.6 to be able to use model-level rules (like RuleFor(element => element)).
As a workaround, I added this validation on the actual class itself instead of creating a validation class. Hope this helps someone.
using FluentValidation;
using FluentValidation.Results;
public class Persons : List<Person>
{
public void ValidateAndThrow()
{
var errors = new List<ValidationFailure>();
try
{
var persons = this.Where(element => element.SSN.Trim().Length > 0);
var allSSNs = persons.Select(element => element.SSN.Trim());
if (allSSNs.Count() > allSSNs.Distinct().Count())
{
var validationFailure = new ValidationFailure("UniqueSSNsInHouseHold", "SSN's in a household should be unique");
errors.Add(validationFailure);
}
}
catch (Exception ex)
{
}
if (errors.Any())
{
throw new ValidationException(errors);
}
}
}

Related

How to send action with AsterNET, C#?

I'm working with AsterNET and C#, I need to get the status of all the extensions, specifically the result of Action: ExtensionStateList but the library doesn't have this action, I'm trying to create it but I can't get it. I hope someone can guide me. Attached is the code.
ResponseEvents re;
try
{
re = manager.SendEventGeneratingAction(new ExtensionStateListAction());
}
catch (EventTimeoutException e)
{
re = e.PartialResult;
}
foreach (ManagerEvent e in re.Events)
{
foreach (KeyValuePair<string, string> d in e.Attributes)
{
Console.WriteLine(e);
}
}
using System;
using AsterNET.Manager.Event;
namespace AsterNET.Manager.Action
{
public class ExtensionStateListAction : ManagerActionEvent
{
public override string Action
{
get { return "ExtensionStateList"; }
}
public override Type ActionCompleteEventClass()
{
return typeof (ExtensionStateListCompleteEvent);
}
}
}
namespace AsterNET.Manager.Event
{
public class ExtensionStateListCompleteEvent : ResponseEvent
{
private int listItems;
public int ListItems
{
get { return this.listItems; }
set { this.listItems = value; }
}
public ExtensionStateListCompleteEvent(ManagerConnection source)
: base(source)
{
}
}
}
Result of this command will come in set of events "ExtensionState" and final "ExtensionStateCompleate"
It will be asyncronous.
You should setup event listener and parse that.

HttpSessionStateBase losing property values of inherited type

We are using HttpSessionStateBase to store messages in a set up similar to this working example:
public class HttpSessionMessageDisplayFetch : IMessageDisplayFetch
{
protected HttpSessionStateBase _session;
private IList<ICoreMessage> messages
{
get
{
if (_session[EchoCoreConstants.MESSAGE_KEY] == null)
_session[EchoCoreConstants.MESSAGE_KEY] = new List<ICoreMessage>();
return _session[EchoCoreConstants.MESSAGE_KEY] as IList<ICoreMessage>;
}
}
public HttpSessionMessageDisplayFetch()
{
if (HttpContext.Current != null)
_session = new HttpSessionStateWrapper(HttpContext.Current.Session);
}
public void AddMessage(ICoreMessage message)
{
if (message != null)
messages.Add(message);
}
public IEnumerable<IResultPresentation> FlushMessagesAsPresentations(IResultFormatter formatter)
{
var mToReturn = messages.Select(m => m.GetPresentation(formatter)).ToList();
messages.Clear();
return mToReturn;
}
}
When we pass in a QualityExplicitlySetMessage (which inherits from ICoreMessage, see below) it is saved correctly to messages.
This is how the object looks after being inserted into the messages list, at the end of AddMessage(ICoreMessage message) above.
But when we come to access it after changing controllers the inherited member's properties are null, which causes a variety of null reference exceptions.
This is how the object now looks after we call FlushMessagesAsPresentations. I've commented out var mToReturn... as this tries to access one of these null ref properties.
I'd like to ask the following:
Why is the HttpSessionStateBase failing to capture these values taken
by the inherited type?
Is this an issue in saving to the HttpSession or in retrieving?
Is this anything to do with, as I suspect, inheritance?
Or is the fact I'm potentially calling a new controller that dependency injects the HttpSessionMessageDisplayFetch causing an issue?
I'm a first-time poster so please let me know if I'm making any kind of faux pas - Super keen to learn! Any input is very welcome.
Some potentially useful code snippets:
QualityExplicitlySetMessage
public class QualityExplicitlySetMessage : QualityChangeMessage
{
public QualityExplicitlySetMessage(IQPossession before, IQPossession after, IQEffect qEffect)
: base(before, after, qEffect)
{
IsSetToExactly = true;
}
}
QualityChangeMessage - Working example
public abstract class QualityChangeMessage : CoreMessage, IQualityChangeMessage
{
protected PossessionChange Change;
public PossessionChange GetPossessionChange()
{
return Change;
}
protected QualityChangeMessage(IQPossession before, IQPossession after, IQEffect qEffect)
{
Change = new PossessionChange(before, after, qEffect);
StoreQualityInfo(qEffect.AssociatedQuality);
}
public override IResultPresentation GetPresentation(IResultFormatter formatter)
{
return formatter.GetQualityResult(this);
}
#region IQualityChangeMessage implementation
public int LevelBefore
{
get { return Change.Before.Level; }
}
//... And so on with values dependent on the Change property.
}
CoreMessage - Working example
public abstract class CoreMessage : ICoreMessage
{
public string MessageType
{
get { return GetType().ToString(); }
}
public string ImageTooltip
{
get { return _imagetooltip; }
set { _imagetooltip = value; }
}
public string Image
{
get { return _image; }
set { _image = value; }
}
public int? RelevantQualityId { get; set; }
protected void StoreQualityInfo(Quality q)
{
PyramidNumberIncreaseLimit = q.PyramidNumberIncreaseLimit;
RelevantQualityId = q.Id;
RelevantQualityName = q.Name;
ImageTooltip = "<strong>" + q.Name + "</strong><br/>" + q.Description + "<br>" +
q.EnhancementsDescription;
Image = q.Image;
}
public virtual IResultPresentation GetPresentation(IResultFormatter formatter)
{
return formatter.GetResult(this);
}
}
UserController - Working example.
public partial class UserController : Controller
{
private readonly IMessageDisplayFetch _messageDisplayFetch;
public UserController(IMessageDisplayFetch messageDisplayFetch)
{
_messageDisplayFetch = messageDisplayFetch;
}
public virtual ActionResult MessagesForStoryletWindow()
{
var activeChar = _us.CurrentCharacter();
IEnumerable<IResultPresentation> messages;
messages = _messageDisplayFetch.FlushMessagesAsPresentations(_storyFormatter);
var vd = new MessagesViewData(messages)
{
Character = new CharacterViewData(activeChar),
};
return View(Views.Messages, vd);
}
}

How can I write these methods in a more generic way in c#?

I have the following class hierarchy:
EstadoBaseMO (parent)
EstadoSAMO(EstadoBaseMO child)
EstadoGesDocMO(EstadoBaseMO child)
SolicitudBasePresenter(parent)
SolicitudGesDocPresenter(SolicitudBasePresenter child)
SolicitudSAPresenter(SolicitudBasePresenter child)
EstadoBaseBO(parent)
EstadoGesDocBO(EstadoBaseBO child)
EstadoSABO(EstadoBaseBO child)
I need to implement a method called SaveNewDetailStates, with the following implementation in SolicitudBasePresente is
public bool SaveNewDetailStates(List<EstadoBaseMO> estados)
{
bool result = true;
if (estados.Any())
{
try
{
EstadoGesDocBO bo = new EstadoGesDocBO();
foreach (var estado in estados)
{
var savedState = bo.Insert(estado);
result &= ((savedState != null) && (savedState.Id != estado.Id));
}
}
catch (Exception ex)
{
result = false;
}
}
return result;
}
SolicitudGesDocPresenter.SaveNewDetailStates implementation
public bool SaveNewDetailStates(List<EstadoGesDocMO> estados)
{
bool result = true;
if (estados.Any())
{
try
{
EstadoGesDocBO bo = new EstadoGesDocBO();
foreach (var estado in estados)
{
var savedState = bo.Insert(estado);
result &= ((savedState != null) && (savedState.Id != estado.Id));
}
}
catch (Exception ex)
{
result = false;
}
}
return result;
}
SolicitudSAPresenter.SaveNewDetailStates implementation
public bool SaveNewDetailStates(List<EstadoSAMO> estados)
{
bool result = true;
if (estados.Any())
{
try
{
EstadoSABO bo = new EstadoSABO();
foreach (var estado in estados)
{
var savedState = bo.Insert(estado);
result &= ((savedState != null) && (savedState.Id != estado.Id));
}
}
catch (Exception ex)
{
result = false;
}
}
return result;
}
As you can see, the code is exactly the same with two differences, in SolicitudSAPresenter I'm using EstadoSAMO and EstadoSABO classes, similar in SolicitudGesDocPresenter.
Things to know:
I don't really need an implementation of SolicitudBasePresenter.SaveNewDetailStates
I tried to convert the parent method(SolicitudBasePresenter.SaveNewDetailStates) to an abstract method, but then, the SAPresenter and GesDocPresenter can't use override because they need to implement the same signature (and it's not the same..), besides, soon after I realized I need a concrete implementation of SolicitudBasePresenter, so it shouldn't be an abstract class (similar happens with a virtual method)
Maybe the use of generics can solve that problem, but I'm still not used to them. I tried with something like SaveNewDetailStates<T,K>(List<T> estados), but then I'm lost and I don't know what else can I do.
What is the best approach for writing this code?
The only solution I have is to delete the SaveNewDetailStates from parent presenter, and write the concrete implementation in children and then everything is fine but...I don't think that's even a solution for a good developer..
You need to use Generics. Define the class EstadoBaseMO<T> and then use the type T in your save method.
public bool SaveNewDetailStates(List<T> estados)
Your child classes can then (for example) extend EstadoBaseMO<SolicitudBasePresenter>.
There are lots of generics tutorials online, have a look at some of them.
https://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx
you can use Generics but you still need to use Interfaces to implement what you need, but you can do it only with Interfeces similar to this, I made separate IEstadoState and IEstadoMO to make it more clear if you don't need additional fields in your logic you can make one interface instead of these two
public interface IEstadoState
{
int Id { get; set; }
}
public interface IEstadoMO
{
int Id { get; set; }
}
public interface IEstadoBO
{
IEstadoState Insert(IEstadoMO estadoMO);
}
public class SolicitudBasePresenter
{
public virtual bool SaveNewDetailStates(List<IEstadoMO> estados, IEstadoBO estadoBO)
{
bool result = true;
if (estados.Any())
{
try
{
foreach (var estado in estados)
{
var savedState = estadoBO.Insert(estado);
result &= ((savedState != null) && (savedState.Id != estado.Id));
}
}
catch (Exception ex)
{
result = false;
}
}
return result;
}
}
public class SolicitudGesDocPresenter : SolicitudBasePresenter { }
public class SolicitudSAPresenter : SolicitudBasePresenter { }
if you prefer to use Generic or don't want to pass second parameter to method here is how it will look
public class SolicitudBasePresenter<T1, T2> where T1 : IEstadoMO where T2 : IEstadoBO, new()
{
public bool SaveNewDetailStates(List<T1> estados)
{
bool result = true;
if (estados.Any())
{
try
{
foreach (var estado in estados)
{
var estadoBO = new T2();
var savedState = estadoBO.Insert(estado);
result &= ((savedState != null) && (savedState.Id != estado.Id));
}
}
catch (Exception ex)
{
result = false;
}
}
return result;
}
}
public class EstadoState : IEstadoState
{
public int Id {get; set;}
}
public class EstadoBaseMO : IEstadoMO
{
public int Id { get; set; }
}
public class EstadoBaseBO : IEstadoBO
{
public IEstadoState Insert(IEstadoMO estado) { return new EstadoState(); }
}
public class EstadoSAMO : EstadoBaseMO { }
public class EstadoGesDocMO : EstadoBaseMO { }
public class EstadoGesDocBO : EstadoBaseBO { }
public class EstadoSABO : EstadoBaseBO { }
public class SolicitudGesDocPresenter : SolicitudBasePresenter<EstadoGesDocMO, EstadoGesDocBO> { }
public class SolicitudSAPresenter : SolicitudBasePresenter<EstadoSAMO, EstadoSABO> { }
your method call will be
var docPresenter = new SolicitudGesDocPresenter();
docPresenter.SaveNewDetailStates(new List<EstadoGesDocMO>());
also you can declare children like this
public class SolicitudGesDocPresenter<T1, T2> : SolicitudBasePresenter<T1, T2> where T1 : IEstadoMO where T2 : IEstadoBO, new() { }
public class SolicitudSAPresenter<T1, T2> : SolicitudBasePresenter<T1, T2> where T1 : IEstadoMO where T2 : IEstadoBO, new() { }
you'll call it in this way
var docPresenter = new SolicitudGesDocPresenter<EstadoGesDocMO, EstadoGesDocBO>();
docPresenter.SaveNewDetailStates(new List<EstadoGesDocMO>());

Testing FluentValidation PropertyValidator

Is it possible to test a FluentValidation PropertyValidator in isolation?
I know I can test the Validator that's using the PropertyValidator for specific errors but I’d rather test true/false just on the property validator if possible.
Can this be done? If so, how?
I also wanted to test my true / false logic. It is a shame the IsValid method is protected. My work around was to create another IsValid method and have the protected IsValid call through to it.
public class MyValidator: PropertyValidator
{
public MyValidator(
string errorMessage = "default Message") : base(errorMessage)
{
}
protected override bool IsValid(PropertyValidatorContext context)
{
var stringToValidate = context.PropertyValue as String;
return IsValid(stringToValidate);
}
public bool IsValid(string stringToValidate)
{
if (stringToValidate == null)
{
return false;
}
//testing logic here
return true;
}
}
I know this has been a while, but I achieved this as follows:
Custom Validator:
public class MyValidator : PropertyValidator
{
public MyValidator ()
: base("Value must be null or between 0 and 3.")
{
}
protected override bool IsValid(PropertyValidatorContext context)
{
if (context.PropertyValue == null)
{
return true;
}
var value = (decimal)context.PropertyValue;
return value >= 0m && value <= 3m;
}
}
Test Validator:
public class TestValidator : InlineValidator<TestObject>
{
public TestValidator (params Action<TestValidator >[] actions)
{
foreach (var action in actions)
{
action(this);
}
}
}
Test Object:
public class TestObject
{
public TestObject(decimal? val)
{
this.GenericDecimal = val;
}
public decimal? GenericDecimal { get; set; }
}
Test:
[Test]
public void TestIt()
{
var validator = new TestValidator(v => v.RuleFor(obj => obj.GenericDecimal).SetValidator( new MyValidator() ));
Assert.IsTrue(validator.Validate(new TestObject(null)).IsValid);
Assert.IsTrue(validator.Validate(new TestObject(0m)).IsValid);
Assert.IsTrue(validator.Validate(new TestObject(3m)).IsValid);
Assert.IsFalse(validator.Validate(new TestObject(-1m)).IsValid);
Assert.IsFalse(validator.Validate(new TestObject(3.01m)).IsValid);
}
As for version 6.2 of FluentValidation it is possible to build the PropertyValidator.Validate() parameter due to making ValidatorSelectors globally configurable: https://github.com/JeremySkinner/FluentValidation/commit/95376c0519da1a06388be91a97fb5062fd4a162e
In the below example you see how I validate the 'puic' property of Track
Unit test:
public void ExistsInCollectionValidatorTest()
{
var track = new Track()
{
puic = "p1"
};
var sut = new ExistsInCollectionValidator<Track>();
// Build PropertyValidator.Validate() parameter
var selector = ValidatorOptions.ValidatorSelectors.DefaultValidatorSelectorFactory();
var context = new ValidationContext(track, new PropertyChain(), selector);
var propertyValidatorContext = new PropertyValidatorContext(context, PropertyRule.Create<Track,string>(t => t.puic), "puic");
var results = sut.Validate(propertyValidatorContext);
// Assertion..
}

Implementing conditional in a fluent interface

I've been trying to implement a fluent interface for a set of rules in my system. What I am trying to accomplish is this
TicketRules
.RequireValidation()
.When(quartType => quartType == QuartType.Before).TotalMilageIs(64)
.When(quartType => quartType == QuartType.After).TotalMilageIs(128);
However, I have trouble implementing the When conditional how I intended to be. Currently, I need to call When() twice like in this snippet:
rules.When(param => param.Remarque == "Test").TotalMilageIs(100);
rules.When(param => param.Remarque == "Other").TotalMilageIs(50);
var params1 = new AddTicketParameters() { Remarque = "Test" };
var params2 = new AddTicketParameters() { Remarque = "Other" };
rules.ExecuteWith(params1);
Assert.That(ticket.TotalMilage, Is.EqualTo(100));
rules.ExecuteWith(params2);
Assert.That(ticket.TotalMilage, Is.EqualTo(50));
My TicketRules class looks this:
[EditorBrowsable(EditorBrowsableState.Never)]
public class TicketRules : ITicketRule, IHideObjectMembers
{
private Ticket theTicket;
public Ticket Ticket
{
set
{
theTicket = value;
}
}
private List<ITicketRule> allRules = new List<ITicketRule>();
public TicketRules()
{
}
public TicketRules(Ticket ticket)
{
theTicket = ticket;
}
public void Execute()
{
ExecuteWith(null, null);
}
public void ExecuteWith(AddTicketParameters param)
{
ExecuteWith(param, null);
}
public virtual void ExecuteWith(AddTicketParameters param, Ticket outsideTicket)
{
foreach (ITicketRule rule in allRules)
{
rule.ExecuteWith(param, theTicket ?? outsideTicket);
}
}
public TicketRules RequireValidation()
{
CreateModifierRule(ticket => ticket.NeedValidation = true);
return this;
}
public TicketRules TotalMilageIs(int milage)
{
CreateModifierRule(ticket => ticket.TotalMilage = milage);
return this;
}
private void CreateModifierRule(Action<Ticket> function)
{
AddRule(new ModifierTicketRule(function));
}
internal void AddRule(ITicketRule rule)
{
allRules.Add(rule);
}
public WhenClauseTicketRule When(Predicate<AddTicketParameters> predicate)
{
WhenClauseTicketRule whenClause = new WhenClauseTicketRule();
whenClause.Predicate = predicate;
AddRule(whenClause);
return whenClause;
}
public TicketRules UseStandardFormulaForTotalMilageAndTime()
{
AddRule(new StandardFormulaTicketRule());
return this;
}
public TicketRules EnsureMinimumMilageIs(int milage)
{
AddRule(new EnsureMinimumMilageTicketRule(milage));
return this;
}
}
the ITicketRules
internal interface ITicketRule : IHideObjectMembers
{
void ExecuteWith(AddTicketParameters param, Ticket ticket);
}
I also need to support the subclasses of AddTicketParameters in the When clause (I've though maybe using generics for that part). I'm posting here because I'm all confused in my design and the Martin Fowler articles confuse me even more.
This is known as the finishing problem when method chaining
Try this
TicketRules
.RequireValidation()
.When(quartType => quartType == QuartType.Before,
rule => rule.TotalMilageIs(64))
.When(quartType => quartType == QuartType.After,
rule => rule.TotalMilageIs(128));
It looks a little odd at first, but it wraps your conditionals into a different scope so you can conditionally execute them. Think about it like creating your own if block. By closing it, you know when you can "finish" a sub statement.

Categories