I have a razor macro where i list sub nodes from a page. I the need to use an image defined on each node as a background. But the macro crashes when i move the razor code to the "logical" place in the code flow.
I have this:
@if (CurrentPage.Children.Where("Visible").Any())
{
<div class="row">
@foreach (var childPage in CurrentPage.Children.Where("Visible"))
{
<div style="background-image:url('')">
@if (string.IsNullOrWhiteSpace(@childPage.ImageId.ToString()) == false){
var image = Umbraco.Media(@childPage.imageID.ToString());
var path = image.umbracoFile;
var theimage = @image.GetCropUrl("umbracoFile", "topbillede");
}
</div>
}
</div>
}
This code works, but is executed after the div i need to set the background on. So i cant set the background. If i move the Media code before the div like this:
@if (CurrentPage.Children.Where("Visible").Any())
{
<div class="row">
@foreach (var childPage in CurrentPage.Children.Where("Visible"))
{
@if (string.IsNullOrWhiteSpace(@childPage.ImageId.ToString()) == false){
var image = Umbraco.Media(@childPage.imageID.ToString());
var path = image.umbracoFile;
var theimage = @image.GetCropUrl("umbracoFile", "topbillede");
}
<div style="background-image:url('@theimage')">
Hello world
</div>
}
</div>
}
@if (CurrentPage.Children.Where("Visible").Any())
{
<div class="row">
@foreach (var childPage in CurrentPage.Children.Where("Visible"))
{
if (string.IsNullOrWhiteSpace(@childPage.ImageId.ToString()) == false){
var image = Umbraco.Media(@childPage.imageID.ToString());
var path = image.umbracoFile;
var theimage = @image.GetCropUrl("umbracoFile", "topbillede");
}
<div style="background-image:url('@theimage')">
Hello world
</div>
}
</div>
}
If so, it's because you've opened the Razor block with @foreach so you're 'in' razor at that point so there's no need to have the @ in front of the 'if' statement.
Yeah it does... but i still cant use the variable i set, because its ouside the closing bracket of the if statement..
And putting the opening div tage inside the if statement causes an error:
if (string.IsNullOrWhiteSpace(@childPage.imageID.ToString()) == false){
var image = Umbraco.Media(@childPage.imageID.ToString());
var path = image.umbracoFile;
var theimage = image.GetCropUrl("umbracoFile", "topbillede");
<div style="background-image:url('@theimage')"> }
Ah, then you just need to delare your variables outside of the if too, so they're scoped beyond the 'if' statement. Declare them above the if, then set their values inside the if, and see if that works. Something like this (untested):
@if (CurrentPage.Children.Where("Visible").Any())
{
<div class="row">
@foreach (var childPage in CurrentPage.Children.Where("Visible"))
{
var image;
var path;
var theimage;
if (string.IsNullOrWhiteSpace(childPage.ImageId.ToString()) == false){
image = Umbraco.Media(childPage.imageID.ToString());
path = image.umbracoFile;
theimage = image.GetCropUrl("umbracoFile", "topbillede");
}
<div style="background-image:url('@theimage')">
Hello world
</div>
}
</div>
}
Yep, totally different kettle of fish. XSLT is declarative and Razor is essentially C#, which is procedural. I'm still moving over from XSLT too - it'll make sense eventually :) The difficulty I'm having personally is getting the separation with Razor so it doesn't turn into spaghetti.
Secondly, I've not used the crop methods yet so not sure what that returns, but the principle would be that you'd make the whole background statement a variable, so something along these lines (note, this obviously doesn't use the cropping stuff but it shows the basic principle):
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@{
Layout = "Master.cshtml";
var image = Umbraco.Media(CurrentPage.topbillede.ToString());
var path = image.umbracoFile;
// Instantiate background image variable
string backgroundImage = "";
// If the image path has a value, create background image value
if(!String.IsNullOrEmpty(path)){
backgroundImage = "background: url(" + path + ");";
}
}
<div style="@backgroundImage">
<p>Hello world</p>
</div>
So, you get your path to the image; if it has a value then you use this value and combine it into a variable along with the CSS background property. Then you just call that variable in the style attribute. I think in the later versions of razor it's even smart enough to not render the style attribute if it has an empty value.
Understanding nesting of Razor code
I have a razor macro where i list sub nodes from a page. I the need to use an image defined on each node as a background. But the macro crashes when i move the razor code to the "logical" place in the code flow.
I have this:
This code works, but is executed after the div i need to set the background on. So i cant set the background.
If i move the Media code before the div like this:
The macro crashes... Why?
Hi Claus,
Does this fix it:
If so, it's because you've opened the Razor block with @foreach so you're 'in' razor at that point so there's no need to have the @ in front of the 'if' statement.
Hope this helps.
Yeah it does... but i still cant use the variable i set, because its ouside the closing bracket of the if statement..
And putting the opening div tage inside the if statement causes an error:
Ah, then you just need to delare your variables outside of the if too, so they're scoped beyond the 'if' statement. Declare them above the if, then set their values inside the if, and see if that works. Something like this (untested):
hmmm, ok... Im used to xslt where the macro will crash if the parameter is undefined.
I guess razor just returns nothing if the parameter is undefined...
Yep, totally different kettle of fish. XSLT is declarative and Razor is essentially C#, which is procedural. I'm still moving over from XSLT too - it'll make sense eventually :) The difficulty I'm having personally is getting the separation with Razor so it doesn't turn into spaghetti.
Hope that sorted your initial problem anyway.
Ok, im back. I'm not getting it 100%. Now in aother context. On a template...
Could you explaing why this doesnt work?
And what if i wanted to check if "topbillede" is defined and only render the style tag inside the div if it was true???
Hi Claus,
Firstly, the variables need to be inside the razor context, so this should work:
Secondly, I've not used the crop methods yet so not sure what that returns, but the principle would be that you'd make the whole background statement a variable, so something along these lines (note, this obviously doesn't use the cropping stuff but it shows the basic principle):
So, you get your path to the image; if it has a value then you use this value and combine it into a variable along with the CSS background property. Then you just call that variable in the style attribute. I think in the later versions of razor it's even smart enough to not render the style attribute if it has an empty value.
I found this article helpful at first - it's well worth reading all the way through and trying to understand as it'll save you a lot of time in the long run: http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx.
First example makes TOTAL sense, and work perfectly! thanks.
Second one gives an error. Its not very pleased with the
Saying:
Implicitly-typed local variables must be initialized
I've edited the example above...
Bookmarked your link for further studies, thanks :)
I ended up with this which works:
is working on a reply...