简体   繁体   中英

ASP.NET MVC: Is "views must be dumb" correct statement?

Most of the good references for MVC on web strongly suggest "views must be dumb". It should not contain any logic. This does not seems valid when I try to implement it.

  • Some of my views display only first name of student and some of them display only last name and some of them display full name. My database (and POCO and DTO) store name in separate components. I see best place to format the name is view.
  • My view changes on some actions on client side without hitting server. Example, on clicking some button, it hides some part of view and shows other and disable some controls. Or another button opens new window and takes some inputs and validates it. This input is never sent to server; it is only useful for some client side activities.
  • I have validations on server side. But just to save the hit to server, I also validate on client side.
  • Data binding with KnockoutJS.
  • Based on data (start and end date) received from server, I generate table on client side to display sections of that period slicing 1 hour each. This is something scheduling like GUI. I need to do date and time calculations in view to achieve this. When I was in stone age (ASP.NET WebForms), I was generating this table on server side; I know you are shocked. I shifted it to JS for performance.
  • In SPA, view hold most of the logic by fetching only necessary data from server through AJAX.

I can put many other similar examples here those force me to put some logic in view. Considering that view still holds logic and use of JS is increasing day by day, can we still say "views must be dumb" is a correct statement?

Some details explaining the same with respect to points above will help.

Notes:

  • Though my question is based on ASP.NET, I am expecting answers referencing to ONLY MVC as a design pattern; no matter what technology I use. So please do not suggest what is another way to do validations. Points above are just to note some of the cases where logic is necessary in view.
  • There might be something wrong in how I am implementing above points. But My only point is that, use of JS (and putting logic in views as a result) is increasing.
  • Everyone is welcome to contradict above points in case I am implementing it wrong way; just do not redirect entire discussion that way.

Edit 1: @kayess: Yes, I have Models as well as ViewModels and this is obvious in MVC. Server logic that is strongly related to specific view and cannot be reused is put in ViewModels. Major part of domain logic which is reusable is put in Models. Even after having ViewModels, there are many things those I will prefer to do on client side. About narrowing the question, the basic answer to this question will be "Yes" or "No". Other details will be just to support the answer. I do not think this will attract opinions as there must be something about MVC views that I have not fully understood. The one answering the question just need to point that out to me.

I think generally by "views must be dumb" means specifically the server side part of the views. Having TypeScript/JS in a view is perfectly normal. I wouldn't however expect to have dozens of lines of C# in the view that is fetching records from a database.

However, having some very simple logic such as the following is pretty common:

@{
    if(user.IsLoggedIn)
    {
        <span>You have new messages!</span>
    }
    else
    {
        <span>You need to login to view messages.</span>
    }
}

However server side view code shouldn't get much more complicated than that because that breaks down the whole point of separation concerns and having appropriate abstractions and design patterns etc, and just becomes unmaintainable.

See also: Microsoft documentation on "Adding a View"

May it be any technology there are set of theories supporting different concepts, like you said view should be dumb there are advocates of model should be dumb.

Idea here is let your view model take care of the manipulation if any needed, and let your view refer to view model. So that change is centric.

And I believe you are alredy doing that.

This is further to the accepted answer.
I think we should centralize the rendering logic to the View part, not onto their ViewModel part. This gives several practical advantages even though theory suggests "view must be dumb":

1) Lower CPU cycles on the server since less logic.

2) Saving bandwidth as less data are passed on wire.

3) Better separation of concerns as presentation logic is centralized to the view. Server only need to pass data to the client side, effectively simplifying the coding complexity on the server side.

Conclusion:

Let the theory say "views must be dumb". Putting presentation logic on client side is good practical approach.

Although this is an old question and has an accepted answer, I want to add some points not covered in any answers.

I think you are overlooking cases where more logic can be pushed to your domain model. For example, you mention the concept of "Name" and that you must use conditional logic in your views to decide whether to show first, last or full name. I have a class called Name in my domain model. It incorporates the logic of FirstName, LastName and FullName like so:

public class Name
{  
    public Name(string firstName, string lastName)
    {
        this.FirstName = firstName;           
        this.LastName = lastName;            
    }

    public string FirstName { get; }       
    public string LastName { get; }      
   
    public string FullName
    {
        get { return $"{this.FirstName} {this.LastName}"; }
    }        
}

In my UI I have have ViewModels with the whatever name property I need. When I convert my domain models to view models my conversion logic tells the ViewModel which property to use. If I need FullName I use Name.FullName. If I just need FirstName, I use Name.Firstname. At no point do I need to put conditional logic about names in my views.

In addition, you can use custom helpers, formatters and extensions to encapsulate reusable logic for views. For example, I have utilities to format phone numbers, addresses etc, so that I do not have to put this logic in every view that needs it. I also have a paging module in my UI that encapsulates paging so that I do not have to have paging logic in my views other than to call the pager.

Partial views are also helpful. For example, from the accepted answer, I would put the following in a partial view and just call it in each view, rather than repeating the conditional logic it in every view:

@{
    if(user.IsLoggedIn)
    {
        <span>You have new messages!</span>
    }
    else
    {
        <span>You need to login to view messages.</span>
    }
}

My point is there is a lot you can do to move logic out of views to keep them dumb.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM