0

I've been doing some searches, found this ASP.NET MVC 3 - Partial vs Display Template vs Editor Template but I am still not clear as what and how should I use for "custom UI controls" for several model properties.

I have two examples in mind:

FistName MiddleInitial LastName or Phone Ext

I want to have some sort of a re-usable UI control / template that I can use.

Say, I have a partial view which I use in both Create and Edit views, called _ClientForm. In this view I have Contact1 and Contact2 and related properties in my model. Now, I'd like to create a common look for both of them and display side by side. Also, they both have Phone/Ext properties and I'd like some sort of visual control to be able to re-use it every time I have these two properties in my model.

I am not clear as what I should use and how should I go with the implementation.

Just to make it clear as what I mean.

Right now I have the partial view with the following code

@using WebDemo.Helper
@model CardNumbers.Objects.Client
<fieldset>
    <legend>Client Info</legend>

    @Html.ValidationSummary(true)

    <input type="hidden" id="fntype" name="fntype">
    @Html.HiddenFor(model => model.Id)
    @Html.EditorFor(model => model.Number, EditorTemplate.TextBox)

    @Html.EditorFor(model => model.Name, EditorTemplate.TextBox)

    @Html.EditorFor(model => model.Address, EditorTemplate.EditBox)

    <div id="ContactsInfo">
        @*Contact 1*@
        <div id="Contact1">

            @Html.EditorFor(model => model.Contact1, EditorTemplate.TextBox)
            @Html.EditorFor(model => model.Email1, EditorTemplate.TextBox)
            @Html.EditorFor(model => model.Phone1, EditorTemplate.TextBox)
            @Html.EditorFor(model => model.Ext1, EditorTemplate.TextBox)

        </div>

        @*Contact2*@
        <div id="Contact2">

            @Html.EditorFor(model => model.Contact2, EditorTemplate.TextBox)

            @Html.EditorFor(model => model.Email2, EditorTemplate.TextBox)
            @Html.EditorFor(model => model.Phone2, EditorTemplate.TextBox)
            @Html.EditorFor(model => model.Ext2, EditorTemplate.TextBox)
        </div>
    </div>
    @*<div class="clear"></div>*@
    <div id="SaveCancel" class="float-right">
        <button type="Submit" id="btnSave">Save</button>
        <button type="reset" id="btnCancel">Cancel</button>
    </div>
</fieldset>

The view code is already a bit simplified using the technique described here http://dotnetspeak.com/index.php/2012/10/asp-net-mvc-template-and-knockout-js

So, as you see I have 2 divs with the Contact information and inside each div I also have Phone/Ext with I'd like to place close to each other.

So, I am thinking I need something reusable for both: the Contact Info and phone/ext.

I also show my Client class for some further clarifications: using System;

using System.ComponentModel.DataAnnotations;
using System.ComponentModel;

using DataAnnotationsExtensions;
using System.ComponentModel.DataAnnotations.Schema;
using System.Collections.Generic;

namespace CardNumbers.Objects
{
    public class Client
    {
        //public Client()
        //{
        //    this.ClientOrders = new List<ClientOrder>();

        //    this.Reorders = new List<Reorder>();
        //}

        [Key]
        [Column("ClientId",TypeName = "int")]
        public virtual int Id { get; set; }
        [Required]
        [DisplayName("Client No")]
        [Column("client_no", TypeName = "smallint")]
        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")]
        public virtual string Name { get; set; }

        [StringLength(100)]
        [DisplayName("First Contact")]
        [DisplayFormat(NullDisplayText = "")]
        [Column("Contact1",TypeName =  "varchar")]
        public virtual string Contact1 { get; set; }

        [Email]
        [StringLength(100)]
        [Column("c1_email", TypeName = "varchar")]
        public virtual string Email1 { get; set; }

        [DataType(DataType.PhoneNumber)]
        [Column("C1_Phone", TypeName = "varchar")]
        [StringLength(10)]
        [DisplayName("Phone")]
        public virtual string Phone1 { get; set; }

        [StringLength(5)]
        [Column("C1_Ext", TypeName = "varchar")]
        [DisplayName("Ext")]
        public virtual string Ext1 { get; set; }

        [StringLength(100)]
        [DisplayName("Second Contact")]
        [Column("Contact2", TypeName = "varchar")]
        public virtual string Contact2 { get; set; }

        [Email]
        [StringLength(100)]
        [Column("C2_Email", TypeName = "varchar")]
        public virtual string Email2 { get; set; }

        [DataType(DataType.PhoneNumber)]
        [StringLength(10)]
        [DisplayName("Phone")]
        [Column("C2_Phone", TypeName = "varchar")]
        public virtual string Phone2 { get; set; }

        [StringLength(5)]
        [DisplayName("Ext")]
        [Column("C2_Ext",TypeName = "varchar")]
        public virtual string Ext2 { get; set; }

        [DataType(DataType.MultilineText)]
        public virtual string Address { get; set; }

        [ForeignKey("EnteredByOperator")]
        public string EnteredBy { get; set; }

        [InverseProperty("ClientsEnteredBy")]
        public virtual Operator EnteredByOperator { get; set; }

        [ForeignKey("ModifiedByOperator")]
        public string ModifiedBy { get; set; }

        [InverseProperty("ClientsUpdatedBy")]
        public virtual Operator ModifiedByOperator { get; set; }

        [DataType(DataType.DateTime)]
        [DisplayName("Created on")]
        public DateTime EnteredOn { get; set; }

        [DataType(DataType.DateTime)]
        [DisplayName("Modified on")]
        public DateTime? ModifiedOn { get; set; }

        public virtual ICollection<ClientOrder> ClientOrders { get; set; }

        public virtual ICollection<Reorder> Reorders { get; set; }
    }
}`

`

Thanks a lot in advance.

Community
  • 1
  • 1
Naomi
  • 718
  • 1
  • 9
  • 28

1 Answers1

1

I would add 2 EditorFor templates.

  • One that edits an individual contact info
  • One that is either for a list of contact info or for a special viewmodel that contains two contact infos. This template would in turn call editor for on all the contained contact info view models which would render the first template.

ViewModels

 public class ContactDetails
 {
    public string Name {get;set;]
    public string Email {get; set;}
 }
 public class ContactsInfo
 {
    public ContactDetails Contact1 {get; set; }
    public ContactDetails Contact2 {get; set; }
 }
 public class Client {
    public ContactsInfo ContactsInfo {get; set;}
 }

Main View

 @model client
 ...other html....
 @Html.EditorFor(m => m.ContactsInfo)
 ...other html....

Editor Template ContactsInfo.cshtml

@model ContactsInfo
<div id="ContactsInfo">
    <div id="Contact1">
        @Html.EditorFor(m => m.Contact1)
    </div>
    <div id="Contact2">
        @Html.EditorFor(m => m.Contact2)
    </div>
</div> 

Editor Template ContactDetails.cshtml

   @model ContactDetails
   @Html.EditorFor(model => model.Contact1, EditorTemplate.TextBox)
   @Html.EditorFor(model => model.Email1, EditorTemplate.TextBox)
   @Html.EditorFor(model => model.Phone1, EditorTemplate.TextBox)
   @Html.EditorFor(model => model.Ext1, EditorTemplate.TextBox)
Betty
  • 9,109
  • 2
  • 34
  • 48
  • I am not sure I understand your idea. May be you can clarify? I added some code in my original question to make it clearer. – Naomi Oct 18 '12 at 18:16
  • This is much more clearer, thanks a lot. Just one thing I am not yet understanding. I have the client class defined in Models (which is in the separate project). So, what is the Client class in the ViewModel? In other words, what is the transition between my Model Client and the ViewModel Client class? Or should that class be named differently? The client class is quite comprehensive right now and uses a lot of Data Annotations – Naomi Oct 18 '12 at 19:11
  • same class, just wanted to demonstrate replacing all the fields with 1 model object. – Betty Oct 18 '12 at 19:41
  • Sorry, please bear with me. Do you mean I should change my current Client class the way you described above or what should I do - still confused. My Client class is (I added it also in the original question). – Naomi Oct 18 '12 at 20:08
  • In other words, do you suggest me to apply changes you gave to the original Client class I posted above? E.g. have the Contact1 and Contact2 to be separate subclasses? Will data annotations still work? – Naomi Oct 18 '12 at 20:12
  • yeah just put the dataannotations on the properties on the contactdetails class instead – Betty Oct 18 '12 at 21:44
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/18261/discussion-between-naomi-and-betty) – Naomi Oct 18 '12 at 23:12
  • I got stuck already on the very first step of changing my class. Please see my comment (last one) to this blog post http://weblogs.asp.net/manavi/archive/2010/12/11/entity-association-mapping-with-code-first-part-1-one-to-one-associations.aspx Do you see how should I proceed? – Naomi Oct 19 '12 at 19:49
  • Unfortunately, I found a bug in Entity Framework for Complex Type. I reported it here http://entityframework.codeplex.com/workitem/604 – Naomi Oct 21 '12 at 05:28
  • I've implemented this idea, but now for some reason I no longer see email validations. The field shows in red, but the text never shows. – Naomi Oct 22 '12 at 02:20
  • Does your view model have validation attributes on it? – Betty Oct 22 '12 at 02:45
  • What exactly do you mean? I have several validations inside the model (through Data Annotations) – Naomi Oct 22 '12 at 19:00
  • The validators are in the EditorFor for the textbox, editbox. I got the idea from the blog post to reduce the view code. – Naomi Oct 22 '12 at 20:12
  • Can you post the code for your EditorFor template? although maybe you should just create a totally new question – Betty Oct 22 '12 at 20:19
  • Yes, I created a new question here http://stackoverflow.com/questions/13016674/validations-not-show-up-using-ef-code-first-with-complex-types – Naomi Oct 22 '12 at 23:15