0

I'm new to MVC (previously using WebForms) and there is one thing I can't seem to find an answer for... Where do you put all the methods that help control the layout?

A lot of the info I've read seems quite contradictory... Most people say you never have any methods inside models or controllers but others say you can? I've also read you shouldn't have methods in a view either. If you can't have methods in Models, Controller or Views then how do you construct any page layout?

It's easy enough to build separate class files with the required methods but then how do you access these in the view?

I understand MVC separates all the concerns but it seems quite difficult to manipulate the view HTML if you only have the model data. The Model usually contains lots of ID and Boolean values which are not for display purposes.

For example I may want to change a specific URL link in the view based on multiple values from the model.

The model may contain values like this:

  • Type = "Country"
  • ID = 75

I would then build the URL based off these values... previously in WebForms this would have been in the code behind but this now doesn't exist in MVC... so what is the best practice in MVC for this?

Dan88
  • 51
  • 2
  • 9
  • If you search google for "asp.net mvc tutorial", there are lot of excellent tutorials which will help you understand and build an mvc app from scatch. the official asp.net web site has nice tutorials. check those out. Good luck – Shyju Nov 18 '15 at 17:22
  • You can dynamically build page output with [Helper classes](http://stackoverflow.com/questions/5052752/adding-your-own-htmlhelper-in-asp-net-mvc-3), [Child Actions](http://stackoverflow.com/questions/12530016/what-is-an-mvc-child-action), [Partial views](http://stackoverflow.com/questions/18872512/what-is-the-point-of-partial-views-in-asp-net-mvc), and [View Models](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc). Whether or not to include methods with models is arguable. – Jasen Nov 18 '15 at 18:00

4 Answers4

1

You can create a view model which will contains all methods/properties used by the view.

For example, you will have :

In the view model :

public bool IsTitleVisible() {
    return ... // Algorithm to compute whether the title must be visible, based on other view models properties
}

In the view :

<div class="main">
    @if(Model.IsTitleVisible() {
        <div class="title">@Model.Title</div>
    }
</div>

This will allow you to have a lighter and readable view.

If you using view models, the code must be separate as following :

  • Controller : It recovers the model, create the view model with the model, and passes it to the view
  • Model : Contains all business properties. It must be totally independent of the HMI.
  • View Model : Contains all methods/properties used to build the view. It's created using the model properties.
  • View : It will indicates how to render the view model.

Then you can add other layers to manage data access, business logic, etc...

Paul DS
  • 859
  • 7
  • 13
  • So could I have a method in a class file that could help construct a value in View Model? I could then just have "@Model.NewValue" in the view – Dan88 Nov 18 '15 at 17:20
  • Exactly. A simple example is to display a full name. You have a property in your view model which returns the firstname + the lastname, with uppercase etc... In the view, you just have to display the fullname property of the view model. – Paul DS Nov 18 '15 at 17:23
  • Remember that, in addition, is a good choice create a class/library (well unit-tested) that talks about your app "domain", or "business logic", the "problem" application is resolving. If not your controllers/views/modelviews will become unmainteinable. this is called DDD (Domain Driven Development) – fiorebat Nov 18 '15 at 17:40
1

The role of Model in a MVC application is to define the relationship between class and database. Keep this simple by adding properties which is eventually used by controller to transfer data to views.

Now you have few ways to go ahead:

  1. Add your new properties like PopulatedURL (a string with a getter only) - that is populated on the fly based on other property values in the model itself. In this case, your model will have this new member and may not be consumed by all the views.
  2. Populating/computing something just for viewing purpose is something user-interface related as the end result i.e. dynamic URL doesn't need to be saved in database. You have two options here: Just concatenate the required values and build a URL with an anchor tag directly in the view (by using URL helper or String format as the base url will always be same).

Or

Create a view-model class which is just for current view. Here you can create anything - properties, methods, etc. that is needed for this view. I use this second approach when my view needs something more that my Model doesn't have and I don't want to add extra members to Model just because one view in my app needs more information.

Depending on the complexity of your project/views, create a view-model (VM) for your view. It will exist just for your view, but your Model can exist for 'n' number of views and is reusable without any extra members defined. Also, it gives you flexibility to add extra members that a linked view needs.

If you follow the second approach, instead of giving model to the view, give view-model to the view. If you don't want to add duplicate properties, refer to Automapper tool that is really good for this case, as the name suggests, it maps properties and much more. This is really good, if you have many properties to map. You can map manually as well but this little tool is a time saver.

KKS
  • 3,600
  • 1
  • 27
  • 54
0

It can take while to get your head around the differences, but it is worth it!

Firstly, models should only have the model data, not methods. However, you can use HTML Helpers, which you can extend to create your own. You can then use these, as you would have done with functions in the code behind page.

Karl Gjertsen
  • 4,690
  • 8
  • 41
  • 64
  • "models should only have the model data" Why? – Kenneth K. Nov 18 '15 at 17:03
  • I've always kept the data in the models to the minimum. They pass the data around and shouldn't have lots of methods within them. That's not to say that extra processing can't be done and added to the model. – Karl Gjertsen Nov 18 '15 at 17:05
0

It seems that because you are using your domain models as view models (and not separating the two) you are running into problems when displaying data. You should map your domain model (or domain models) to a single view model specific to the view in question. That view model should ideally contain only the information required to display that specific view.

Therefore, at a basic level, a request should come into the controller for a page. The controller should coordinate with the business layer which should perform any business operations and to retrieve any domain model for a specific business use case. This data should then be mapped to a view model and passed to the view for rendering.

To clarify:

View:

The views responsibility is to display information from the view model. Whilst it is possible to create methods in the view using inline syntax (e.g. Razor & C#) it is (IMO) better not give the view too much responsibility (see Single Responsiblity Principle) and only have the view render the information provided by the model. At the point of rendering, the model should ideally contain all information that is required by the view and should not have to perform any additional business logic.

At this level, you can have HTML Helper methods to help to render HTML but (as the name suggests) these should just be methods to help display HTML and should not perform business logic. The business logic should have already been performed in your business layer.

You can also help control the layout using _Layout views, partial views and child actions.

View Model:

I believe it is acceptable for the view model to have methods or properties on them as long as (as previously mentioned) they do not perform business logic. The logic performed by methods here is logic operating on the information in the view model as a convenience to the view.

As for your specific question regarding creation of a url in the view; one possiblie way of performing this would be to have the view model provide the dynamic information to create the url (e.g. the type, the id, etc.) and then to use the Html.ActionLink helper or Url.Link (or similar) helpers to render the link as necessary.

Community
  • 1
  • 1
Dangerous
  • 4,818
  • 3
  • 33
  • 48
  • I would suggest that composing a `FullName` from a first and last name is not something that a specific view model should do *unless* it is the only place in the whole system that needs to know how to do this action. Otherwise, I think there should be code elsewhere that can be reused over and over. – ErikE Nov 18 '15 at 18:23
  • ErikE - I agree. I guess this is business logic really and didn't really consider my example. I will update my example to something more appropriate. – Dangerous Nov 18 '15 at 18:41
  • I can't really think of an example right now so I have removed instead. – Dangerous Nov 18 '15 at 18:48