I like to check the model for nulls before I use the value in the view. Is this the correct way to use the get and set? I am getting an Exception of type 'System.StackOverflowException' was thrown." on the this.MiddleInitial = value;
Model
public string MiddleInitial {
get {
if (string.IsNullOrWhiteSpace(MiddleInitial) == true) {
return MiddleInitial;
}
return $ "{MiddleInitial.Trim()}.";
}
set {
this.MiddleInitial = value;
}
}
Updated Model
public string MiddleInitial {
get {
if (string.IsNullOrWhiteSpace(MiddleInitial) == true) {
return MiddleInitial;
}
return $ "{MiddleInitial.Trim()}.";
}
set {
if (string.IsNullOrWhiteSpace(MiddleInitial) == true) {
return MiddleInitial;
}
return $ "{MiddleInitial.Trim()}.";
}
}
Inside your get method's if condition, you should check false, not true. Like below:
get
{
//if (string.IsNullOrWhiteSpace(MiddleInitial) == true)
if (string.IsNullOrWhiteSpace(MiddleInitial) == false)
{
return MiddleInitial;
}
return $"{MiddleInitial.Trim()}.";
}
Using an internal private backing field for the property allows you a fine control on what goes into the property and what you return back
// The blank value should be the default for the property
private string _middleInitial = "";
public string MiddleInitial
{
get { return _middleInitial; }
// When someone tries to set a new value for the property
// check for Invalid values (in this case a null ) and
// reset the property back to the default
// (or even throw an exception if it is the case)
set
{
_middleInitial = (value == null ? "" : value.Trim());
// if(value == null)
// throw new ArgumentException("Null is not accepted");
// else
// _middleInitial = value.Trim();
}
}
Related
I would like to display 'reason not explicited' if the user doesn't fill this field or the user input if he fills it.
With this code, I don't understand why but even if I fill the field, it is going to display 'reason not explicited'.
private string reason;
public string Reason
{
get
{
return this.reason;
}
set
{
if (string.IsNullOrEmpty(this.Reason))
this.reason = "reason not explicited";
else this.reason = value;
}
}
[Pure]
public static bool IsNullOrEmpty(String value) {
return (value == null || value.Length == 0);
}
just use value in your setter to handle the correct behavior
set
{
if (string.IsNullOrEmpty(value))
this.reason = "reason not explicited";
else
this.reason = value;
}
Because you are checking the property instead of the value.
Your current code sets the value of the property only if it's null or empty.
It should be
set
{
if (string.IsNullOrEmpty(value))
this.reason = "reason not explicited";
else this.reason = value;
}
Or even better:
set
{
this.reason = (string.IsNullOrEmpty(value)) ? "reason not explicited": value;
}
You have to check value, not this.Reason:
public string Reason
{
get
{
return this.reason;
}
set
{
this.reason = string.IsNullOrEmpty(value)
? "reason not explicited"
: value;
}
}
The problem is in this line of code
if (string.IsNullOrEmpty(this.Reason))
When you are trying to get the value of this property, calls it's getter, which returns value of reason field. And this field is not filled with correct value at the moment you are trying to get value of it.
So you should modify your code to check if null or empty string of concrete input value:
if (string.IsNullOrEmpty(value))
you need to pass value to the function IsNullOrEmpty function
if (string.IsNullOrEmpty(value))
this.reason = "reason not explicited";
else this.reason = value;
The setter will trigger when you change(assign) the value, so if the user skip that field means the setter will not trigger. But the getter will trigger when you access the value of the property. So in your case if you apply the logic inside the get means it will display the "reason not explicited" if the reason is null or empty. So the new logic would be like the following:
get
{
if (string.IsNullOrEmpty(this.reason))
return "reason not explicited";
else this.reason = value;
return this.reason;
}
set
{
this.reason = value;
}
Another solution will be like this:
Initialize the backup property with the "reason not explicited" so even if the user skip the field(setter will not trigger) you will get the default value to be printed. And you have to update the backup property based on the value
private string reason = "reason not explicited";
public string Reason
{
get { return this.reason; }
set
{
if (String.IsNullOrEmpty(value))
this.reason = "reason not explicited";
else
this.reason = value;
}
}
You might do an extension method to IsNullOrEmpty():
public static bool IsNullOrEmpty(this string value) => string.IsNullOrEmpty(str);
And then you can use it this way:
set { this.reason = value.IsNullOrEmpty() ? "reason not explicited" : value; }
public static trnUser GetUserByEmail(string email)
{
if (string.IsNullOrEmpty(email) == true)
{
return null;
}
}
if (string.IsNullOrEmpty(email) == true) {
return null;
} else {
return new trnUser();
}
you need to provide information on what to return when the if statement is false.
I'm attempting to resolve the following exercise:
You need to create a class named Product that represents a product.
The class has a single property named Name. Users of the Product class
should be able to get and set the value of the Name property. However,
any attempt to set the value of Name to an empty string or a null
value should raise an exception. Also, users of the Product class
should not be able to access any other data members of the Product
class. How will you create such a class?
I have created the following code but for some reason it does not throw the exception when the string is invalid:
class Program
{
static void Main(string[] args)
{
Product newProduct = new Product();
Console.WriteLine("Enter Product name:");
newProduct.Name = null; //Console.ReadLine();
Console.WriteLine("Product name is : {0}", newProduct.Name);
Console.ReadLine();
}
}
class Product
{
private string name;
public string Name
{
get
{
return this.name;
}
set
{
if (Name != String.Empty || Name != null)
{
name = value;
}
else
{
throw new ArgumentException("Name cannot be null or empty string", "Name");
}
}
}
}
Is the exception not thrown because I do not have try-catch statement?
I was also wondering is it possible to have only catch statement without try statement?
Use String.IsNullOrEmpty Method (String). Change your set like this:
set
{
if (!string.IsNullOrEmpty(value))
{
name = value;
}
else
{
throw new ArgumentException("Name cannot be null or empty string", "value");
}
}
Also you can use String.IsNullOrWhiteSpace Method (String) that Indicates whether a specified string is null, empty, or consists only of white-space characters.
Your if state is wrong. Let's do a truth table:
if (value != String.Empty || value != null)
Name = null True Or False = True
Name = "name" True Or True = True
Name = "" False Or True = True
Your if statement is always true!
I would re-write it thus:
if (value == String.Empty || value == null)
{
throw new ArgumentException("Name cannot be null or empty string", "Name");
}
else
{
name = value;
}
you could just change the Or to and AND but I think the above reads better (the below has an unnecessary double negative):
if (value != String.Empty && value != null)
{
name = value;
}
else
{
throw new ArgumentException("Name cannot be null or empty string", "value");
}
As Dmitry Bychenko says, I didn't notice you were not testing for value. In getters you should use the value property. Not the name of your property
The second parameter (again pointed out by Dmitry Bychenko) in your exception should be:
The name of the parameter that caused the current exception.
MSDN
which in your case is the string "value":
throw new ArgumentException("Name cannot be null or empty string", "value");
If you want different exceptions on null and on empty string (often null means that something is totally wrong, when empty string is just a format error):
public string Name {
get {
return name;
}
set {
if (null == value)
throw new AgrumentNullException("value");
else if (String.Equals(value, ""))
throw new AgrumentException("Empty values are not allowed.", "value");
name = value;
}
}
In case you don't want to distiguish them:
public string Name {
get {
return name;
}
set {
if (String.IsNullOrEmpty(value))
throw new AgrumentException("Null or empty values are not allowed.", "value");
name = value;
}
}
Note, that in both cases it's value that you have to test, not a property Name. In your original code the name's (and so Name as well) initial value is null and you'll get exception whatever you try to set.
I am trying to make a contact class for my contact managers application and I need to have email have to contain 1 and only 1 # symbol and make sure the phone number is in the format 123-456-7890 but I am not sure how to do this.
Any guidance would be appreciated
class Contact
{
class Contact
{
//private member variables
private String _firstName;
private String _lastName;
private Type _contactTypes;
private String _phoneNumber;
private String _emailAddress;
//Public constructor that takes five arguments
public Contact()
{
//Call the appropriate setter (e.g. FirstName) to set the member variable value
/* GetFirstName = firstName;
GetLastName = lastName;
ContactTypes = contactTypes;
GetPhoneNumber = phoneNumber;
GetEmailAddress = emailAddress;*/
}
/*********************************************************************
* Public accessors used to get and set private member variable values
*********************************************************************/
//Public ContactTypes accessor
public Type ContactTypes
{
get
{
//Return member variable value
return _contactTypes;
}
set
{
//Validate value and throw exception if necessary
if (value == null)
throw new Exception("ContactType must have a value");
else
//Otherwise set member variable value*/
_contactTypes = value;
}
}
enum ContactTypesEnum { Family, Friend, Professional }
//Public FirstName accessor: Pascal casing
public String GetFirstName
{
get
{
//Return member variable value
return _firstName;
}
set
{
//Validate value and throw exception if necessary
if (value == "")
throw new Exception("First name must have a value");
else
//Otherwise set member variable value
_firstName = value;
}
}
//Public LastName accessor: Pascal casing
public String GetLastName
{
get
{
//Return member variable value
return _lastName;
}
set
{
//Validate value and throw exception if necessary
if (value == "")
throw new Exception("Last name must have a value");
else
//Otherwise set member variable value
_lastName = value;
}
}
//Public PhoneNumber accessor
public String GetPhoneNumber
{
get
{
//Return member variable value
return _phoneNumber;
}
set
{
bool isValid = Regex.IsMatch(value, #"/d{3}-/d{3}-/d{4}");
//Validate value and throw exception if necessary
if (value == "")
throw new Exception("PhoneNumber must have a value");
else
//Otherwise set member variable value
_phoneNumber = value;
}
}
//Public Email accessor
public String GetEmailAddress
{
get
{
//Return member variable value
return _emailAddress;
}
set
{
//Validate value and throw exception if necessary
if (value == "")
throw new Exception("EmailAddress must have a value");
else
//Otherwise set member variable value
_emailAddress = value;
}
}
}
}
I agree with the comment from #Enigmativity - it's not a good idea to throw exceptions in your accessor set functions. That being said, you're already halfway there with your isValid regular expression test in GetPhoneNumber.
set
{
bool isValid = Regex.IsMatch(value, #"/d{3}-/d{3}-/d{4}");
if (isValid) // Set member variable value
_phoneNumber = value;
}
You can either do a similar regular expression test for your email or use System.Net.Mail.MailAddress class. See this SO response.
In my controller, I have an action that takes in 3 arguments (primary_key, property, and value) and uses reflection to set the value on corresponding model. (Found by its primary key)
I thought I could catch the model if it was invlaid with ModelState.IsValid but it evaluates as true. Now it goes to db.SaveChanges(); which throws exception.
The ModelState is valid. (Apparently it is no the model instance as found by the primary key and actually refers to my three inputs).
I thought I could check my model for errors with the following line...
if (System.Data.Entity.Validation.DbEntityValidationResult.ValidationErrors.Empty)
But I am getting a "missing object reference" error.
I have no idea what that means. (New to C# and everything else here.) Any help?
EDIT 1 - SHOW MORE CODE:
Validations
[Column("pilot_disembarked")]
[IsDateAfter(testedPropertyName: "Undocked",
allowEqualDates: true,
ErrorMessage = "End date needs to be after start date")]
public Nullable<System.DateTime> PilotDisembarked { get; set; }
Custom Validatior
public sealed class IsDateAfter : ValidationAttribute, IClientValidatable
{
private readonly string testedPropertyName;
private readonly bool allowEqualDates;
public IsDateAfter(string testedPropertyName, bool allowEqualDates = false)
{
this.testedPropertyName = testedPropertyName;
this.allowEqualDates = allowEqualDates;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var propertyTestedInfo = validationContext.ObjectType.GetProperty(this.testedPropertyName);
if (propertyTestedInfo == null)
{
return new ValidationResult(string.Format("unknown property {0}", this.testedPropertyName));
}
var propertyTestedValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null);
if (value == null || !(value is DateTime))
{
return ValidationResult.Success;
}
if (propertyTestedValue == null || !(propertyTestedValue is DateTime))
{
return ValidationResult.Success;
}
// Compare values
if ((DateTime)value >= (DateTime)propertyTestedValue)
{
if (this.allowEqualDates)
{
return ValidationResult.Success;
}
if ((DateTime)value > (DateTime)propertyTestedValue)
{
return ValidationResult.Success;
}
}
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
}
Controller Action
[HttpPost]
public ActionResult JsonEdit(string name, int pk, string value)
{
Voyage voyage = db.Voyages.Find(pk);
var property = voyage.GetType().GetProperty(name);
if (Regex.Match(property.PropertyType.ToString(), "DateTime").Success)
{
try
{
if (Regex.Match(value, #"^\d{4}$").Success)
{
var newValue = DateTime.ParseExact(value, "HHmm", System.Globalization.CultureInfo.InvariantCulture);
property.SetValue(voyage, newValue, null);
}
else if (value.Length == 0)
{
property.SetValue(voyage, null, null);
}
else
{
var newValue = DateTime.ParseExact(value, "yyyy/MM/dd HHmm", System.Globalization.CultureInfo.InvariantCulture);
property.SetValue(voyage, newValue, null);
}
}
catch
{
Response.StatusCode = 400;
return Json("Incorrect Time Entry.");
}
}
else
{
var newValue = Convert.ChangeType(value, property.PropertyType);
property.SetValue(voyage, newValue, null);
}
if (ModelState.IsValid)
{
db.SaveChanges();
Response.StatusCode = 200;
return Json("Success!");
}
else
{
Response.StatusCode = 400;
return Json(ModelState.Keys.SelectMany(key => this.ModelState[key].Errors));
}
}
When any value of your model is null at that time ModelState.IsValid.So first check your model data.