Reputation: 1
In C #, I defined a class called ( Utility ) in which I defined a set of functions that I can use inside the program.
I defined an email template check function that's apparently grammatically fine. If I use the extension ( .com ) in the program, it is not a problem, but we get into trouble when we use an extension other than ( .com ). In this case, it is not possible to leave our control box. Can you help me figure out what the problem is?
private static string[] formatEmail = new string[4];
public static void CheckFormatEmail(System.Windows.Forms.TextBox textBox,
System.Windows.Forms.ErrorProvider errorProvider)
{
formatEmail[0] = ".com";
formatEmail[1] = ".org";
formatEmail[2] = ".ir";
formatEmail[3] = ".net";
int indexChar = 0;
int lenght = 0;
string subString = null;
string suffix = null;
if ((textBox.Text).Contains("@"))
{
for (int i = 0; i < formatEmail.Length; i++)
{
if (!textBox.Text.EndsWith(formatEmail[i]))
{
textBox.Focus();
textBox.BackColor = System.Drawing.Color.FromArgb(252, 91, 91);
errorProvider.SetError(textBox, "وارد كنيد" + "** [email protected] **" + "لطفا ايميل را در قالب");
}
else
{
suffix = formatEmail[i];
indexChar = textBox.Text.LastIndexOf('@');
if (string.Compare(suffix, ".ir") == 0)
{
lenght = (textBox.Text.Length - indexChar) - 3;
subString = textBox.Text.Substring(indexChar, lenght);
if (!string.IsNullOrWhiteSpace(subString.Remove(0, 1)))
{
textBox.BackColor = System.Drawing.SystemColors.Window;
errorProvider.Clear();
;
}
else
{
textBox.BackColor = System.Drawing.Color.FromArgb(252, 91, 91);
errorProvider.SetError(textBox, "وارد كنيد" + "** [email protected] **" + "لطفا ايميل را در قالب");
textBox.Focus();
break;
}
}
else
{
lenght = (textBox.Text.Length - indexChar) - 4;
subString = textBox.Text.Substring(indexChar, lenght);
if (!string.IsNullOrWhiteSpace(subString.Remove(0, 1)))
{
textBox.BackColor = System.Drawing.SystemColors.Window;
errorProvider.Clear();
return;
}
else
{
textBox.BackColor = System.Drawing.Color.FromArgb(252, 91, 91);
errorProvider.SetError(textBox, "وارد كنيد" + "** [email protected] **" + "لطفا ايميل را در قالب");
textBox.Focus();
break;
}
}
}
}
}
else
{
textBox.Focus();
textBox.BackColor = System.Drawing.Color.FromArgb(252, 91, 91);
errorProvider.SetError(textBox, "وارد كنيد" + "** [email protected] **" + "لطفا ايميل را در قالب");
return;
}
}
Upvotes: 0
Views: 132
Reputation: 155145
Rather than try to fix your code, I'll say that you're doing it wrong at a fundamental level by reimplementing your own e-mail address validation logic - which is already a solved problem with countless of solutions.
So don't reinvent the wheel, just do this:
using System;
using System.ComponentModel.DataAnnotations;
using System.Net.Mail;
using System.Windows.Forms;
public static class MyValidationMethods
{
public static void ValidateEmailAddressTextBox( TextBox textBox, ErrorProvider err, Boolean focusOnError )
{
if( textBox is null ) throw new ArgumentNullException(nameof(textBox));
if( err is null ) throw new ArgumentNullException(nameof(err));
//
if( TryValidateEmailAddress( textBox.Text, out MailAddress? addr ) )
{
err.SetError( textBox, "" ); // Don't use `Clear()` for a single control, instead use `SetError()` with an empty message.
String dnsHostName = addr.Host;
String[] dnsLabels = dnsHostName.Split('.');
// TODO: If you really want to filter or restrict e-mail DNS names then you can do that here by doing case-insensitive matches on the last 2 or 3 elements in `dnsLabels`.
}
else
{
err.SetError( textBox, "\"${textBox.Text}\" is not a valid e-mail address." );
if( focusOnError ) textBox.Focus();
}
}
// NOTE: If you're targeting .NET Core or later (e.g. .NET 5, .NET 6, etc) then be-aware that `EmailAddressAttribute` was changed to only perform very simplistic (almost useless!) validation instead of using its previously stricter regex.
// * See:
// * https://github.com/dotnet/corefx/pull/4319
// * https://github.com/dotnet/runtime/issues/20884
// * However this code below (in `TryValidateEmailAddress`) still okay on .NET 5+ because the `MailAddress` constructor still performs its own (unchanged) validation and will throw an exception (which is instantly caught).
// * Though it *does* accept e-mail address strings with a display-name component, e.g. `"Something" <username@host>"`.
// * If you want to disallow that then a quick-fix is to reject the string if it contains double-quotes. This is included in the code below within the `#if NET5_0_OR_GREATER` code.
// * There are limited scenarios where double-quotes are valid in an RFC email-address without a display-name, but they're esoteric and not worth handling, imo.
private static readonly EmailAddressAttribute _validator = new EmailAddressAttribute();
private static Boolean TryValidateEmailAddress( String inputEmailAddress, [NotNullWhen(true)] out MailAddress? addr )
{
#if NET5_0_OR_GREATER
if( _validator.IsValid( inputEmailAddress ) && !inputEmailAddress.Contains('"') )
#else
if( _validator.IsValid( inputEmailAddress ) )
#endif
{
try
{
addr = new MailAddress( inputEmailAddress );
return true;
}
catch( Exception ex ) when ( ex is ArgumentException || ex is FormatException )
{
}
}
addr = null;
return false;
}
}
I made the .Focus()
call conditional via the Boolean focusOnError
method parameter so you can validate multiple controls at-once without needing to .Focus()
on a single specific control.
For as usage example, I assume you have a method to validate all controls-at-once (ValidateEverything
below), in addition to a [Control.Validatingevent-handler][1] named
EmailAddressTextBox_Validating, and that your
ErrorProvidercontrol is named
formErrors`) and represents errors for multiple controls instead of just 1.
public partial class MyForm : Form
{
private TextBox firstEmailInputTextBox;
private TextBox anotherEmailInputTextBox;
private ErrorProvider formErrors;
// [...]
// Uses `focusOnError: true`:
private void EmailAddressTextBox_Validating( Object sender, CancelEventArgs e )
{
TextBox tb = (TextBox)sender;
MyValidationMethods.ValidateEmailAddressTextBox( tb, this.formErrors, focusOnError: true );
}
// Uses `focusOnError: false` to avoid breaking the UX:
private void ValidateEverything()
{
MyValidationMethods.ValidateEmailAddressTextBox( this.firstEmailInputTextBox, this.formErrors, focusOnError: false );
MyValidationMethods.ValidateEmailAddressTextBox( this.anotherEmailInputTextBox, this.formErrors, focusOnError: false);
}
}
As for why you're having issues with .Focus()
, it's because you're inconsistently mixing break
and return
inconsistently - but if you simplify your logic (as done in my answer) it removes the problem entirely.
Upvotes: 1