5

I have written a CustomValidation attribute for a model I am using in an MVC application.

It's not that complex, however for some reason I am getting a really odd NullReferenceException error. I have stripped this right back to the absolute bare minimum just to try and get past this.

The code trips over here if (value != null)

And if I put a breakpoint on the line above it, stepping over generates the exception, almost before the breakpoint.

The weird thing is, I can take value and put it into a string variable and I can see it is valid and present.

I then tried to change the if statement to check that variable is null instead of value and that ALSO yields the error.

What have I done wrong?

The actual Error Response back from the controller is below. The line it references is the If statement.

<h1>An unhandled exception occurred while processing the request.</h1>
        <div class="titleerror">NullReferenceException: Object reference not set to an instance of an object.</div>
        <p class="location">TechsportiseOnline.Helpers.CustomValidations&#x2B;BibValidatorAttribute.IsValid(object value, ValidationContext validationContext) in 
            <code title="C:\Users\matthew.warr\Documents\Git\Website\TechsportiseOnline\Helpers\CustomValidations.cs">CustomValidations.cs</code>, line 22
        </p>

CustomAttribute Class

public class BibValidatorAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        value = (string)value;

        if (value != null)
        {
            RaceEntry raceEntry = (RaceEntry)validationContext.ObjectInstance;

            var _context = (ApplicationDbContext)validationContext.GetService(typeof(ApplicationDbContext));

            var databaseBib = _context.RaceEntries.FirstOrDefault(c => c.Id == raceEntry.Id).BibNumber.ToString();

            if (value == databaseBib)
                {
                    return new ValidationResult("The bib number entered already exists");
                }
                else
                {
                    return ValidationResult.Success;
                }
        }
        else
        {
            return ValidationResult.Success;
        }              
    }
}

Model

public partial class RaceEntry
    {

        public long Id { get; set; }
        public long RaceID { get; set; }
        [NotMapped]
        public string RaceName { get; set; }
        [NotMapped]
        [DisplayFormat(DataFormatString = "{0:dd MMMM yyyy}")]
        public DateTime RaceDate { get; set; }
        [IgnoreDataMember]
        public string OwnerID { get; set; }
        [IgnoreDataMember]
        public string AthleteUserId { get; set; }
        [Display(Name = "Title")]

        public string Title { get; set; }
        [Display(Name = "First Name *")]
        [Required]
        public string FirstName { get; set; }
        [Display(Name = "Last Name *")]
        [Required]
        public string LastName { get; set; }
        [Display(Name = "Email Address")]
        [EmailAddress(ErrorMessage = "Invalid Email Address")]
        [RequiredOnlineOnly]
        public string Email { get; set; }
        [Display(Name = "Date Of Birth *")]
        [DataType(DataType.Date)]
        [DateOfBirth]
        [DisplayFormat(DataFormatString = "{0:dd MMMM yyyy}")]
        public DateTime DateOfBirth { get; set; }
        [Display(Name = "Gender *")]
        public string Gender { get; set; }
        [Display(Name = "EA Affiliation Number")]
        public string EANumber { get; set; }
        [Display(Name = "Club Name")]
        public string Club { get; set; }
        [Display(Name = "Team")]
        public string Team { get; set; }
        [Display(Name = "Bib/Race Number")]
        [BibValidator (ErrorMessage = "The bib number you have entered already exists")]
        public string BibNumber { get; set; }
        public DateTime EntryDateTime { get; set; }
        [IgnoreDataMember]
        public DateTime LastUpdated { get; set; }
        public string Status { get; set; }
        [Display(Name = "Mobile Phone")]
        public string MobilePhone { get; set; }
        [IgnoreDataMember]
        public string FullMobilePhone { get; set; }
        [IgnoreDataMember]
        [Display(Name = "Number")]       
        public string HouseNumber { get; set; }
        [Display(Name = "Address *")]
        [RequiredOnlineOnly]
        public string Address1 { get; set; }
        [Display(Name = "Address 2")]
        public string Address2 { get; set; }
        [Display(Name = "Town/City")]
        public string City { get; set; }
        [Display(Name = "State")]
        public string State { get; set; }
        [Display(Name = "County")]
        public string County { get; set; }
        [Display(Name = "Country")]
        public string Country { get; set; }
        [Display(Name = "Postcode *")]
        [RequiredOnlineOnly]
        public string PostCode { get; set; }
        public string Source { get; set; }
        [Display(Name = "Entry Type")]
        public string EntryType { get; set; }

        public bool Premium { get; set; }
        public bool SMSSent { get; set; }
        public bool FinalInstructionsSent { get; set; }
        public bool ResultEmailSent { get; set; }
        public bool Refunded { get; set; }
        public string StripeCode { get; set; }
        public decimal AmountPaid { get; set; }
        public string AmountPaidCurrency { get; set; }

        [IgnoreDataMember]
        public string BillingName { get; set; }
        [IgnoreDataMember]
        public string BillingAddress1 { get; set; }
        [IgnoreDataMember]
        public string BillingAddress2 { get; set; }
        [IgnoreDataMember]
        public string BillingCity { get; set; }
        [IgnoreDataMember]
        public string BillingState { get; set; }
        [IgnoreDataMember]
        public string BillingCounty { get; set; }
        [IgnoreDataMember]
        public string BillingCountry { get; set; }
        [IgnoreDataMember]
        public string BillingPostCode { get; set; }
        [IgnoreDataMember]
        public string BillingEmail { get; set; }

    }

Relevant section of Controller

[HttpPost]
        public IActionResult Create([FromBody] RaceEntry item)
        {
            if (item == null)
            {
                return BadRequest();
            }

            //Check bib number
            if (!ModelState.IsValid)
            {
                return BadRequest("Bib number already exists");
            }
27
  • 1
    Hmmm, sounds like a multithreading issue. How/where is this attribute used? Commented Mar 2, 2018 at 13:26
  • 3
    Check the stack trace of the exception. Me thinks the value object in question is not an actual string object, but rather of some type that implements buggy operator overloads for == and/or !=. Commented Mar 2, 2018 at 13:26
  • 2
    Saying that, what is the point of value = (string)value;, other than cheking it is castable to a string. After this, value is still of type object. I would create a new variable to store the string Commented Mar 2, 2018 at 13:34
  • 1
    @DanielLerps You could get a NullReferenceExceptionif a class implements an explicit cast operator and that throws a NullReferenceException. Commented Mar 2, 2018 at 13:39
  • 2
    @MatthewWarr, don't just throw code at us. Look at the stack trace of the exception to identify the code line throwing the exception as precisely as possible... Commented Mar 2, 2018 at 14:01

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.