IF-IF-Else doesn't work as I need and want - c#

I need to know how I could handle my problem in a efficient and smart way:
I want an error-handling for user's input; I have 2 fields CustomerID and Company:
if (customerIDExists)
{
errorMessage = "...";
}
if (companyInvalid)
{
errorMessage = "...";
}
else
{
// Add user to DB
}
There could be 3 errors:
CustomerID already exists
Company has an invalid name
CustomerID AND Company is invalid at the same time
With the example above the else is for the last if (companyInvalid). How can I deal with the else that this only executes when the 1 and 2 if doesn't match?
Else if is not right because I have to check all opportunities.

Well, you could make it very explicit:
if (customerIDExists)
{
...
}
if (companyInvalid)
{
...
}
if (!customerIDExists && !companyInvalid)
{
// Add user to DB
}
Or just use the fact that you haven't got an error message:
string errorMessage = null;
if (customerIDExists)
{
errorMessage = ...;
}
if (companyInvalid)
{
errorMessage = ...; // Don't forget it could already be non-null!
}
if (errorMessage == null)
{
// No error message, so we must be fine
// Add user to DB
}

If I understand your problem the else will fire if customerIDExists is true.
Try this
if(customerIDExists)
{
errorMessage = "...";
}
else if(companyInvalid)
{
errorMessage = "...";
}
else
{
// Add user to DB
}
I've added an else if to the second condition. Now your application will check if the customerIDExists, if it doesn't it will check if the companyInvalid if it doesn't it will add the user to the database.
Now, what happens if both of these are incorrect? You'll only present on error message to your user, this will be annoying when they fix that issue and discover they have another you didn't tell them about! My suggestion would be to use a list of errors, if there aren't any then save to the database:
var errors = new List<string>();
if(customerIDExists)
{
errors.Add("Customer exists");
}
if(companyInvalid)
{
errors.Add("Company invalid");
}
if(!errors.Any())
{
// Add user to DB
}
return errors;

You can use a variable:
bool isValid = true;
if(customerIDExists)
{
errorMessage = "...";
isValid = false;
}
if(companyInvalid)
{
errorMessage = "...";
isValid = false;
}
if(isValid)
{
// Add user to DB
}

You can try old technique:
do {
if(customerIDExists)
{
errorMessage = "...";
break;
}
if(companyInvalid)
{
errorMessage = "...";
break;
}
// All is ok.
} while (false);

If you want to show all messages and don't break the proof after first error, you could use something like this:
List<string> errorMessages = new List<string>();
if (customerIDExists)
{
errorMessages.Add("...");
}
if (companyInvalid)
{
errorMessages.Add("...");
}
if (errorMessages.Count == 0) //Valid
{
}
else //Invalid
{
}

I assume you'd want to report all errors, not just the first that's encountered.
var errors = new List<string>();
if (customerIDExists)
{
errors.Add("customer id exists");
}
if (companyInvalid)
{
errors.Add("company is invalid");
}
if(errors.Any())
{
// display all error messages
}
else
{
// Add user to DB
}

Related

C# use field 1 value if field 2 empty

I am running through a set of records using a for each loop, and also doing simple checks to ensure that good data is inserted into a database table.
Sometimes the dataset can be missing the LegistarID value, the change I need to do in my code, is to add a check for LegistarItem,
if the value of LegistarID is missing, but the AgendaItem value is not, then assign the value of AgendaItem to LegistarID
if LegistarId is missing, and there is also no AgendaItem value, then return a message to the user, to let them know that these values need to be present in the dataset they are trying to import.
I know it does not sound complex, but I am having a hard time making this change successfully. I need a bit of help if possible, please.
Here is my code as I currently have it:
if (ModelState.IsValid)
{
using (Etities db = new Entities())
{
foreach (var i in meeting)
{
if (i.MeetingID == 0)
{
message = string.Format("This file is missing the Meeting ID value of at least 1 record. \n Verify that the data you are trying to upload meets the criteria, and then try to upload your file again.", i.MeetingID);
return new JsonResult { Data = new { status = status, message = message } };
}
else
{
// development
var compositeKey = db.MeetingAgenda.Find(i.MeetingID, i.AgendaItem);
if (compositeKey == null)
{
// Add new
// development
db.MeetingAgenda.Add(i);
//
}
else
{
// Serves as an update, or addition of a previously imported dataset
db.Entry(compositeKey).CurrentValues.SetValues(i.MeetingID);
db.Entry(compositeKey).State = EntityState.Modified;
}
}
}
db.SaveChanges();
status = true;
}
}
else
{
message = string.Format("Please, verify that the file you are trying to upload is correctly formatted, and that the data it contains, meets the expected criteria, then click the upload button again. \n Thank you!");
return new JsonResult { Data = new { status = status, message = message } };
}
I think that part of the code I need is something like this:
else if (i.LegistarID == 0 and i.AgendaItem != 0)
{
i.LegistarID = i.AgendaItem
}
I just am unsure how in the current code place it.
I would check all rows before returning a result.
if (ModelState.IsValid) {
var errors = new List<string> ();
var rowCounter = 1;
using (Etities db = new Entities ()) {
foreach (var i in meeting) {
if (i.MeetingID == 0) {
// Let the user know this row is bad
errors.Add ($"Row {rowCounter}: This file is missing the Meeting ID. Verify that the data you are trying to upload meets the criteria, and then try to upload your file again.");
}
// Check if LegistarID is missing
if (i.LegistarID == 0) {
// Check if Agenda Item is present
if (i.AgendaItem == 0) {
errors.Add ($"Row {rowCounter}: Meeting has no LegistarID and no Agenda Item. Please check data");
} else {
i.LegistarID = i.AgendaItem
}
}
// development
var compositeKey = db.MeetingAgenda.Find (i.MeetingID, i.AgendaItem);
if (compositeKey == null) {
// Add new
// development
db.MeetingAgenda.Add (i);
//
} else {
// Serves as an update, or addition of a previously imported dataset
db.Entry (compositeKey).CurrentValues.SetValues (i.MeetingID);
db.Entry (compositeKey).State = EntityState.Modified;
}
rowCounter++;
}
// If there are errors do not save and return error message
if (errors.Count > 0) {
return new JsonResult { Data = new { status = false, message = string.Join ("\n", errors) } };
}
db.SaveChanges ();
status = true;
}
} else {
message = string.Format ("Please, verify that the file you are trying to upload is correctly formatted, and that the data it contains, meets the expected criteria, then click the upload button again. \n Thank you!");
return new JsonResult { Data = new { status = status, message = message } };
}
The "if(i.MeetingID == 0)" else is redundant, because you are returning if the condition is met. So to avoid unneeded/confusing nesting I would rewrite the actual code (of the loop only) as:
foreach (var i in meeting)
{
if (i.MeetingID == 0)
{
message = string.Format("This file is missing the Meeting ID value of at least 1 record. \n Verify that the data you are trying to upload meets the criteria, and then try to upload your file again.", i.MeetingID);
return new JsonResult { Data = new { status = status, message = message } };
}
// development
var compositeKey = db.MeetingAgenda.Find(i.MeetingID, i.AgendaItem);
if (compositeKey == null)
{
// Add new
// development
db.MeetingAgenda.Add(i);
//
}
else
{
// Serves as an update, or addition of a previously imported dataset
db.Entry(compositeKey).CurrentValues.SetValues(i.MeetingID);
db.Entry(compositeKey).State = EntityState.Modified;
}
}
Then, I would add the new condition in between the MeetingID = 0 check and the rest of the code, like this:
foreach (var i in meeting)
{
if (i.MeetingID == 0)
{
message = string.Format("This file is missing the Meeting ID value of at least 1 record. \n Verify that the data you are trying to upload meets the criteria, and then try to upload your file again.", i.MeetingID);
return new JsonResult { Data = new { status = status, message = message } };
}
// *** New check on LegistarID and AgendaItem ***
if(i.LegistarID == 0)
{
// Is there a chance to fill LegistarID with AgendaItem?
if(i.AgendaItem != 0)
{
// Yes, fill it and then let the rest of the code flow peacefully.
i.LegistarID = i.AgendaItem
}
else
{
// No way: I must stop the procedure here and warn the user about this.
// return "these values need to be present in the dataset they are trying to import."
}
}
// development
var compositeKey = db.MeetingAgenda.Find(i.MeetingID, i.AgendaItem);
if (compositeKey == null)
{
// Add new
// development
db.MeetingAgenda.Add(i);
//
}
else
{
// Serves as an update, or addition of a previously imported dataset
db.Entry(compositeKey).CurrentValues.SetValues(i.MeetingID);
db.Entry(compositeKey).State = EntityState.Modified;
}
}

In app billing plugin fails on Xamarin.Android with a vague error message ("Something went wrong on our end. Please try again")

When using James Montemagno's In App Billing Plugin for Xamarin.Android, a vague error message appears at the purchase screen when attempting to purchase products from Google Play:
Something went wrong on our end. Please try again
I am more or less completely using sample code from the plugin's documentation. The plugin works fine with reserved billing IDs for testing, such as android.test.purchased. This support forum states that the issue is due to "existing security measures", which is not particularly clear- https://forums.xamarin.com/discussion/153166/in-app-purchase-error-something-went-wrong-on-our-end-please-try-again.
The error code that results is Plugin.InAppBilling.Abstractions.PurchaseError.UserCancelled.
Here is the code for the purchasing function:
class ProVersionUnlocker
{
string ProductID = "XXXXXXXXXXXX";
public async Task<bool> WasProVersionPurchased()
{
/*TESTING
*
* TESTING
*
* TESTING
*/
#if DEBUG
//return true;
#endif
var billing = CrossInAppBilling.Current;
try
{
var connected = await billing.ConnectAsync(ItemType.InAppPurchase);
if (!connected)
{
//Couldn't connect
return false;
}
//check purchases
var purchases = await billing.GetPurchasesAsync(ItemType.InAppPurchase);
//check for null just incase
if (purchases?.Any(p => p.ProductId == ProductID) ?? false)
{
//Purchase restored
return true;
}
else
{
//no purchases found
return false;
}
}
catch (InAppBillingPurchaseException purchaseEx)
{
//Billing Exception handle this based on the type
Log.Debug("IAP", "Error: " + purchaseEx);
}
catch (Exception ex)
{
//Something has gone wrong
}
finally
{
await billing.DisconnectAsync();
}
return false;
}
public async Task<bool> PurchaseProVersion()
{
if (await WasProVersionPurchased())
return true;
string Payload = "ProVersionProVersion";
var billing = CrossInAppBilling.Current;
try
{
var connected = await billing.ConnectAsync(ItemType.InAppPurchase);
if (!connected)
{
//we are offline or can't connect, don't try to purchase
return false;
}
//check purchases
var purchase = await billing.PurchaseAsync(ProductID, ItemType.InAppPurchase, Payload, new Verify());
//Consume for further testing
//var consumedItem = await CrossInAppBilling.Current.ConsumePurchaseAsync(purchase.ProductId, purchase.PurchaseToken);
//possibility that a null came through.
if (purchase == null)
{
//did not purchase; do nothing and fall through to failure
}
else if (purchase.State == PurchaseState.Purchased)
{
return true;
}
}
catch (InAppBillingPurchaseException purchaseEx)
{
//Billing Exception handle this based on the type
//Maybe it was an Already Purchased Error, in which case we return true
if (purchaseEx.PurchaseError == PurchaseError.AlreadyOwned)
return true;
Log.Debug("IAP", "Error: " + purchaseEx);
}
catch (Exception ex)
{
//Something else has gone wrong, log it
Log.Debug("IAP", "Issue connecting: " + ex);
}
finally
{
await billing.DisconnectAsync();
}
return false;
}
public class Verify : IInAppBillingVerifyPurchase
{
const string key1 = #"XOR_key1";
const string key2 = #"XOR_key2";
const string key3 = #"XOR_key3";
public Task<bool> VerifyPurchase(string signedData, string signature, string productId = null, string transactionId = null)
{
//This is only used for testing things at the moment.
#if false
var key1Transform = Plugin.InAppBilling.InAppBillingImplementation.InAppBillingSecurity.TransformString(key1, 1);
var key2Transform = Plugin.InAppBilling.InAppBillingImplementation.InAppBillingSecurity.TransformString(key2, 2);
var key3Transform = Plugin.InAppBilling.InAppBillingImplementation.InAppBillingSecurity.TransformString(key3, 3);
return Task.FromResult(Plugin.InAppBilling.InAppBillingImplementation.InAppBillingSecurity.VerifyPurchase(key1Transform + key2Transform + key3Transform, signedData, signature));
#else
return Task.FromResult(true);
#endif
}
}
Here is the calling code, which is within a PreferenceFragment:
var Unlocker = new ProVersionUnlocker();
var unlock = this.FindPreference("unlock");
unlock.PreferenceClick += async (sender, e) =>
{
//Toast.MakeText(Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity, "Ayy lmao", ToastLength.Short).Show();
unlock.SetSummary(Resource.String.PressAgain);
bool Success = await Unlocker.PurchaseProVersion();
//Toast.MakeText(Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity, Success.ToString(), ToastLength.Short).Show();
UnlockStuff();
};

System.Data.Entity.Validation.DbEntityValidationException

I have a project that uses Entity Framework. While calling SaveChanges on my DbEntityValidationException, I get the following exception:
System.Data.Entity.Validation.DbEntityValidationException: 'Validation
failed for one or more entities. See 'EntityValidationErrors' property
for more details.'
This is all fine and dandy, but I don't want to attach a debugger every time this exception occurs. More over, in production environments I cannot easily attach a debugger so I have to go to great lengths to reproduce these errors.
How can I see the details hidden within the DbEntityValidationException?
private void btnCreateLetter_Click(object sender, EventArgs e)
{
using (TransactionScope TS = new TransactionScope())
{
try
{
Letter TblLetter = new Letter();
TblLetter.Subject = txtSubject.Text.Trim();
TblLetter.Abstract = txtAbstract.Text.Trim();
TblLetter.Body = ckeCKEditor.TextEditor.Text.Trim();
{
var LastLetterID = (from Letter in Database.Letters orderby Letter.LetterID descending select Letter).First();
TblLetter.LetterNO = PublicVariable.TodayDate.Substring(0, 4).Substring(2, 2) + PublicVariable.gDetermineJobLevel + "/" + (LastLetterID.LetterID + 1);
}
TblLetter.CreateDate = lblCreateDate.Text;
TblLetter.UserID = PublicVariable.gUserID;
if (rdbClassification.Checked == true)
{
TblLetter.SecurityType = 1;
}
else if (rdbConfidential.Checked == true)
{
TblLetter.SecurityType = 2;
}
else if (rdbSeries.Checked == true)
{
TblLetter.SecurityType = 3;
}
if (rdbActionType.Checked == true)
{
TblLetter.UrgencyType = 1;
}
else if (rdbInstantaneous.Checked == true)
{
TblLetter.UrgencyType = 2;
}
else if (rdbAnnie.Checked == true)
{
TblLetter.UrgencyType = 3;
}
TblLetter.ArchivesType = 1;
if (rdbFollowHas.Checked == true)
{
TblLetter.FollowType = 1;
}
else if (rdbFollowHasnoot.Checked == true)
{
TblLetter.FollowType = 2;
}
if (rdbAttachmentHas.Checked == true)
{
TblLetter.AttachmentType = 1;
}
else if (rdbAttachmentHasnot.Checked == true)
{
TblLetter.AttachmentType = 2;
}
TblLetter.ReadType = 1;
TblLetter.LetterType = 1;
TblLetter.DraftType = 1;
if (rdbResponseDeadlineHas.Checked == true)
{
TblLetter.AnswerType = 1;
TblLetter.AnswerReadLine = String.Format("{0:yyyy/MM/dd}", Convert.ToDateTime(pdpSetResponseDeadline.Value.Year.ToString() +
"/" + pdpSetResponseDeadline.Value.Month.ToString() + "/" + pdpSetResponseDeadline.Value.Day.ToString()));
}
else if (rdbResponseDeadlineHasnot.Checked == true)
{
TblLetter.AnswerType = 2;
}
Database.Letters.Add(TblLetter);
Database.SaveChanges();
if (rdbAttachmentHas.Checked == true)
{
if (lblPath.Text != "")
{
FileStream ObjectFileStream = new FileStream(lblPath.Text, FileMode.Open, FileAccess.Read);
int Lenght = Convert.ToInt32(ObjectFileStream.Length);
byte[] ObjectData;
ObjectData = new byte[Lenght];
string[] strPath = lblPath.Text.Split(Convert.ToChar(#"\"));
ObjectFileStream.Read(ObjectData, 0, Lenght);
ObjectFileStream.Close();
AttachFile TableAttachFile = new AttachFile();
TableAttachFile.FileSize = Lenght / 1024;
TableAttachFile.FileName = strPath[strPath.Length - 1];
TableAttachFile.FileData = ObjectData;
TableAttachFile.LetterID = TblLetter.LetterID;
Database.AttachFiles.Add(TableAttachFile);
Database.SaveChanges();
}
}
TS.Complete();
MessageBox.Show("saved", "ok", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (InvalidCastException ex)
{
MessageBox.Show(ex.ToString());
MessageBoxIcon.Error);
return;
}
}
}
You have to get the validation errors from the db.SaveChanges() method of the DatabaseContext object -- you can't get them where you are.
You can either modify the SaveChanges() method of your database context and wrap it in a try-catch block, or (since the class is partial) you can extend the partial class within your application and just override the SaveChanges() method.
There is a nice blog post about this called Easy way to improve DbEntityValidationException of Entity Framework here.
The essence of it is something like this:
public partial class NorthwindEntities
{
public override int SaveChanges()
{
try
{
return base.SaveChanges();
}
catch (DbEntityValidationException ex)
{
// Retrieve the error messages as a list of strings.
var errorMessages = ex.EntityValidationErrors
.SelectMany(x => x.ValidationErrors)
.Select(x => x.ErrorMessage);
// Join the list to a single string.
var fullErrorMessage = string.Join("; ", errorMessages);
// Combine the original exception message with the new one.
var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);
// Throw a new DbEntityValidationException with the improved exception message.
throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
}
}
}
The blogger explains:
That’s it! The rest of your code will automatically use the overridden
SaveChanges so you don’t have to change anything else. From now on,
your exceptions will look like this:
System.Data.Entity.Validation.DbEntityValidationException: Validation
failed for one or more entities. See 'EntityValidationErrors' property
for more details. The validation errors are: The field PhoneNumber
must be a string or array type with a maximum length of '12'; The
LastName field is required.
The DbEntityValidationException also contains the entities that caused
the validation errors. So if you require even more information, you
can change the above code to output information about these entities.
As mention, you need to check on your EntityValidationError when it throws the exception.
You should fix that validation error, instead of asking bypass this exception.
Normally these errors are table allow length, data type, column does not allow null and etc. There will be exact fiend name mention in your exception too.

messagebox to show all validation fields

so I have 3 fields that combines into 1 string and I'm currently fixing the validation so the question is how can i identify a certain textbox that is empty and the user needs to fill it up before he/she can proceed i tried this
if(string.IsNullOrEmpty(txtEYear.Text) || string.IsNullOrEmpty(txtECat.Text) || string.IsNullOrEmpty(txtEID.Text))
{
MessageBox.Show("Please fill in the missing fields");
}
Try this one.When any filed is empty focus the required field.
string message = string.empty;
message = "Please fill the ";
if(string.IsNullOrEmpty(txtEYear.Text))
{
message = message + " txtEYear ";
txtEYear.Focus();
}
if(string.IsNullOrEmpty(txtECat.Text))
{
message = message + " txtECat";
txtECat.Focus();
}
if(string.IsNullOrEmpty(txtEID.Text))
{
message = message + " txtEID";
txtEID.Focus();
}
MessageBox.Show(message+" Fields");
For that you have to use separate loop and form the message something like this:
bool isValidated = true;
StringBuilder message= new StringBuilder("Please fill the following fields: ");
if(string.IsNullOrEmpty(txtEYear.Text)
{
message.Append("Year");
isValidated = false;
}
if(string.IsNullOrEmpty(txtECat.Text))
{
message.Append("txtECat");
isValidated = false;
}
if(string.IsNullOrEmpty(txtEID.Text))
{
message.Append("ID");
isValidated = false;
}
// check all fields are valid
if(isValidated)
{
// Continue
}
else
{
MessageBox.Show(message.ToString());
}

asp.net How to insert record into database

I am having difficulties on getting my insert method to work correctly. I am new to back end development so any suggestions or comments will be helpful.
public Boolean insertDefaultUser()
{
Boolean flag = true;
Users newUser = new Users();
newUser.alias = "bulby";
newUser.password = "chicken";
newUser.email = "r#hot.com";
dbc.Users.AddObject(newUser); // ERROR !
dbc.SaveChanges();
return flag;
}
However, on the "add object line" it gives me the follow error --->
Error "The best overloaded method match for System.Data.Objects.ObjectSet<Guild_Chat.User>.AddObject(Guild_Chat.User)' has some invalid arguments ".
Try adding the actual entity type Guild_Chat.User, for example:
public bool InsertDefaultUser()
{
try
{
Guild_Chat.User newUser = new Guild_Chat.User
{
alias = "bulby",
password = "chicken",
email = "r#hot.com"
};
dbc.Users.AddObject(newUser);
dbc.SaveChanges();
return true;
}
catch(Exception e)
{
return false;
}
}

Categories