none
Need an example of using ModelMetadata.ModelType property RRS feed

  • Question

  • Hi everybody,

    .NET documentation gives only a few words describing ModelMetadata.ModelType property. I need help in understanding if this is what I need to use and what exactly does it return and how can I use it. Let me explain what I want to achieve

    I have the following property in my model

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

    In my view I want this property to be automatically displayed with the class that only allows numerical input.

    I have the following EditorFor view defined for the textbox (textbox.cshtml in the Shared/EditorTemplates folder):

    <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>
    

    The above was designed based on this blog post

    http://dotnetspeak.com/index.php/2012/10/asp-net-mvc-template-and-knockout-js/comment-page-1/#comment-56698

    Now, I want the editor above to become "smarter" and automatically use "number only" class if my model is numeric.

    I have alternative solution discussed in this stackoverflow question

    http://stackoverflow.com/questions/13984602/how-to-make-entry-field-to-allow-numbers-only-using-ef-and-data-annotations

    but I think to also make it work using just one editor. I am hoping that ModelMetadata.ModelType can give me what I am looking for, but I tried to find examples, have been searching for a while and didn't find anything I can understand and use. Perhaps someone can help me.

    Thanks a lot in advance.


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog

    Sunday, December 23, 2012 3:21 AM

All replies

  • Hi Naomi,

    Welcome to the MSDN forum.

    I am trying to involve a senior expert into your thread. Please wait for the response. Sorry for any inconvenience.

    Merry Christmas!


    Alexander Sun [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, December 24, 2012 8:51 AM
  • Thanks, Alexander.

    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog

    Monday, December 24, 2012 3:57 PM
  • You can always use ViewData.ModelMetadata.ModelType to get conditional code based on property type.

    Sergey

    Monday, December 24, 2012 7:07 PM
  • I understand I can use the ModelType, but what exactly does it return? Does it return a string like "integer" or what? I am going to try it now but I hoped to find an example and I googled a lot on that question on Sunday and found nothing I could understand.

    Ok, I tested and ModelType.ToString returned Int16 for this case. I wish I can see all possible values it can return, but at least now I have some idea of how to write that conditional code.

    UPDATE. I also found this http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/66a7dc8d-f276-4d45-8da4-f8d9857db52c/ - the question now is how can I incorporate the above into the razor view?


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog



    • Edited by Naomi N Monday, December 24, 2012 8:31 PM
    Monday, December 24, 2012 7:34 PM
  • I've implemented this

    <div class="editor-field">
       @if (ViewData.ModelMetadata.ModelType.IsNumeric())
       {
        <input type="number" id=@ViewData.ModelMetadata.PropertyName name=@ViewData.ModelMetadata.PropertyName class="numericOnly" value=@Model  />
       }
        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>


    which seems to work OK, but I am getting the following warning

    Warning 1 Validation (HTML5): This attribute requires a value. If the value is enclosed in quotation marks, the quotation marks must match.

    So I am wondering how can I adjust the input line to avoid the warning.

    Thanks in advance.


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog

    Wednesday, December 26, 2012 10:00 PM
  • This is because your ID is not quoted.  However, your approach seems off to me.  All you need to do is test for number and add your class to list of classes in the Html.Textbox code 

    Sergey

    Thursday, December 27, 2012 2:09 AM
  • Can you clarify what do you mean, please, and also explain how can I make it to be input type="number" using the above?

    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog

    Thursday, December 27, 2012 2:17 AM
  • I did not notice you wanted to use input-number.  Just put quotes around the Id then.

    Sergey

    Thursday, December 27, 2012 2:42 AM
  • Do you mean all the current code, but the stuff with @ inside quotes?

    Let me try that, then, thanks.

    BTW, I've been struggling with attempting to use flexigrid and modal forms for editing for a while. I made partial progress, but still far from success. May be you will be able to provide ideas in this thread

    http://social.microsoft.com/Forums/en-US/partnerdevaspnet/thread/61443760-bd03-4e31-95a4-7d6f4ce4f39a


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog

    Thursday, December 27, 2012 2:46 AM
  • I am having problems with that solution I implemented :( The validations do not seem to fire correctly.

    Here is my current solution

     @if (ViewData.ModelMetadata.ModelType.IsNumeric())
       {
        <input type="number" id="@ViewData.ModelMetadata.PropertyName" name="@ViewData.ModelMetadata.PropertyName" class="numericOnly" value="@Model"  />
       }
        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 }
                })

    And this is what I put in my ViewModel (I had to move properties from the model into view model because otherwise they were not firing):

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using CardNumbers.Objects;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel;
    
    using DataAnnotationsExtensions;
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace CardNumbers.Models
    {
        public class ClientViewModel
        {
            public Client Client { get; set; }
    
            [Required]
            [DisplayName("Client No")]
            [UIHint("Number")]
            [Column("client_no", TypeName = "smallint")]
            [Remote("doesClientNoExist", "Client", HttpMethod = "POST", ErrorMessage = "Client Number already exists. Please enter a different Client Number.")]
            public virtual Int16 Number { get; set; }
    
            [Required]
            [Column("client_name", TypeName = "varchar")]
            [DisplayName("Client Name")]
            [MaxLength(30, ErrorMessage = "Client Name should not be longer than 30 characters")]
            [MinLength(3, ErrorMessage = "Client Name is too short")]
            [Remote("doesClientNameExist", "Client", HttpMethod = "POST", ErrorMessage = "Client Name already exists. Please enter a different Client Name.")]
            public virtual string Name { get; set; }
    
            public int id { get; set; }
        }
    }

    So, now the Client Name validations seem to work Ok and even unique validation (Remote attribute) works fine.

    But the Client No does not seem to work. I can try using the same code and forget about input type=number (just use the numericonly class), but I wanted to use input type=number.

    Do you see what should I adjust?

    Thanks again for your help.


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog

    Thursday, December 27, 2012 8:16 PM
  • Alexander,

    I am having trouble of making input type=number combined with validations. For my latest solution posted in this thread validations do not fire and I am not sure how to solve this problem. Have you had a chance to find an expert?

    Thanks again.


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog


    • Edited by Naomi N Thursday, December 27, 2012 10:33 PM
    Thursday, December 27, 2012 10:32 PM
  • Ok, I re-defined the above to be

    <div class="editor-field">
       @if (ViewData.ModelMetadata.ModelType.IsNumeric())
       {
        @Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { type = "number", @class = "numericOnly"  })
           @*<input type="number" id="@ViewData.ModelMetadata.PropertyName" name="@ViewData.ModelMetadata.PropertyName" class="numericOnly" value="@Model" 
            data-bind="@ViewData.ModelMetadata.PropertyName" />*@
       }
        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 now validations fire. However, now the validations fire "too early". In other words, right after I type just one digit in the client no field, the validations fire right away.

    Here is my numericOnly class - may be I need to adjust it?

    $(".numericOnly").keypress(function (e) {
        if (String.fromCharCode(e.keyCode).match(/[^0-9]/g)) return false;
    });
    

    or is it "normal" behavior of the input type="number" and validations ?


    For every expert, there is an equal and opposite expert. - Becker's Law


    My blog

    Thursday, December 27, 2012 11:11 PM