Foreach loop only validates first element - c#

I'm validating TextFields with a foreach loop with an if/else statement inside. This all happens inside a public virtual Boolean Method(). Only the first element is validated and I don't know why the rest is not validated.
How do I have to change my method so it will validate all the items in TextFieldList?
This is my method:
public virtual Boolean ValidateTextFields(){
foreach (UITextField item in TextFieldList) {
if (item.Text == "") {
item.AttributedPlaceholder = new NSAttributedString (item.Placeholder, foregroundColor: UIColor.Red);
return false;
} else {
return true;
}
}
return true;
}
EDIT:
I got it working but now I have another issue, I have multiple methods like ValidateTextFields and I check them like this:
if (ValidateTextFields() && ValidateEmail() ) {
Console.WriteLine ("CONTINUE TO NEXT SCREEN");
} else {
Console.WriteLine ("ERRORRRRRR");
}
Now if ValidateTextFields() is false then ValidateEmail() is never called so the EmailTextFields won't be validated. Only after ValidateTextFields() is true I can validate ValidateEmail(). Is there a way to call both methods at the same time and check if they are true?

Try this:
If have any invalid field the Method returns false, else if all fields is valid returns true.
public virtual Boolean ValidateTextFields(){
foreach (UITextField item in TextFieldList) {
if (item.Text == "") {
item.AttributedPlaceholder = new NSAttributedString (item.Placeholder, foregroundColor: UIColor.Red);
return false;
}
}
return true;
}
Or you can valid all itens to put a attributedplaceholder for each item and returns if has any invalid, like this:
public virtual Boolean ValidateTextFields(){
bool hasInvalidFields = false;
foreach (UITextField item in TextFieldList) {
if (item.Text == "") {
item.AttributedPlaceholder = new NSAttributedString (item.Placeholder, foregroundColor: UIColor.Red);
hasInvalidFields = true;
}
}
return !hasInvalidFields;
}
For your edit, to call all validates you can:
bool validTextFields = ValidateTextFields();
bool validEmails = ValidateEmail();
if ( validTextFields && validEmails) {
Console.WriteLine ("CONTINUE TO NEXT SCREEN");
} else {
Console.WriteLine ("ERRORRRRRR");
}

Your code will always return after the first element has been processed, whether it's valid or not.
What you probably want instead is to validate all elements and return afterwards:
var result = true;
foreach (UITextField item in TextFieldList) {
if (item.Text == "") {
item.AttributedPlaceholder =
new NSAttributedString (item.Placeholder, foregroundColor: UIColor.Red);
result = false;
}
}
return result;
You simply need to remember what to return in the end instead of returning immediately.

Related

How to remove items from Ilist

I have an IList , I also have a method which checks if the item is already in list and if it is I need it to be deleted/ removed and add again.
private PurchaseItemViewModel CheckSessionPurchaseItemViewModel(long purchaseLevelId)
{
bool itemFound = false;
PurchaseItemViewModel purItem = new PurchaseItemViewModel();
foreach (var item in UserSession.UserDataPurchaseItems)
{
if (item.PurchaseLevelId == purchaseLevelId)
{
itemFound = true;
purItem.Note = item.Note;
purItem.PurchaseAmount = item.PurchaseAmount;
purItem.PurchaseLevelId = item.PurchaseLevelId;
}
}
if (itemFound)
{
return purItem;
}
return null;
}
If it the above method finds the purchase item then it returns an object else null.
IList<PurchaseItemViewModel> purchaseSessionList = UserSession.UserDataPurchaseItems;
PurchaseItemViewModel pItem = CheckSessionPurchaseItemViewModel(levelId);
if(pItem != null)
{
purchaseSessionList.Remove(item);
}
So the issue is with the below line it is not removing the item , it does not even error.
**purchaseSessionList.Remove(item);**
Use this code for removing:
if(pItem != null) purchaseSessionList.Remove( purchaseSessionList.SingleOrDefault( s => s.PurchaseLevelId== levelId) );
IMHO you don't need to create pItem, would be enough to return false or true or item primary key.

Issue with chaining Required Field and Regular Expression validators for Textbox controls

I'm trying to implement a form validation with ASP.net and I have tried every solution suggested here but the best one was on aspsnippets.com so far.
My code is like below:
<asp:TextBox ID="tTitle" runat="server" onblur="WebForm_OnBlur()"/>
<asp:RequiredFieldValidator runat="server" ControlToValidate="tTitle"/>
<asp:TextBox ID="tEMail" runat="server" onblur="WebForm_OnBlur()"/>
<asp:RequiredFieldValidator runat="server" ControlToValidate="tEMail"/>
<asp:RegularExpressionValidator runat="server" ControlToValidate="tEMail"
ValidationExpression="\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*"/>
<asp:LinkButton ID="btnSubmit" runat="server" Text="Submit"/>
Javascript
<script type="text/javascript">
function WebForm_OnSubmit() {
if (typeof (ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false)
{
for (var i in Page_Validators) {
try {
var control =
document.getElementById(Page_Validators[i].controltovalidate);
if (!Page_Validators[i].isvalid) {
control.className = "error";
} else {
control.className = "";
}
} catch (e) { }
} return false;
} return true;
}
function WebForm_OnBlur() {
for (var i in Page_Validators) {
try {
var control =
document.getElementById(Page_Validators[i].controltovalidate);
if (!Page_Validators[i].isvalid) {
control.className = "error";
} else {
control.className = "";
}
} catch (e) { }
} return false;
}
</script>
The problem is the e-mail field only validates for the regular expression. If I change the order of the validators, it only validates for required expression.
The possible problem is that the code loops through all the validators but does not compare the ones that reference the same control at once. This causes only the last validator condition to be applied on the control.
The possible problem is that the code loops through all the validators but does not compare the ones that reference the same control at once. This causes only the last validator condition to be applied on the control.
Yes, this is indeed the problem. To fix it, you can do the following:
In the WebForm_OnBlur function, loop through the validators associated with the control that lost focus (rather than all the validators on the page), and clear the className property only if all the validators are valid:
function WebForm_OnBlur(control) {
for (var i = 0; i < control.Validators.length; i++) {
if (!control.Validators[i].isvalid) {
control.className = "error";
return;
}
}
control.className = "";
}
In the onblur attribute of the TextBox controls, pass this as the argument to WebForm_OnBlur:
<asp:TextBox ID="tTitle" runat="server" onblur="WebForm_OnBlur(this)"/>
<asp:TextBox ID="tEMail" runat="server" onblur="WebForm_OnBlur(this)"/>
In the WebForm_OnSubmit function, call WebForm_OnBlur for each control that has associated validators:
function WebForm_OnSubmit() {
if (typeof(ValidatorOnSubmit) === "function" && ValidatorOnSubmit() === false) {
for (var i = 0; i < Page_Validators.length; i++) {
var control = document.getElementById(Page_Validators[i].controltovalidate);
if (Page_Validators[i] === control.Validators[0]) // minor optimization
WebForm_OnBlur(control);
}
return false;
}
return true;
}
In addition to #MichaelLiu, You can make your own validators that inherit from the CustomValidator class and alter the rendering of the validators to make them a little easier to work with.
For example:
Validators.cs
Take notice of how we add a property of CssControlErrorClass. We will use this when applying a class with the invalid input in question.
We also set other properties so you don't have to set them everytime, ClientValidationFunction and ValidateEmptyText.
public class RequiredFieldValidator : CustomValidator
{
public string CssControlErrorClass { get; set; }
public RequiredFieldValidator()
{
ClientValidationFunction = "validators.required";
ValidateEmptyText = true;
}
public string InitialValue
{
get
{
object o = ViewState["InitialValue"];
return ((o == null) ? String.Empty : (string)o);
}
set
{
ViewState["InitialValue"] = value;
}
}
protected override void Render(HtmlTextWriter writer)
{
//Have to add attributes BEFORE the beginning tag is written to the stream
writer.AddAttribute("data-errorClass", CssControlErrorClass);
writer.AddAttribute("data-for", GetControlRenderID(ControlToValidate));
base.Render(writer);
}
protected override bool EvaluateIsValid()
{
//Default implementation of the RequiredFieldValidation validator
string controlValue = GetControlValidationValue(ControlToValidate);
if (controlValue == null)
{
return true;
}
var result = (!controlValue.Trim().Equals(InitialValue.Trim()));
//Check to see if validation failed, if it did, add the class to the control to validate
if (!result)
{
var control = (WebControl) NamingContainer.FindControl(ControlToValidate);
//Didn't look into it too much, but the validators fire twice for some reason
if(!control.CssClass.Contains(CssControlErrorClass)) control.CssClass += " " + CssControlErrorClass;
}
return result;
}
}
public class RegularExpressionValidator : CustomValidator
{
public string CssControlErrorClass { get; set; }
public string ValidationExpression
{
get
{
object o = ViewState["ValidationExpression"];
return ((o == null) ? String.Empty : (string)o);
}
set
{
try
{
Regex.IsMatch(String.Empty, value);
}
catch (Exception e)
{
throw new HttpException(string.Format("{0} - {1}", "Validator_bad_regex", value), e);
}
ViewState["ValidationExpression"] = value;
}
}
public RegularExpressionValidator()
{
ClientValidationFunction = "validators.regex";
}
protected override void Render(HtmlTextWriter writer)
{
//Have to add attributes BEFORE the beginning tag is written to the stream
writer.AddAttribute("data-errorClass", CssControlErrorClass);
writer.AddAttribute("data-regex", ValidationExpression);
writer.AddAttribute("data-for", GetControlRenderID(ControlToValidate));
base.Render(writer);
}
protected override bool EvaluateIsValid()
{
//Default implementation of the RegularExpressionFieldvalidator
string controlValue = GetControlValidationValue(ControlToValidate);
if (controlValue == null || controlValue.Trim().Length == 0)
{
return true;
}
try
{
Match m = Regex.Match(controlValue, ValidationExpression);
var result = (m.Success && m.Index == 0 && m.Length == controlValue.Length);
//Check to see if validation failed, if it did, add the class to the control to validate
if (!result)
{
var control = (WebControl) NamingContainer.FindControl(ControlToValidate);
//Didn't look into it too much, but the validators fire twice for some reason
if (!control.CssClass.Contains(CssControlErrorClass)) control.CssClass += " " + CssControlErrorClass;
}
return result;
}
catch
{
return true;
}
}
}
Validators.js
Since in the previous classes we pre-defined the javascript functions, we can add a simple script like so:
var v = window.validators = window.validators || {
errorControlAttributeName: "data-for",
errorClassAttributeName: "data-errorClass",
regexAttributeName: "data-regex",
required: function(src, args) {
var controlId = src.getAttribute(v.errorControlAttributeName),
errorClass = src.getAttribute(v.errorClassAttributeName),
input = document.getElementById(controlId);
var isValid = (args.Value !== "");
v._toggleInputErrorState(input, errorClass, isValid);
args.IsValid = isValid;
return;
},
regex: function(src, args) {
var controlId = src.getAttribute(v.errorControlAttributeName),
errorClass = src.getAttribute(v.errorClassAttributeName),
regexString = src.getAttribute(v.regexAttributeName),
input = document.getElementById(controlId),
regex = new RegExp(regexString);
var isValid = regex.test(args.Value);
v._toggleInputErrorState(input, errorClass, isValid);
args.IsValid = isValid;
return;
},
/************* Helper functions ***********/
_toggleInputErrorState: function (inputEl, errorClass, isValid) {
if (!isValid) {
if (!v._hasClass(inputEl, errorClass)) {
inputEl.className += " " + errorClass;
}
} else {
if (v._hasClass(inputEl, errorClass)) {
//Not the most performant, but is sure is easiest
inputEl.className = inputEl.className.replace(" " + errorClass, "");
}
}
},
_hasClass: function(el, className) {
return el.className.indexOf(className) != -1 ? true : false;
},
}
Very simple validation library that you can easily extend with things you are actually interesting in.
Default.aspx
After than you can put the controls into your page:
<Validators:RequiredFieldValidator runat="server" CssControlErrorClass="input-validation-error" ControlToValidate="Test" ErrorMessage="REQUIRED BRO!"></Validators:RequiredFieldValidator>
<Validators:RegularExpressionValidator runat="server" ValidationExpression="[0-9]" CssControlErrorClass="input-validation-error" ControlToValidate="Test" ErrorMessage="REQUIRED RegEx BRO!"></Validators:RegularExpressionValidator>
Is this the best way? Probably not, (these two use the default implementation that is given by Microsoft) there are way smarter people out there than I and I don't work with WebForms much. The biggest benefit I see is that you get some reusable code, using a familiar syntax, that will eventually contain all your validation needs versus messing around with js everytime to get the validation "rules" how you want them.
The issue is resolved by replacing the code snippet below. To correct we must loop through all the validators for a control, then we should decide whether it has to marked with the error class. After this, your code will work as expected.
Replace the loop
for (var i in Page_Validators) {
try {
var control =
document.getElementById(Page_Validators[i].controltovalidate);
if (!Page_Validators[i].isvalid) {
control.className = "error";
} else {
control.className = "";
}
} catch (e) { }
}
with the below code
for (var j in Page_Validators) {
try {
var control =
document.getElementById(Page_Validators[j].controltovalidate);
var IsError = false;
for (var i in control.Validators) {
if (!control.Validators[i].isvalid) {
IsError = true;
}
}
if (IsError)
control.className = "error";
else
control.className = "";
} catch (e) { }
}
I just ran it and this is working excellently :) Try this solution!
you can try Page_ClientValidate() in javascript instead of looping across validator.
I believe this will validate all the validators on the page.
It also takes in parameter which "Validation group name" if you want to validate specific controls bound by particular validation group.

How to fix a boolean method that returns true everytime asp.net

I designed my webpage to read a data string then display the results on labels in an html table. I am attempting to highlight the row that my database reads as a current order. My only problem is only one record is set to be active but they all highlight as if they were active. I use an array to set my data and I also use the label to get the ID I need (all is in code below). I have posted my method and where I use it in the asp page load. How can I fix my method to return correctly?
The implementing of the method in page load
if (lineData.IsCurrentOrderFind(L68.Text))
{
myTable.Rows[1].Cells[0].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[1].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[2].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[3].BgColor = "#FE2E2E";
myTable.Rows[1].Cells[4].BgColor = "#FE2E2E";
}
Here is method that label above gets passed to
public bool IsCurrentOrderFind(string itemNumber)
{
StringBuilder sqlString = new StringBuilder();
sqlString.Append("SELECT * ");
sqlString.Append("FROM WorkOrder ");
sqlString.Append("WHERE LineNumber = " + ConfigurationManager.AppSettings["Line"] + " AND LineCompleted = 0 AND (ScaleGroup LIKE '%1' OR ScaleGroup LIKE '%3') ");
sqlString.Append(" AND CaseGenNum6 = #CaseGenNum6");
SqlDataReader reader = null;
SqlConnection dbConn = App_Code.DBHelper.getConnection();
SqlParameter[] parameters = new SqlParameter[] { new SqlParameter("#CaseGenNum6", itemNumber) };
try
{
reader = App_Code.DBHelper.executeQuery(dbConn, sqlString.ToString(), parameters);
while (reader.Read())
{
IsCurrentOrder = (reader["IsCurrentOrder"] != DBNull.Value && !string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString())) ? true : false;
}
reader.Close();
reader.Dispose();
dbConn.Close();
dbConn.Dispose();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (dbConn != null)
{
try { dbConn.Close(); dbConn.Dispose(); }
catch { }
}
if (reader != null)
{
try { reader.Close(); reader.Dispose(); }
catch { }
}
}
if (IsCurrentOrder == true) I realize this is not necessary
{
return true;
}
else
{
return false;
}
}
The problem could be with this expression:
!string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString())
Instead of calling ToString(), try simply casting it to a string:
!string.IsNullOrEmpty((string)reader["IsCurrentOrder"])
Possibly even better (the previous line might throw an exception if it's not really a string):
!string.IsNullOrEmpty(reader["IsCurrentOrder"] as string)
The reason being is that if the string is really null, calling ToString() will return a non-null string "null".
IsCurrentOrder is not declared locally. It seems to be declared at a higher scope. When you enter this function, nothing is initializing the variable (back to false). So, it is remaining at its last setting. Try this code instead:
public bool IsCurrentOrderFind(string itemNumber)
{
bool IsCurrentOrder = false;
//and the rest of your source code
the line
IsCurrentOrder = (reader["IsCurrentOrder"] != DBNull.Value && !string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString())) ? true : false;
}
It's not actually checking the value of the field, only that it's not null or empty.
Try
if(
(reader["IsCurrentOrder"] != DBNull.Value
&&
!string.IsNullOrEmpty(reader["IsCurrentOrder"].ToString()))
)
{
IsCurrentOrder = reader["IsCurrentOrder"];
}
else
IsCurrentOrder = false;
I think there is a lot of refactoring you could do to this method though that will simplify the logic.

Callback URL matching logic

I am working on an OAuth type module. In this i have a collection of URLs which are called as Whitelist URLs. I have to check whether the callback URL specified matches with any of these URLs in the collection.
I've written the following code. Please let me know whether i've done it correctly or am i missing some steps. Also, please let me know if i need any kind of refactoring if i want to unit test these methods.
The code is:
public class ValidateURLs
{
public bool MatchRedirectUrl(string requestUrl, IList<string> urlCollection)
{
var requestUri = new Uri(requestUrl);
foreach (var url in urlCollection)
{
var matchUri = new Uri(url);
if (IsDomainMatching(requestUri, matchUri))
{
if (IsPortMatch(requestUri, matchUri))
{
if (IsPathMatch(requestUri, matchUri))
return true;
else
return false;
}
}
}
return false;
}
private bool IsDomainMatching(Uri url1, Uri url2)
{
var result = String.Compare(url1.Host, url2.Host);
if (result == 0)
return true;
else
return false;
}
private bool IsPortMatch(Uri url1, Uri url2)
{
if (url1.Port == url2.Port)
return true;
return false;
}
private bool IsPathMatch(Uri url1, Uri url2)
{
return (url1.PathAndQuery.StartsWith(url2.PathAndQuery) || url2.PathAndQuery.StartsWith(url1.PathAndQuery));
}
}
Thanks in advance.
Regards,
Suyog
Instead of writing all this code, you should look at Uri.Compare
But you also want path.startswith to be part of the comparison. Notice it takes a bitwise enum UriComponents to define which components of the url to compare. So you could replace much of the code with Uri.Compare not comparing path and then have a startsWith path ANDed.
So all your code could be replaced with something like:
Uri.Compare(uri1, uri2, UriComponents.HostAndPort, ...) == 0 &&
(url1.PathAndQueryStartsWith(url2.PathAndQuery) || url.PathAndQueryStartsWith(...));
On a side note, code in this form:
var result = String.Compare(url1.Host, url2.Host);
if (result == 0)
return true;
else
return false;
Can simply be written as:
return String.Compare(url1.Host, url2.Host) == 0;
You should also do case insensitive compares with: StringComparison.OrdinalIgnoreCase

error telling not all code paths return a value

Iwrote a c# code and it seemed correct for me
public static BCSMappedTable GetMappedTable(string p_ListName)
{
List<BCSDataBase> ConnexionList = BCSManagement.GetAllDataBases();
bool found = false;
foreach (BCSDataBase connexion in ConnexionList)
{
foreach (BCSMappedTable tabList in connexion.GetMappedTables())
{
if (tabList.getListeName().Equals(p_ListName))
{
found = true;
return tabList;
}
}
}
if (found)
return new BCSMappedTable();
}
but this error keeps appearing
error : not all code paths return a value
and I don't have a clue why ! I lean I always return the required value
At the end of the function, if found is false, you don't have a return path...
As you have a return statement inside your loop, the function will exit as soon as the item is found, thus you don't need the found variable. You can go with something like:
public static BCSMappedTable GetMappedTable(string p_ListName)
{
List<BCSDataBase> ConnexionList = BCSManagement.GetAllDataBases();
foreach (BCSDataBase connexion in ConnexionList)
{
foreach (BCSMappedTable tabList in connexion.GetMappedTables())
{
if (tabList.getListeName().Equals(p_ListName))
{
// return as soon as the item is found
return tabList;
}
}
}
// this code won't be executed if the item was found before...
return new BCSMappedTable();
}
because at the end you have
if (found)
return new BCSMappedTable();
what if it wasnt found?
Thing is, it wouldnt get there because when found was set to true, you returned from the function - so, also, all this needs to say is
return new BCSMappedTable();
public static BCSMappedTable GetMappedTable(string p_ListName)
{
List<BCSDataBase> ConnexionList = BCSManagement.GetAllDataBases();
bool found = false;
foreach (BCSDataBase connexion in ConnexionList)
{
foreach (BCSMappedTable tabList in connexion.GetMappedTables())
{
if (tabList.getListeName().Equals(p_ListName))
{
found = true;
return tabList;
}
}
}
if (!found)
return new BCSMappedTable();
}
implement else part of
if (found)
return new BCSMappedTable();
else
return tablist1;//or something else
In your code you have:
found = true;
return tabList;
There is no point setting a value to a local variable and then returning directly after it, as this variable will not be used. return basically exits the method with the value you are returning (which should match the type of your method).
As the error states, not all paths return a value. If found==false there will be no return value.
try this
public static BCSMappedTable GetMappedTable(string p_ListName)
{
List<BCSDataBase> ConnexionList = BCSManagement.GetAllDataBases();
bool found = false;
foreach (BCSDataBase connexion in ConnexionList)
{
foreach (BCSMappedTable tabList in connexion.GetMappedTables())
{
if (tabList.getListeName().Equals(p_ListName))
{
found = true;
return tabList;
}
}
}
if (found)
{
return new BCSMappedTable();
}
return found;
}

Categories

Resources