Michel
Michel

Reputation: 23635

Where to place the 'logic' to compose the fullname from a person's name parts (in a MVC application)

I have 3 viewmodels which all have to show the fullname of a person.

Now i offcourse can duplicate the GetFullName() function in all 3 viewmodels, but that is not so dry.

But where then do i leave the logic to calculate the persons fullname?

Such a simple thing, and so many ways to implement it.

What our your thoughts on it?

Upvotes: 2

Views: 1124

Answers (4)

Peter
Peter

Reputation: 14518

We have a 'formatter' class which handles formatting certain data such as displaying an address line over multiple lines or just a single line.

We call it like this: Formatter.FormatAddress(address) where address is a Model class instance. You could easily apply such logic with your fullname.


Another option would be to write your own HtmlHelperExtensions so you could just do Html.FormatFullName(Model.FirstName, Model.LastName).

public static IHtmlString FormatFullName(this HtmlHelper helper, params string[] names)
{
    return new MvcHtmlString(helper.Encode(string.Join(" ", names)));
}

It isn't considered bad practice to add html to HtmlHelperExtensions either so that's nice imho.

Upvotes: 2

jbl
jbl

Reputation: 15413

I would have my 3 view models implement a common interface IFormattablePerson featuring the fields used to calculate the fullname and rely on String.Format

This allows a very convenient way of extending display by just adding new string formats in a custom formatter.

This would lead to something like :

The common interface the View Models have to implement :

public interface IFormattablePerson: IFormattable
{
string FirstName{get;set;}
string LastName{get;set;}
}   

the same ToString() implementation, which will never change, in each View Model

public string ToString(string format, IFormatProvider formatProvider)
{
    if (formatProvider == null)
        return ToString(format, new FormatProviderIFormattablePerson());
    else
        return (formatProvider.GetFormat(typeof(IFormattablePerson)) as ICustomFormatter).Format(format, this, formatProvider);
}

This uses FormatProvider and CustomFormatter for the IFormattablePerson. Then you just need to add and implement new formats in the CustomFormatter

public class FormatProviderIFormattablePerson : IFormatProvider
{
    // String.Format calls this method to get an instance of an
    // ICustomFormatter to handle the formatting.
    public object GetFormat(Type service)
    {
        if (service == typeof(IFormattablePerson))
        {
            return new CustomFormatterIFormattablePerson();
        }
        else
        {
            return null;
        }
    }
}

public class CustomFormatterIFormattablePerson : ICustomFormatter
{
    public string Format(string format, object arg, IFormatProvider provider)
    {
        if (string.IsNullOrEmpty(format))
            format = "full";

        if (arg is IFormattablePerson)
        {
            IFormattablePerson t = (IFormattablePerson) arg;
            switch (format)
            {
                case "f": 
                    return t.FirstName;

                case "l": 
                    return t.LastName;

                case "full": 
                default:
                    return string.Format("{0} {1}",
                        t.FirstName,
                        t.LastName).Trim();
            }                   
        }
        if (arg is IFormattable)
            return string.Format(String.Format("{{0:{0}}}",format), arg);
        else
            return arg.ToString();
    }
}

Upvotes: 1

bluetoft
bluetoft

Reputation: 5443

How about in a BaseClass for all three ViewModels

public string FirstName {get;set;}
public string LastName {get;set;}
public string FullName {get{return String.Format("{0} {1}",FirstName,LastName);}}

Using a baseclass will allow you to minimize code duplication for all three ViewModels. This is also a simple solution which is easy to understand (by future developers) and quick to change. Is there something about an API which would limit this funciotonality?

Upvotes: 1

ZombieSheep
ZombieSheep

Reputation: 29963

My first thought would be to ask if your view models are directly storing the user data, or exposing a class which contains the user name. If you aren't I'd probably re-factor the username data out to its own class (along with other user data, if that makes sense to your app, then put the FormattedFullName property in that class.

public class ViewModel1()
{
    public PersonData myPerson {get; set;}
    // other properties
}

public class ViewModel2()
{
    public PersonData myPerson {get; set;}
    // other properties
}

public class PersonData()
{
    public string forename { get; set; }
    public string surname { get; set; }
    public string FormattedFullName 
    { 
        get 
        { 
            return string.Format("{0} {1}", forename, surname); 
        } 
    }
    // other properties
}

Upvotes: 2

Related Questions