Where does the formatting logic belong to MVC?

Say that my phone number is stored in the database as a 10-digit string:

0000000000

And I want to format this phone number, presenting it to the user as:

(000) 000-0000

And I have an extension method in the utility assembly that handles this formatting:

static string ToPhoneNumber(this string value) { return Regex.Replace(value, @"(\d{3})(\d{3})(\d{4})", "($1) $2-$3"); } 

My question is: at what point should I apply this transformation?

1) In view:

 @Model.PhoneNumber.ToPhoneNumber() 

2) In the viewing model:

 public string FormattedPhoneNumber { get { return this.PhoneNumber.ToPhoneNumber() } } 

3) In the controller:

 userModel.FormattedPhoneNumber = userModel.PhoneNumber.ToPhoneNumber() 

4) In the domain model (same implementation as # 2)

5) In the service (same implementation as # 3)

Also, does the answer depend on whether global formatting (for example, a phone number) is required compared to isolated one-time formatting on a single view?

I would give my thoughts, but I do not want to influence any answers.

+6
source share
7 answers

I think it is the responsibility to choose the way the data is displayed. Because only the presentation knows what is available for presentation. On the other hand, it is probably easier to do in the controller. The controller would know about the user's locale. Apparently, this is very small.

+4
source

I personally like to keep things in my ViewModel because you end up looking weird looking code if you don't. Take your example.

Shaver Type:

 @using MyNamespace.Models.Extensions @model MyNamespace.Models.ViewModels.IndexViewModel @if (string.IsNullOrWhiteSpace(Model.PhoneNumber) { <div> @Model.PhoneNumber.ToPhoneNumber() </div> } 

Compared to alternative:

Shaver Type:

 @model MyNamespace.Models.ViewModels.IndexViewModel @Model.FormattedPhoneNumber 

ViewModel:

  public string FormattedPhoneNumber { get { return PhoneNumber.IsEmpty() ? "Not Available" : PhoneNumber.ToPhoneNumber(); } } 

You can definitely improve my code, but the fact is that it simplifies your views and does not clutter the branching logic.

In addition, I never claimed to be a saint, so I do not always follow my advice, but I must. Do as I say, not like me :)

+4
source

First of all, with architectural patterns in general, and especially with “separation of concerns,” the final arbiter is always “the best approach in my scenario” - I strongly believe that dogmatic commitment to the rule-set without taking into account your own plans and needs is a terrible practice. Not to mention that there is no clear consensus: depending on your variety of XYZ (MVC, MVP, MVVM), you will find opposing thoughts about what happens where everything is on the network.

However, my quick answer to the question: "Use your opinion."

Arguments for "in view":

  • he is dealing with the presentation, so this is the responsibility of the opinions.

Arguments for "in view model":

  • In general, the role of the representation model is to represent the representations of the “readiness for data binding” model; therefore, the transformation of the model data into the form directly consumed by the representation is responsible for the representation model.

Arguments for the model:

  • it may be overly general for model data; therefore, following DRY, the model will take responsibility for this view.

Arguments for the controller:

  • ... Well, I can’t think of a reasonable one here. Controllers usually react to actions, so it stretches to justify its belonging.

What I'm trying to do is that while one point of your system accepts and assumes responsibility, and this responsibility is processed exclusively by this component / layer / class, we have achieved the main goal, which is to prevent breeding / repetition / low cohesion.

My personal opinion, fwiw is likely to fall into the model of gaze or gaze. If it were WPF, I would almost certainly tell an opinion (through the providers of the formats available for wpf data binding). In the web world, I probably tend to believe, although a strong argument for the model exists - say that now you want to expose this data using the REST / JSON / etc service: you can easily deal with this change (if you want to return formatted data, that is)

TL / DR: It really depends; follow common sense and use your judgment. The most important part and any logic connected with it is an important part, and ask any dogmatic / command words "Thou Shalt".

+2
source

Depending on a few things that you define in the ViewModel, do you follow the MVCVM * (homing) MVCVM * method, in which you will have a ViewModel specific to your view, in addition to your domain models?

If so, the VM can certainly contain formatting logic, that is, the whole goal is to have this view model, primarily for the view model. So option 2.

However, the reasoning for this is that formatting yourself will start with the DRY principle if you format like this:

 @Regex.Replace(Model.PhoneNumber, @"(\d{3})(\d{3})(\d{4})", "($1) $2-$3"); 

Since you have an extension method, there aren't many problems calling the formatter in your view at all, but I still prefer to do it in a dedicated virtual machine.

If your virtual machine is really a domain model containing raw data (see this , template 1), then this must be in your View, so Option 1. Just note that if you use this template, I would suggest against him, since he makes your view strongly connected with a low-level object, you better abstract it to what you need. that your connections between the domain model model + View are really strong (i.e. compiled at compile time, not at run time!).

First of all, it certainly should not be in your domain model.

* Model, View, Controller, ViewModel. If the ViewModel contains the data that should be used in your view, in the format in which it is required.

0
source

I would put this in the viewmodel, not the view. The view is intended only for presenting data / information to the end user. Maintaining a separation of problems ensures that each object is as independent as possible. If you pass formatted numbers to a view, the view has nothing to do with what should be displayed, just display the formatted numbers.

0
source

I would say that this is modeling, not formatting. If the receiving application needs to reformat the order, interval or capitalization of these fields, it must first split one field into several separate fields.

This should be a level of service. We are talking about a scheme, not a format. The application requires that the fields be separated as part of the data contract. Where this separation takes place should be at the application level that your application consumes.

The service layer should try to add metadata to the information through the schema.

For example, if I get a phone number from a data contract as follows: 1234567890

The following are the presentation requirements: (123) 456 - 7890

The service level should break the phone number into its elements

 <PhoneNumber> <CountryCode>1</CountryCode> <Area>123</Area> <Prefix>456</Prefix> <LineNumber>7890</LineNumber> </PhoneNumber> 
0
source

Option 1 is the best, followed by 2. In the controller, you must actually remove the formatting to send it to the service level, so neither the domain model nor the service model are aware of formatting.

-1
source

All Articles