DataAnnotations Automatic Handling of int is Causing a Roadblock - asp.net

Summary: DataAnnotation's automatic handling of an "int?" is making me rethink using them at all.
Maybe I'm missing something and an easy fix but I can't get DataAnnotations to cooperate. I have a public property with my own custom validation attribute:
[MustBeNumeric(ErrorMessage = "Must be a number")]
public int? Weight { get; set; }
The point of the custom validation attribute is do a quick check to see if the input is numeric and display an appropriate error message. The problem is that when DataAnnotations tries to bind a string to the int? is automatically doesn't validate and displays a "The value 'asdf' is not valid for Weight."
For the life of me I can't get DataAnnotations to stop handling that so I can take care of it in my custom attribute.
This seems like it would be a popular scenario (to validate that the input in numeric) and I'm guessing there's an easy solution but I didn't find it anywhere.

Here's a workaround (as I wouldn't really call this a solution). Add a Messages.resx file inside the App_GlobalResources folder of your web application. Add the following resource inside:
Key: PropertyValueInvalid
Value: {0} Must be a number
In the Application_Start method of Global.asax add the following:
DefaultModelBinder.ResourceClassKey = "Messages";

Related

How do I override fluentvalidator extension methods?

I am using .NET ASP.NET MVC 4. For validation I am using Fluent validation. I am new to this. How can I override a method of the DefaultValidatorExtensions class?
I found one solution.
Create basevalidator class which inherited both IValidatorInterceptor and AbstractValidator. But I am not getting how to override validation methods.
Actually I want to change the default message of any validation method. The message is common for all attributes for some validations, so I want to override those validation methods rather to use 'WithMessage()'.
For example:
RuleFor(x => x.Name).NotEmpty(); will return " 'Name' should not be empty." But I want message 'Required'.
I found an answer on this link. I think it can help you:
https://fluentvalidation.net/localization#default-messages
If you want to replace all (or some) of FluentValidation’s default messages then you can do this by implementing a custom version of the ILanguageManager interface.
For example, the default message for the NotNull validator is '{PropertyName}' must not be empty. If you wanted to replace this message for all uses of the NotNull validator in your application, you could write a custom Language Manager:
public class CustomLanguageManager : FluentValidation.Resources.LanguageManager {
public CustomLanguageManager() {
AddTranslation("en", "NotNullValidator", "'{PropertyName}' is required.");
}
}
Here we have a custom class that inherits from the base LanguageManager. In its constructor we call the AddTranslation method passing in the language we’re using, the name of the validator we want to override, and the new message.
Once this is done, we can replace the default LanguageManager by setting the LanaguageManager property in the static ValidatorOptions class during your application’s startup routine:
ValidatorOptions.LanguageManager = new CustomLanguageManager();
This is a simple example that only replaces one validator’s message in English only, but could be extended to replace the messages for all languages. Instead of inheriting from the default LanguageManager, you could also implement the ILanguageManager interface directly if you want to load the messages from a completely different location other than the FluentValidation default (for example, if you wanted to store FluentValidation’s default messages in a database).
Of course, if all you want to do is replace this message for a single use of a validator, then you could just use WithMessage("'{PropertyName}' is required");

ASP.NET MVC - How to handle a string in a model that does not allow nulls?

So I'm a bit new to ASP.NET and MVC. I've got an ASP.NET MVC5 application, using Entity Framework 6. I've generated my models from a SQL Server database, and am so far just using the vanilla index/create/details/edit constructs.
In my models, various fields are marked as "Allow Nulls" and others aren't. While creating a new entry, any type that is, say, an int that is left as null is handled nicely by the ModelState.IsValid check and the #Html.ValidationMessageFor messages.
On one entry test, however, I received a DbEntityValidationException. I used the try/catch from this question to find out that it was one of the string (VARCHAR) fields that was left blank.
I am assuming this is because the string class allows nulls, where as int does not (unless declared as Nullable<type> in the model) thus the controller/model doesn't flag it as invalid.
What would be the easiest way to handle this? Is there a way to decorate the string property in the model so it gets checked as well? Or do I need to go as far as attempting to save, catching the exception, and manually handling the validation messages?
Thanks
It is possible to decorate your property with a Required-attribute. Mvc wil show an error message when the user is posting a form while this property is empty.
public class TestClassModel
{
[Required]
public string RequiredString { get; set; }
}

ASP.NET 4 JSON DataContractJsonSerializer Lower Case

I have a class with several properties all defined in sentence case:
Public Class Provider
Public Property ProviderName As String
End Class
I need to be able to pass instances of this through AJAX which I will then be using in JavaScript to add to an array, process etc. Currently I am using the DataContractJsonSerializer to serialize to JSON and return through an ASHX handler. It may just be me being picky, but I don't really like having sentence case properties in JavaScript, I would prefer them all to be lower case, to produce the following:
alert(myProvider.providername);
With the default DataContractJsonSerializer I simply cannot find a way to do this! With JSON.NET it would appear that it is a simple task, but unfortunately I can't introduce another dependency into this project - as much as I would like to.
Does anybody know of any way to override the format of keys that are generated?
The project is using ASP.NET Web Forms 4.0.
Thanks,
Chris.
It's possible to customize the DataMember attribute to use a lowercase name. Here's the syntax in C#, I assume in VB should be similar:
[DataMember(Name = "title")]
public string Title { get; set; }

asp.net MVC3 Custom Validation

I am new to MVC so this question may be naive
I know you can add validation attributes to model properties and the framework will provide appropriate server side and client side validation.However I am forced to use a legacy database structure where one of the properties in the model is either "int" or "string"
and the other property(Value) data type is determined by the first property.This means that I cannot use Annotations for validation. But is there any simple way of programatically "annotating" the properties after values are fetched from the database and the model class is constructed.If this can be done then it will do effective (client Side) validation without much hassle.
thanks
This answer shows one way to inject attributes at runtime. Another answer shows how to use validations that are only checked sometimes.
In your case it would be pretty easy to do model-based validation.
For server-side validation:
public class MyModel: IValidatableObject
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public IEnumerable<ValidationResult>
Validate(ValidationContext validationContext)
{
var relevantFields = new [] {"Prop2"};
if (Prop1 == "Int" && NotValidInt(Prop2))
yield return new ValidationResult("Prop2 must be convertable to int", relevantFields);
else if (prop1 == "String" && NotValidString(Prop2))
yield return new ValidationResult("Prop2 must be convertible to string", relevantFields);
}
}
For client-side validation, it's a bit more involved but details are available here:
MSDN article on adding support for clientside validation
A Good StackOverflow answer on the topic
See the custom validation section of the free Pluralsight training on validation for more information on server-side validation.
You are falling into the normal newbie error of thinking of your database as the M in MVC. Any non-trivial app is going to require that you seperate your database model from your view model. So apply your attributes to a view model, then use business logic to copy the values to your database model when your view is properly validated.
MVC is a User Interface pattern, and databases do not belong in it... I know, every sample application under the sun passes your data objects to the view, but that's just not the way it should be done.

Getting the actual field data from a Linq Expression

I'm working on an ASP.NET MVC3 application and I annotated my model with an attribute that specifies what roles can change specific fields for any possible status the model is in. Take this as an example:
public class Model
{
[RoleLimiter(
new[]{Role.Admin, Role.BasicUser, Role.Validator}, // for draft
new[]{Role.Admin, Role.BasicUser, Role.Validator}, // for awaiting validation
new[]{Role.Admin})] // for published etc
public string Subject {get;set;}
}
It looks a bit messy, sure, but it's very easy to change if needed. Now once I have this, it's easy to check for each field the current status and then get the list of roles that can change it. If the current role isn't in it, I'll add a disabled class to the control.
What I wanted to do next is to make a HtmlHelper extension that has the same syntax as the normal EditorFor (or even a straight-forward TextBoxFor), but does this extra check and automatically adds the attribute behind the scenes, but I'm stuck on getting the field info from the expression, ie:
How do you get from
HtmlHelper.TextBoxWithRoleLimitationsFor(x=>x.Subject);
to the attribute attached to x.Subject?
You fetch the LambdaExpression.Body and check whether it's a MemberExpression. You can then get the Member of the MemberExpression and get the custom attributes from that.

Resources