I was able to bypass all the framework messages by making the property a string in my view model.
[Range(0, 15, ErrorMessage = "Can only be between 0 .. 15")]
[StringLength(2, ErrorMessage = "Max 2 digits")]
[Remote("PredictionOK", "Predict", ErrorMessage = "Prediction can only be a number in range 0 .. 15")]
public string HomeTeamPrediction { get; set; }
Then I need to do some conversion in my get method:
viewModel.HomeTeamPrediction = databaseModel.HomeTeamPrediction.ToString();
and post method:
databaseModel.HomeTeamPrediction = int.Parse(viewModel.HomeTeamPrediction);
This works best when using the range attribute, otherwise some additional validation would be needed to make sure the value is a number.
You can also specify the type of number by changing the numbers in the range to the correct type:
[Range(0, 10000000F, ErrorMessageResourceType = typeof(GauErrorMessages), ErrorMessageResourceName = nameof(GauErrorMessages.MoneyRange))]