Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Required" validation message remains after removal of [Required] attribute MVC 5

I had a [Required] attribute in one of my view model's properties:

[DefaultValue(1)]
[Required(ErrorMessage = "* Required")] // this has now been removed
public int QuoteQuantity { get; set; }

I removed the [Required], but I still get this validation message that prevents me from submitting.

In the view I have these lines:

@Html.EditorFor(model => model.QuoteQuantity, new { htmlAttributes = new { @class = "form-control", value = "1" } })
@Html.ValidationMessageFor(model => model.QuoteQuantity, "", new { @class = "text-danger" })

When I leave this empty and submit I get this validation error:

The QuoteQuantity field is required.

I should mention that I have built the solution repeatedly, closed and reopened VS, and still I keep getting this validation error even though the current code is this:

[DefaultValue(1)]
public int QuoteQuantity { get; set; }

Any idea why this might happen?

like image 704
Shiran Dror Avatar asked May 10 '16 22:05

Shiran Dror


1 Answers

It's because your QuoteQuantity is an int, which is currently not Nullable, so when you're trying to validate, the field cannot be empty because it does not allow nulls.

2 ways of getting round this:

  • Set your QuoteQuantity int as int? (Nullable int)

or

  • Use a different property to accept the value as a string, and in your get for the QuoteQuantity, use an int.TryParse to see if the string can convert to an int. You would need some sort of check in place, though to see if it falls within your min/max range - if you have one

Example:

First suggestion:

public int? QuoteQuantity { get; set; }

Second suggestion: (returns 0, if the string is empty/null or not a valid int)

public int QuoteQuantity
{
    get 
    {
        int qty = 0;
        if (!string.IsNullOrWhiteSpace(QuoteQuantityAsString))
        {
            int.TryParse(QuoteQuantityAsString, out qty);
        }
        return qty;
    }
}

public string QuoteQuantityAsString { get; set; }
// You will then need to use the
// QuoteQuantityAsString property in your View, instead

I would suggest the first option, and make sure you do null checks around where you're using the QuoteQuantity :)

Hope this helps!

EDIT:

In the fairness of giving various options, I've just thought of another way (probably better than suggestion 2). Either way, I think suggestion 1 is still the best way.

In order to return validation only if the user does input something into your "Quote Quantity" string input on the view:

View:

  • In the View, add a text input, that allows the user to input the quantity (or not, as might be the case) and use this in place of your current QuoteQuantity elements

  • Give it an id + name of something like quoteQty

  • Add a ValidationFor, like before, but give it the quoteQty name as the first argument

Controller:

  • In your controller POST method, accept another param of string quoteQty (so that this maps to the same as the name from your View). This will get populated from your HttpPost

  • Before your (ModelState.IsValid) check, try and parse the quoteQty as an int; if not, add a ModelError for quoteQty, with a message

  • Then, your model will return a validation error and be displayed on the page as desired.

  • Downside is, this can't be validated client-side so the server will have to return the error

Like this:

public ActionResult SendQuote(Model yourmodel,
                              string quoteQty)
{
    if (!string.IsNullOrWhiteSpace(quoteQty))
    {
        if (!int.TryParse(quoteQty, out yourmodel.QuoteQuantity))
        {
            // If the TryParse fails and returns false
            // Add a model error. Element name, then message.
            ModelState.AddModelError("quoteQty",
                                     "Whoops!");
        }
    }
    ...
    // Then do your ModelState.IsValid check and other stuffs
}

And just use the original property

public int QuoteQuantity { get; set; }

in your model. An int's default value will be 0 if you never set it. If the TryParse fails, it sets the value to 0, too

like image 175
Geoff James Avatar answered Nov 18 '22 22:11

Geoff James