42
votes

Whilst looking at a theme I downloaded from the Orchard CMS gallery, I noticed that a Layout.cshtml file had this block of code at the top of the file:

@functions {
// To support the layout classifaction below. Implementing as a razor function because we can, could otherwise be a Func<string[], string, string> in the code block following.
string CalcuClassify(string[] zoneNames, string classNamePrefix)
{
    var zoneCounter = 0;
    var zoneNumsFilled = string.Join("", zoneNames.Select(zoneName => { ++zoneCounter; return Model[zoneName] != null ? zoneCounter.ToString() : ""; }).ToArray());
    return HasText(zoneNumsFilled) ? classNamePrefix + zoneNumsFilled : "";
}
}

I know what the declared function does (calculates which zones are populated in order to return the width of each column), my question is- what is the correct use of the @function block, and when should I ever use it?

4
Personally I think it should be avoided as it just muddies the waters in what is you presentation/view layer and what is your business controller/layer.Liam
@Liam - I disagree. I think it should expressly be used for purposes of avoiding muddying the waters. In this example, it's for purposes of determining column width, which is not something the controller should even know about.Bobson

4 Answers

58
votes

The @functions block lets you define utility functions directly in the view, rather than adding them as extensions to the @Html helper or letting the controller know about display properties. You'd want to use it when you can meet these conditions:

  1. The functionality is tied closely to the view and is not generally useful elsewhere (such as "How wide do I make my columns").
  2. The functionality is more than a simple if statement, and/or is used in multiple places in your view.
  3. Everything that the function needs to determine it's logic already exists in the Model for the view.

If you fail the first one, add it as a @Html helper.

If you fail the second one, just inline it.

If you fail the third one, you should do the calculation in your controller and pass the result as part of the model.

6
votes

Others have explained what @functions does so I won't rehash that. But I would like to add this:

If your view is typed to a viewmodel, I think a viable option would be to move this logic into the viewmodel to avoid cluttering your markup with too much code. Otherwise your views start to look more and more like classic ASP and I don't think anybody wants that.

I don't think there's anything wrong with using @functions or @helper in your view, but once you get beyond a couple of methods in your view, or even if the function is somewhat complicated, it might be worth refactoring to the viewmodel if at all possible. If it's code that can be reused, it may be a good idea to to pull it out into a helper class or an extension to the HtmlHelper class. One thing that is a bummer is realizing you just rewrote a piece of code that already existed because you didn't know it was hidden away in some arbitrary view.

0
votes

From msdn blogs, @functions block is to let you wrap up reusable code, like the methods and properties

0
votes

In this particular case, the people who have created the theme you are using probably were trying to keep it as a simple theme (only views, css and images).

If you need to write some code for a theme for Orchard, you have to turn to a module (as stated here: http://docs.orchardproject.net/Documentation/Anatomy-of-a-theme) unless you write this code in the view.

I am not sure it is worth the time to switch from a theme to a module only to get the size of a column.