Current value in Range validator ErrorMessage - MVC 5 - asp.net-mvc

This may be something really simply, but I just can't find any examples that do what I'm trying to do.
I'm trying to display the current value in my rangeattribute validator for my model.
I'm trying to decorating my property like so...
<Required>
<Display(Name:="Invoice(s) Amount")>
<Range(1, Decimal.MaxValue, ErrorMessage:="The value '{don't know what goes here}' is not valid for {0}.")>
<DataType(DataType.Currency)>
<DisplayFormat(ApplyFormatInEditMode:=False, DataFormatString:="{0:C2}")>
Public Property InvoiceAmount As Decimal
I've seen lots of examples where {1} and {2} are used to display the min and max for the range. However I haven't seen anything where the current value is displayed.
If I enter some non-numeric value, it displays the default messages as...
The value 'asdf' is not valid for Invoice(s) Amount.
This is why I'm assuming there aught to be some way to do it also for the range.
So essentially what I want to do is display the same kind of message when the value is a valid decimal, but is outside the allowed range, so it could be something like...
The value '-100' is not valid for Invoice(s) Amount.
It seems like it should be really simple.

I don't think this can be done with RangeAttribute, but create a class inherited form RangeAttribute and you can override the default behaviour and do what you like.

Related

How can I indicate an error during a parse operation?

Within the scripting language I am implementing, valid IDs can consist of a sequence of numbers, which means I have an ambiguous situation where "345" could be an integer, or could be an ID, and that's not known until runtime. Up until now, I've been handling every case as an ID and planning to handle the check for whether a variable has been declared under that name at runtime, but when I was improving my implementation of a particular bit of code, I found that there was a situation where an integer is valid, but any other sort of ID would not be. It seems like it would make sense to handle this particular case as a parsing error so that, e.g., the following bit of code that activates all picks with a spell level tag greater than 5 would be considered valid:
foreach pick in hero where spell.level? > 5
pick.activate[]
nexteach
but the following which instead compares against an ID that can't be mistaken for an integer constant would be flagged as an error during parsing:
foreach pick in hero where spell.level? > threshold
pick.activate[]
nexteach
I've considered separate tokens, ID and ID_OR_INTEGER, but that means having to handle that ambiguity everywhere I'm currently using an ID, which is a lot of places, including variable declarations, expressions, looping structures, and procedure calls.
Is there a better way to indicate a parsing error than to just print to the error log, and maybe set a flag?
I would think about it differently. If an ID is "just a number" and plain numbers are also needed, I would say any string of digits is a number, and a number might designate an ID in some circumstances.
For bare integer literals (like 345), I would have the tokenizer return maybe a NUMBER token, indicating it found an integer. In the parser, wherever you currently accept ID, change it to NUMBER, and call a lookup function to verify the "NUMBER" is a valid ID.
I might have misunderstood your question. You start by talking about "345", but your second example has no integer strings.

Rails converting string with float value to integer

I have a model that has an attribute named value this is saved in the db as an integer.
I input the number in the view using a text_field, I am also performing a method on it :before_save that takes the value (something like 21.37) and using the money gem convert it to just cents.
However, it seems that before I can even perform the method that converts it from a float to an integer it is being converted to some kind of integer and the decimal is being lost.
I have tested this by outputting value in the method that runs before_save: and it round it to 21
Does anyone know why this might be happening, Im not performing any other changes to it.
I'm guessing you're doing something like Coupon.new(params) in your controller, and since Rails knows Coupon's value should be an integer, it helpfully calls to_i on params[:value] for you under the covers, which turns 21.37 into 21. Here's a rather inelegant but effective fix:
params[:value] ~= /.*\.(\d+)/
params[:value] = params[:value].to_f * (10**$1.length) if $1
Do that before you do Coupon.new(params).
Another option is to simply assume you don't care about anything after the 2nd decimal place (you're dealing with cents after all). Then you can simply do params[:value] = params[:value].to_f.round(2) * 100.
Also you should consider using number_field instead of text_field in your view so you can at least be sure you're getting a number. Something like number_field(:coupon, :value, step: 0.01) should ensure your users can enter decimals.
I agree with #kitkat seems like something that would happen in the model layer. You might be able to implement your conversion to cents logic in 'before_validation' or perhaps a custom setter for 'coupon'.

Bean Validation Min/Max wrong message

I'm using Min/Max Beanvalidation. Here is an example:
#Min(value = 100, message="too low")
#Max(value = 1000, message="too high")
private Integer example;
If i enter 99 i get the correct message "too low". If i enter 1001 i also get the correct message "too high". If i enter a very high number e.g. 10000000000 i get a generic message which i found out is this one: javax.faces.converter.BigIntegerConverter.BIGINTEGER={2}. So i suspect that if the user enters a number which is larger then the actual field type, he will get another message.
This is actually not what i want to achieve. I always want to show the user "too high". Is there a way to achieve this?
There are really two things going on, conversion and validation. In a first step JSF needs to take your string input and convert it to a number. This is where you get the error. Your value cannot be converted to an Integer. If conversions works, JSF populates your model and that's where validation kicks in. If validation then fails you get the defined Bean Validation messages. So what can you do:
Configure the JSF message for javax.faces.converter.BigIntegerConverter.BIGINTEGER={2} to be more descriptive
Change the datatype, for example use BigInteger. In this case the conversion from string to number will work
Use string in the bean and validate the string. You probably need then to convert to a number at a different point though, but that depends on you use case.
The maximum for Integer in java is 2^31 which is just over 2.1 billion. The input you used, 10 billion, is then beyond the maximum of an integer and would overflow the field, so it is not a valid given the field type, regardless of any validation you may have in place. you could switch the field type to be a BigInteger, then override the default validation messages to fit your needs, but that may be overkill given the purpose of your question. You can also have custom messages
Why not just limit the amount of characters in the inputfield in the frontend, for example
<h:inputText maxlength="4"/>
I'd guess it's possible to bypass if you really want, but I would'nt worry too much about the usability for someone hacking the site :-)

Weird behavior with Range DataAnnotation

I have a Password field with [Range(5, 10)].
If I input a correct value between 5 and 10, it displays a message error anyway. What might be causing this?
the Range attribute is used to determine what the minimum and maximum numeric value for the field should be. If you are trying to set min/max length I would suggest using [StringLength(10, MinimumLength=5)] attribute to set this constraint on the property which would do what I think it is your looking to for

floating point precision in ruby on rails model validations

I am trying to validate a dollar amount using a regex:
^[0-9]+\.[0-9]{2}$
This works fine, but whenever a user submits the form and the dollar amount ends in 0(zero), ruby(or rails?) chops the 0 off.
So 500.00 turns into 500.0 thus failing the regex validation.
Is there any way to make ruby/rails keep the format entered by the user, regardless of trailing zeros?
I presume your dollar amount is of decimal type. So, any value user enters in the field is being cast from string to appropriate type before saving to the database. Validation applies to the values already converted to numeric types, so regex is not really a suitable validation filter in your case.
You have couple of possibilities to solve this, though:
Use validates_numericality_of. That way you leave the conversion completely to Rails, and just check whether the amount is within a given range.
Use validate_each method and code your validation logic yourself (e.g. check whether the value has more than 2 decimal digits).
Validate the attribute before it's been typecasted:
This is especially useful in
validation situations where the user
might supply a string for an integer
field and you want to display the
original string back in an error
message. Accessing the attribute
normally would typecast the string to
0, which isn‘t what you want.
So, in your case, you should be able to use:
validates_format_of :amount_before_type_cast, :with => /^[0-9]+\.[0-9]{2}$/, :message => "must contain dollars and cents, seperated by a period"
Note, however, that users might find it tedious to follow your rigid entry rules (I would really prefer being able to type 500 instead 500.00, for example), and that in some locales period is not a decimal separator (if you ever plan to internationalize your app).
In general if you wish to “remember” the decimal precision of a floating point value, you should use a decimal type, not a binary float.
On the other hand, I'm not certain why you would wish to force the string representation in such a strict manner… How about accepting any number and formatting it with e.g. number_to_currency?
Usually with money it's best to store it as an integer in cents (500 cents is $5.00). I use the Money gem to handle this.

Resources