ASP.NET MVC: DataAnnotations - Show an error messa

2019-07-08 08:11发布

问题:

There appears to be something of a hole in the way DataAnnotations works in that a user entering in some text into a field that will go into an int will never reach the DataAnnotations code. It kicks off a model binding error and displays the error to the user "The value 'a' is not valid for the XXXX field."

Anyway, it's all very nice that it automatically handles this situation, but I actually want to display an error message indicating the problem eg. "The value 'a' is not numeric. Please enter in a numeric value for the XXXX field".

I have tried the solutions set out How to replace the default ModelState error message in Asp.net MVC 2? and ASP.NET MVC - Custom validation message for value types, but I can't get them to work.

It appears that my resource file is not being read at all, since here (http://msdn.microsoft.com/en-us/library/system.web.mvc.defaultmodelbinder.resourceclasskey.aspx) it states "If the property is set to an invalid class key (such as a resource file that does not exist), MVC throws an exception." and even if I change the line to DefaultModelBinder.ResourceClassKey = "asdfasdhfk" there is no exception.

Anyone have any ideas?

EDIT: Here is some code. All of it is working minus my Messages.resx file's messages are not being used. The code for Messages.resx is auto generated so I won't include it.

So entering "a" into ProcessOrder results in a generic message rather than what I have entered into Messages.resx for PropertyValueInvalid (and InvalidPropertyValue for good measure).

Application_Start method

protected void Application_Start()
{            
    RegisterRoutes(RouteTable.Routes);
    ModelBinders.Binders.DefaultBinder = new Microsoft.Web.Mvc.DataAnnotations.DataAnnotationsModelBinder(); //set dataanooations to be used
    DefaultModelBinder.ResourceClassKey = "Messages"; //set data annotations to look in messages.resx for the default messages
    ValidationExtensions.ResourceClassKey = "Messages";
}

Entity Class

[MetadataType(typeof(GLMetaData))]
public partial class GL
{

}



public class GLMetaData
{
    public int TransRefId { get; set; }

    [DisplayName("Process Order")]
    public int? ProcessOrder { get; set; }

    [DisplayName("Trans Type")]
    [StringLength(50)]
    public string TransType { get; set; }

    [StringLength(100)]
    public string Description { get; set; }

    [DisplayName("GL Code")]
    [StringLength(20)]
    public string GLCode { get; set; }

    [DisplayName("Agents Credit No")]
    [StringLength(50)]
    public string AgentsCreditNo { get; set; }

    [Required]
    public bool Active { get; set; }
}

Controller Action:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(GL glToBeUpdated)
    {
        try
        {
            if (!ModelState.IsValid)
                return View(glToBeUpdated);

            //set auto properties
            glToBeUpdated.UpdateDate = DateTime.Now;
            glToBeUpdated.UpdateUser = this.CurrentUser;

            glDataLayer.update(glToBeUpdated);

            glDataLayer.submitChanges();

            return RedirectToAction("Index");
        }
        catch
        {
            glDataLayer.abortChanges();

            throw;
        }
    }

回答1:

What I did to combat a similar issue was to clear the model state, validate against ModelState["XXXX"].Value.AttemptedValue instead of against the nulled value caused by an trying to put an invalid value into the Model's property, populating the error messages and resetting the Model values.

That way I can have the error messages I want and if necessary offer more than one ("a value is required" or "the value must be numeric").



回答2:

I have battled this for most of the day on MVC4 RC. No matter what i set

DefaultModelBinder.ResourceClassKey

to it never seemed to work. It also never threw an exception when I assigned junk.

This is what I was using to assign the value (to no avail):

 DefaultModelBinder.ResourceClassKey = typeof(App_GlobalResources.ValidationMessages).Name;

In the end I decided to tackle this error message on the client side and override the data attribute that jQuery uses to display the message.

@Html.TextBoxFor(m => m.Amount, new Dictionary<string,object>(){{"data-val-number","Invalid Number"}})

this is working how I need it to.

Ironically this works too:

@Html.TextBoxFor(m => m.Amount, new Dictionary<string, object>() {{ "data-val-number", HttpContext.GetGlobalResourceObject("ValidationMessages", "PropertyValueInvalid") } })


回答3:

Here I have taken Contact number field as string but with Range Attribute so can provide numeric validatioin to use if from your Resource file .

    [Required(ErrorMessageResourceType = typeof(Global), ErrorMessageResourceName = "ContactNumberRequired")]
    [Range(0, int.MaxValue, ErrorMessageResourceType = typeof(Global), ErrorMessageResourceName = "ValidContactNumber")]
    [Display(Name = "Contact Number")]
    public string ContactNumber { get; set; }

So now here provided ErrorMessageResourceName as key . You can customize and use it also in Multi Language