by Damiaan Peeters
11. January 2013 08:58
It is possible to use Embedded macro scripts in master pages. You know:
<umbraco:Macro runat=”server” language=”cshtml”>
@Model.Name
</umbraco:Macro>
I’ve seen a lot of these chunks of code in masterpages. Although you might LOVE Razor, there is no reason for you to do this!
First of all, you could solve the previous line simple with a <umbraco:Item /> tag in your master page. Secondly, Umbraco released version 4.10 with MVC capabilities. So you don’t need to use the Masterpages anyway. Do you? Thirdly, u can still use inline code. I know the documentation says it’s not a recommended way, but it’s fast and for easy master page related things I think perfectly fine. <% if(condition) umbraco.NodeFactory.Node.GetCurrent().GetProperty(…).Value %> This doesn’t involve a creation overhead for each Razor macro which is being called.
But here are my personal reasons why I don’t like them:
- Visual studio problems: if coding embedded macro’s in visual studio you have
- no intellisense
- bad syntax highlighting
- impossible errors & bizar warnings
- automatic formatting shortcut screws up everything. In VS, you can use CTRL + K , CTRL + D to format your code automatically. Your embedded macro’s will probably screws up regularly.
- Hard(er) to configure cache parameters. Did you ever tried to cache by page or by member?
- Having to macro’s running next to each other:
…
</umbraco:Macro>
<umbraco:Macro runat="server" language="cshtml">
… - You can’t set a break point and really DEBUG what might be going wrong in your code.
- When you ARE debugging
- you end up in separate files and you do not know which masterpage you are exactly debugging
- you can and will change - by accident – temporary generated razor scripts
Most of the time I use these rules on how we use Razor Macro’s in Umbraco:
- Create separate files in the MacroScripts folder.
- If performance is importance convert Model to DynamicNode instead of working with DLR objects
- Add @Inherits & @using umbraco.MacroEngines to optimize Visual Studio Experience
- Use Helpers where possible
- Extend @Library or create own extensions in App_Code or even better: a custom .Net dll with your code precompiled
- Choose between @umbraco.library.GetDictionaryItem(“theDictKey”) and @Dictionary.theDictKey and don’t use both.
- Follow coding standards which are normally applied in normal .Net code. For razor I prefer { on the same line (see post of scottgu introducing Razor). But don’t mix!
- If you really need an embedded macro and want a break point, use @{ System.Diagnostics.Debugger.Break(); }
Oh. And check out the umbraco development guidelines on our, they are there for you to read.
What do you think? Do you agree? What are your best practices for umbraco and Razor macro’s.
by Damiaan Peeters
15. April 2012 19:38
Sometimes you get tired of reinventing the wheel. Every time I start typing code using the XpathNodeIterator classes I have that feeling. Every time I search a few minutes for a better solution, but the only solution is the umbraco.library.GetPrevalues() .
So I copied the code from there into a .Net class. I created it as a Razor extention, and copied the values into a dictionary.
namespace MyRazorStuff {
public static Dictionary<int, object> GetPrevalues(this RazorLibraryCore library, int dataTypeId) {
XPathNodeIterator preValueRootElementIterator = umbraco.library.GetPreValues(dataTypeId);
preValueRootElementIterator.MoveNext(); //move to first
XPathNodeIterator preValueIterator = preValueRootElementIterator.Current.SelectChildren("preValue", "");
var retVal = new Dictionary<int, object>();
while (preValueIterator.MoveNext()) {
retVal.Add(Convert.ToInt32(preValueIterator.Current.GetAttribute("id", "")), preValueIterator.Current.Value);
}
return retVal;
}
}
Why does it mean? After I add a using statement to the RazorScript
@using MyRazorStuff
I can now make a dropdownbox in a razorscript from the datatype prevalues pretty easily:
@{
var myvalues = Library.GetPrevalues(GsTehuurTekoopDataTypeId);
if (myvalues.Count > 0) {
<select id="ohyeahbaby">
@foreach (var item in myvalues) {
<option value="@item.Key">@item.Value</option>
}
</select>
}
}
How about that? Please share your thought. Is it wrong to use a dictionary in favor of a XPathNodeIterator? Should be using a direct database connection much faster?