What does an @functions code block in a razor file do, and when (if ever) should I use it?
Asked Answered
M

4

43

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?

Maples answered 20/12, 2012 at 15:22 Comment(2)
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.Oligopsony
@Oligopsony - 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.Retain
R
60

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.

Retain answered 20/12, 2012 at 15:44 Comment(5)
+1. This is a great answer. There is a case for using @functions, but not very often!Dhole
Great answer, especially the part about explaining alternatives you should use :DAnserine
hi Bobson, you mean we can't use @functions block in other files?Meggie
@GeorgiKovachev - As far as I know, that's correct. The contents of an function block are only valid in the same file. I've never actually tried it, though, so it's possible there's some variant you can use to include a different file's functions. I'd find it very strange, though.Retain
@GeorgiKovachev you can create Razor helpers, instead of functions, if you want to use them in other Views. Do no forget to place those @helpers in App_Code in order to make them globally visible. Then you can use those helpers in any View, by prepending them with filename which contains that Razor helper.Kaisership
A
8

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.

Apron answered 20/12, 2012 at 16:14 Comment(0)
S
0

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

Supat answered 20/12, 2012 at 15:31 Comment(0)
C
0

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.

Cyanamide answered 20/12, 2012 at 15:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.