Implementing a Chain of Validations with their own confirmation dialogs? - algorithm

I need to perform a series of validations, say ValidationA, ValidationB, ValidationC.
If any validation fails, the chain fails to validate immediately.
Each subsequent validation is performed only after the previous validation condition passes.
If a validation condition fails, I need to show a confirmation dialog to the user, e.g. "Are you sure you want to do this?" — where if the user says "Yes" then we should move on to the next validation in the chain. If the user says "No" in the confirmation dialog, then we can fail immediately.
What is a good way to implement this?

The answer is in C#, but I hope it's clear. The most important thing here is that raw validation is separated from the UI. OverridableValidator is an "UI guy" which gets "logic guy" in constructor, along with the message to be shown to the user.
interface IValidator<T>
{
bool IsValid(T subject);
}
class OverridableValidator<T> : IValidator<T>
{
readonly IValidator<T> _validator;
readonly string _confirmOverrideMessage;
public OverridableValidator(IValidator<T> validator, string confirmOverrideMessage)
{
_validator = validator;
_confirmOverrideMessage = confirmOverrideMessage;
}
public bool IsValid(T subject)
{
if (_validator.IsValid(subject))
{
return true;
}
return MessageBox.Show(_confirmOverrideMessage, "Confirmation required", MessageBoxIcon.Question, MessageBoxButtons.YesNo) == DialogResult.Yes;
}
}
class Person
{
public int Age {get;set;}
public int HeightInCentimeters {get;set;}
}
class MaturityValidator : IValidator<Person>
{
public bool IsValid(Person guy)
{
return guy.Age >= 18;
}
}
class HeightValidator : IValidator<Person>
{
public bool IsValid(Person guy)
{
return guy.HeightInCentimeters < 120;
}
}
void Main()
{
var ageValidator = new OverridableValidator<Person>(new MaturityValidator(), "Do you want to sell him cigarettes?");
var heightValidator = new OverridableValidator<Person>(new HeightValidator(), "Do you want to invite such a short person to your basketball team?");
var validatedPerson = new Person() { Age = 15, HeightInCentimeters = 140 };
var validatorsList = new[] {ageValidator, heightValidator};
foreach (var validator in validatorsList)
{
if (!validator.IsValid(validatedPerson))
{
return; //validaton failed
}
}
Console.WriteLine("This guy can smoke and play in NBA");
}

Implement it like this:
(ValidationA || UserConfirmationA) && (ValidationB || UserConfirmationB) && (ValidationC || UserConfirmationC)
where Validation and UserComfirmation are function which do what their names say and return a boolean.
I assume that && and || are lazy which is the case in most languages.

In addition to what dzendras said, it might help for you to look at Chain of responsibility pattern allowing you to add validators dynamically.

Related

Validating selection field

I have a property that has an enumeration, in one of the values of the enumeration I have "help", if the user selects that option, I would like to do two things: 1. Send the user a text with help. 2. Ask the user if he wants to continue, or if he wants to leave. I do not know how to do it.
thank you very much.
public enum ContentClassification
{
Confidential_Restricted = 1 ,
Confidential_Secret = 2,
Public = 3,
Strictly_Confidential = 4,
help = 5
};
public ContentClassification ContentClassification { get; set; }
return new FormBuilder()
.Field(nameof(ContentClassification))
You may launch the Form many times, means if you get the "Help" choice from the first Form, launch another form for confirmation.
For example:
public enum ContentClassification
{
Confidential_Restricted = 1,
Confidential_Secret = 2,
Public = 3,
Strictly_Confidential = 4,
help = 5
};
public enum Validating
{
Continue,
Leave
};
[Serializable]
public class Classification
{
public ContentClassification? Choice;
public static IForm<Classification> BuildForm()
{
return new FormBuilder<Classification>()
.Message("You want to")
.Field(nameof(Choice))
.Build();
}
public Validating? Confirmation;
public static IForm<Classification> BuildConfirmForm()
{
return new FormBuilder<Classification>()
.Message("Send your message here")
.Field(nameof(Confirmation))
.Build();
}
}
And then create your RootDialog for example like this:
[Serializable]
public class RootDialog : IDialog<object>
{
public Task StartAsync(IDialogContext context)
{
var form = new FormDialog<Classification>(new Classification(), Classification.BuildForm, FormOptions.PromptInStart, null);
context.Call(form, this.GetResultAsync);
return Task.CompletedTask;
}
private async Task GetResultAsync(IDialogContext context, IAwaitable<Classification> result)
{
var state = await result;
if (state.Choice == ContentClassification.help)
{
var form = new FormDialog<Classification>(new Classification(), Classification.BuildConfirmForm, FormOptions.PromptInStart, null);
context.Call(form, null); //change null to your result task here to handle the result.
}
}
}
You still need to implement the logic codes for other options in GetResultAsync method together with the logic codes to handle the result of second form BuildConfirmForm.

LUIS ActionBinding Param Library doesnt display if enum

If I specify as enum then it doesn't get displayed in the dialog. Can anyone help to point out if am missing some thing?
[LuisActionBinding("CollPay", FriendlyName = "Reminder")]
public class CollPayAction : BaseLuisAction
{
public enum PaymentAmtOptions
{
[Terms(new string[] { "Full Payment", "Entire Amount", "Full Due Amount" })]
FullPayment = 1,
[Terms(new string[] { "Clubbed Payment", "Combined Payment" })]
CombinedPayment
};
[Required(ErrorMessage = "Are you planning to make a separate payment or combined one?")]
[LuisActionBindingParam(CustomType = "BOPYMTOPTION", Order = 2)]
[Template(TemplateUsage.EnumSelectOne, "Are you planning to make a separate payment or combined one? {||}",
"How would you like to make the payment - separate for each Invoice(or) clubbed with other pending dues? {||}")]
public PaymentAmtOptions PaymentAmount { get; set; }
public override Task<object> FulfillAsync()
{
var result = string.Format("Hello! You have reached the CollPay intent");
return Task.FromResult((object)result);
}
}
Thanks for reporting this, it was certainly an issue. The good news is that a PR with a patch was already created.
Once the PR is approved, you will have to update your code:
-To use the updated library
-To validate the enum value. Below you will find how the code could look like:
[LuisActionBinding("CollPay", FriendlyName = "Reminder")]
public class CollPayAction : BaseLuisAction
{
public enum PaymentAmtOptions
{
None = 0, // default - no option selected
FullPayment = 1,
CombinedPayment = 2
};
// custom validator for my enum value
public class ValidPaymentAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
return value is PaymentAmtOptions && ((PaymentAmtOptions)value) != PaymentAmtOptions.None;
}
}
[ValidPayment(ErrorMessage = "Are you planning to make a separate payment [FullPayment] or combined one [CombinedPayment]?")]
[LuisActionBindingParam(CustomType = "BOPYMTOPTION", Order = 2)]
public PaymentAmtOptions PaymentAmount { get; set; }
public override Task<object> FulfillAsync()
{
var result = string.Format("Hello! You have reached the CollPay intent");
return Task.FromResult((object)result);
}
}

ViewModel class-level validation

I want to validate my View Model in class-Level .
I am using a actionFilter. How do I use a data annotation?
and how to inject the Access database?
A validation that would happen if the customer says it is already our customer or not.
I used action filter but I think it must have a way to use a DataAnnotation
Commented the code follows:
public class DadosAssinaturaFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var model = filterContext.ActionParameters.Values.FirstOrDefault(x => x.GetType() == typeof(DadosAssinatura)) as DadosAssinatura;
var modelState = filterContext.Controller.ViewData.ModelState;
if (model != null)
{
var jaSouCliente = modelState.FirstOrDefault(x => x.Key == "JaSouCliente");
if (jaSouCliente.Key != null) // select "Is Clilent" radiobutton ?
if (jaSouCliente.Value.Errors.Count > 0) // if so remove the errors of the registration data
{
modelState.RemoveKeysStartsWith("DadosCliente.");
modelState.RemoveKeysStartsWith("DadosAcesso.");
}
else if (model.JaSouCliente != null && model.JaSouCliente.Value) // else, click in "Is Client"
{
modelState.RemoveKeysStartsWith("DadosCliente."); //remove
modelState.Remove("DadosAcesso.ConfirmaSenha"); //how injec UnitOfWor/Repository? AutoFac?
if (unitOfWork.Client.GetClientByUser(model.DadosAcesso.Usuario, model.DadosAcesso.Senha) == null)//user and Password
modelState.AddModelError("DadosAcesso.Usuario", "Usuario Nao Encontrado");
}
else if (model.DadosCliente.PessoaFisica) // is a company our people?
{
modelState.Remove("DadosCliente.RazaoSocial"); // remove validate for company name
modelState.Remove("DadosCliente.Cnpj"); //the brazilian document of company
}
else modelState.Remove("DadosCliente.Cpf"); //the brazilian document of people
}
base.OnActionExecuting(filterContext);
}
}
public static class ModelStateErros
{
public static void RemoveKeysStartsWith(this ModelStateDictionary modelStateDictionary, string startsWith)
{
var keys = modelStateDictionary.Keys.Where(key => key.StartsWith(startsWith)).ToList();
foreach (var variable in keys)
{
modelStateDictionary.Remove(variable);
}
}
}
sorry my English
Simply implement IValidateableObject in your ViewModel class (or create another partial class) and avoid the filter completely, and keep your validation logic with your ViewModel.
How do I use IValidatableObject?

Creating linq expression with a subtype restriction

I have this list of type IEnumerable<MyBaseType> for which I am trying to create an extra where-clause to retrieve a specific item in the list. The specific value does only exist on subtype MyFirstType and MySecondType. Not on MyBaseType.
Is it possible to create an expression kind of...
MyList.Where(b => (b is MyFirstType || (b is MySecondType)) && b.SpecificValue == message.SpecificValue);
Above is not working since b is of type MyBaseType and SpecificValue does not exist there. Also note that I do have another subtype MyThirdType that neither has the SpecificValue.
What does work doing what I want is this...
foreach (dynamic u in MyList)
{
if (u is MyFirstType || u is MySecondType)
{
if (u.SpecificValue == message.SpecificValue)
{
//Extracted code goes here
break;
}
}
}
Anyone have an idea how to create an linq expression for the above scenario?
Maybe there is a better solution but as I see it, this could work well enough... If you don't mind performance.
Well then, start by declaring an interface:
public interface IMySpecialType
{
object SpecificValue {get; set;} //you didn't specify what type this is
//all your other relevant properties which first and second types have in common
}
Then, make MyFirstType and MySecondType derive from this interface:
public class MyFirstType : MyBaseType, IMySpecialType
{
//snipet
}
public class MyFirstType : MySecondType, IMySpecialType
{
//snipet
}
Then, filter and cast:
MyList
.Where(b => (b is MyFirstType) || (b is MySecondType))
.Cast<IMySpecialType>()
.Where(b => b.SpecificValue == message.SpecificValue);
//do something
The direct translation of your code to a Linq where clause is
string messageValue = "foo";
var result = baseList.Where(item =>
{
dynamic c = item;
if(item is MyFirstType || item is MySecondType)
{
if( c.SpecificValue == messageValue)
return true;
}
return false;
});
This will require testing the type of the class though and using dynamic - so you might as well cast item to either MyFirstType or MySecondType directly.
An alternative would be using reflection to check if the property exists, using this approach you are not dependent on the actual types of your items as long as they do have the property you are interested in:
string messageValue = "foo";
var result = baseList.Where( item =>
{
var prop = item.GetType().GetProperty("SpecificValue");
if (prop != null && prop.GetValue(item, null) == messageValue)
return true;
else return false;
});
If modifying the class hierarchy is an option you can have you MyFirstType or MySecondType implement an interface that holds the property, then you can use OfType() in your Linq query:
interface ISpecific
{
string SpecificValue { get; set; }
}
class MyFirstType : MyBase, ISpecific
{
public string SpecificValue { get; set; }
}
...
string messageValue = "foo";
var result = baseList.OfType<ISpecific>()
.Where(item => item.SpecificValue == messageValue);
A far more easy way to do that would be to create an interface to mark all your classes having this property SpecificValue. Then it's a child play :
static void Main(string[] args)
{
List<MyBaseType> MyList = new List<MyBaseType>();
ISpecificValue message = new MyFirstType();
MyList.OfType<ISpecificValue>().Where(b => b.SpecificValue == message.SpecificValue);
}
}
class MyBaseType { }
interface ISpecificValue { string SpecificValue { get; set; } }
class MyFirstType : MyBaseType, ISpecificValue
{
public string SpecificValue;
}
class MySecondType : MyBaseType, ISpecificValue
{
public string SpecificValue;
}

How to handle Focuschangelistener in blackberry for this situation?

I am having three EditField i have a set focuslistener for the second editfield alone. when the focus is lost i am checking whether the field is empty or not if the field is empty it will show the popup message .Now the problem is once the user came to that field he could not move to other fields without entering any fields but i want user can move to the field which is above to that field and he could not to move to the below field.How to handle this situation? Please share ur ideas.
I suppose it's for validation functionality?
See proposed validation strategy: we have interface IValidated which can be checked for proper data:
interface IValidated {
public boolean validate();
}
Now, any field, like list or checkbox or choice can implement it.
Next, there is onFocus event in each field, there you can validate previouse IValidated field and setFocus back if it's fail.
See EditField example:
class ValidatedEdit extends BasicEditField implements IValidated {
private static final String EMPTY_STRING = "";
public ValidatedEdit(String label, String value) {
super(label, value);
}
protected void onFocus(int direction) {
// it's from upper field
if (direction > 0 && getIndex() > 0) {
// get upper field
Field field = getManager().getField(getIndex() - 1);
// if its IValidated
if (field instanceof IValidated) {
IValidated validated = (IValidated) field;
// validate, if false set focus to IValidated
if (!validated.validate()) {
field.setFocus();
return;
}
}
}
super.onFocus(direction);
}
public boolean validate() {
return !getText().equalsIgnoreCase(EMPTY_STRING);
}
}
Example of use:
class Scr extends MainScreen {
ValidatedEdit mEditField1 = new ValidatedEdit("field#1", "");
ValidatedEdit mEditField2 = new ValidatedEdit("field#2", "");
ValidatedEdit mEditField3 = new ValidatedEdit("field#3", "");
public Scr() {
add(mEditField1);
add(mEditField2);
add(mEditField3);
}
}

Resources