Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make entry field to allow numbers only using EF and Data Annotations?

I am trying to figure out if there is a way to make sure that numeric only input is allowed using Data Annotations and Entity Framework.

I am using the following code

[Required]
[DisplayName("Client No")]
[Column("client_no", TypeName = "smallint")]
public virtual Int16 Number { get; set; }

I want this to be displayed using number class.

In one place I use the following

<input type="number" name="searchClientNo" class="numericOnly" /><br />

but in the entry form I am using

@Html.EditorFor(m => m.Number, EditorTemplate.TextBox)

where I have a custom made EditorFor with the following code

<div class="editor-label">
    @Html.Label((ViewData.ModelMetadata.DisplayName??ViewData.ModelMetadata.PropertyName),
        new Dictionary<string, object>
            {
                { "for", ViewData.ModelMetadata.PropertyName }
            })
</div>
<div class="editor-field">
    @Html.TextBox("", (object)Model,
        new Dictionary<string, object>
            {
                { "id", ViewData.ModelMetadata.PropertyName },
                { "name", ViewData.ModelMetadata.PropertyName },
                { "class", "text-box single-line"},
                { "data-bind", "value: " + ViewData.ModelMetadata.PropertyName },
            })
    @Html.ValidationMessage(ViewData.ModelMetadata.PropertyName,
        new Dictionary<string, object>
            {
                { "data-valmsg-for", ViewData.ModelMetadata.PropertyName }
            })
</div>

I am wondering how can I keep this code without changes but still use the numeric only textbox. Do I need to use UIHint?

Or alternatively, is it possible to make my existing EditorFor smarter?

I found this blog post http://robseder.wordpress.com/2012/06/01/uihint-displaytemplates-and-editortemplates-in-mvc/ but I am already using a custom EditorFor. May be I need to add a new type, say, EditorTemplate.NumericTextBox and add another editor? This sounds like it may work, I am going to try this tomorrow...

Thanks a lot in advance.

like image 718
Naomi Avatar asked Dec 21 '12 05:12

Naomi


People also ask

Does EF core support data annotation attributes?

Data Annotations attributes are . NET attributes which can be applied on an entity class or properties to override default conventions in EF 6 and EF Core. Data annotation attributes are included in the System.

Which data annotation is used to exclude a property when the columns are created for the corresponding table?

The NotMapped attribute can be applied to properties of an entity class for which we do not want to create corresponding columns in the database.


2 Answers

You could write a custom editor template ~/Views/Shared/EditorTemplates/NumberTemplate.cshtml:

@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { type = "number" })

and then decorate your view model property with the UIHint attribute:

[Required]
[DisplayName("Client No")]
[Column("client_no", TypeName = "smallint")]
[UIHint("NumberTemplate")]
public virtual Int16 Number { get; set; }

and inside your view:

@Html.EditorFor(x => x.Number)

or if you don't want to use the UIHint attribute on your view model you could define EditorTemplate.NumericTextBox = "NumberTemplate" and then:

@Html.EditorFor(m => m.Number, EditorTemplate.NumericTextBox)
like image 127
Darin Dimitrov Avatar answered Oct 20 '22 16:10

Darin Dimitrov


Just want to share my solution in case it may help someone:

My New EditorFor:

<div class="editor-label">
    @Html.Label((ViewData.ModelMetadata.DisplayName??ViewData.ModelMetadata.PropertyName),
        new Dictionary<string, object>
            {                
                { "for", ViewData.ModelMetadata.PropertyName }
            })
</div>

<div class="editor-field">
   @if (ViewData.ModelMetadata.ModelType.IsNumeric())
   {
    @Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { type = "number", @class = "numericOnly"  })      
   }
    else
    {
     @Html.TextBox("", (object)Model,
        new Dictionary<string, object>
            {
                { "id", ViewData.ModelMetadata.PropertyName },
                { "name", ViewData.ModelMetadata.PropertyName },
                { "class", "text-box single-line"},
                { "data-bind", "value: " + ViewData.ModelMetadata.PropertyName },
            })
    }

     @Html.ValidationMessage(ViewData.ModelMetadata.PropertyName,
        new Dictionary<string, object>
            {
                { "data-valmsg-for", ViewData.ModelMetadata.PropertyName }
            })
</div>

And the IsNumeric extension method is based on the code I found in C# MSDN forum and this is its implementation:

/// <summary>
/// Checks is the object is of numeric type 
        /// see http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/66a7dc8d-f276-4d45-8da4-f8d9857db52c/
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
        public static bool IsNumeric(object obj)
        {
            return (obj == null) ? false : IsNumeric(obj.GetType());
        }

        public static bool IsNumeric(this Type type)
        {
            if (type == null)
                return false;

            TypeCode typeCode = Type.GetTypeCode(type);

            switch (typeCode)
            {
                case TypeCode.Byte:
                case TypeCode.Decimal:
                case TypeCode.Double:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.SByte:
                case TypeCode.Single:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                    return true;
            }
            return false;
        }
like image 26
Naomi Avatar answered Oct 20 '22 15:10

Naomi