Macro broken after upgrade to 4.10 - razor

I recently upgraded from 4.09 to Umbraco 4.10. I have a pretty common/simple little macro that I use to generate my top navigation. I check the record to see if it's the last in the count, and if not add a pipe symbol as a visual separator.
This worked as expected with all version thru 4.09 but after upgrade all item get the pipe symbol even the last one.
#inherits umbraco.MacroEngines.DynamicNodeContext
#{
var level = String.IsNullOrEmpty(Parameter.Level) ? 1 : int.Parse(Parameter.Level);
var ulClass = String.IsNullOrEmpty(Parameter.UlClass) ? "" : String.Format(" class=\"{0}\"", Parameter.UlClass);
var parent = #Model.AncestorOrSelf(level);
var pages = parent.Children.Where("Visible");
if (parent != null) {
<ul class="topNav">
#foreach (var item in pages) {
var selected = Array.IndexOf(Model.Path.Split(','), item.Id.ToString()) >= 0 ? " class=\"selected\"" : "";
if (item != (pages.Last()))
{
<li#Html.Raw(selected)>
#item.Name |
</li>
}
else
{
<li#Html.Raw(selected)>
#item.Name
</li>
}
}
</ul>
}
}
I'm not sure what changed, but it seems like (in my code) pages.Last() is never true.
Anyone have any ideas? - Thanks

You should be able to get the result you want by using the IsNotLast() helper, like so:
<li#Html.Raw(selected)>
#item.Name#(item.IsNotLast() ? " |" : "")
</li>
Refer to the Umbraco Razor Feature Walkthrough–Part 7 for more information on the IsHelpers that are available. They're pretty handy when you want information about the nodes you're traversing.

I ended up going at it a little bit differently, but I still have no idea why this changed.
instead of
if (item != (pages.Last()))
I went with
if (item.Index() != (pages.Count()-1))
solved for now, but I welcome any feedback if anyone else stumbles on this issue

Related

VS2013 Razor and Format Document

Formatting this part of code via Ctrl+E, D:
if (row % 3 == 0)
{
#:</div>
}
gives me:
if (row % 3 == 0)
{
#:
</div>
}
which makes my .cshtml document invalid.
Any suggestions on how to prevent this in VS2013, but that my other code still gets proper formatting using Ctrl+E, D?
I get the same issue as you. The only way I managed to stop it was by rewriting it like this (you won't need the initial # before the if as long as you are already in a code block, but I did when I pasted it into my page to test it):
#if (row % 3 == 0)
{
#Html.Raw("</div>")
}
I first learnt about using #: as a replacement for when #Html.Raw didn't work.

On every children add 1 (+1) Umbraco Razor

In the code below i need it to add (+1) on every children on data-slide-index="0".
Starting at 0 and then 1,2,3,4,5
It should look like this:
data-slide-index="0"
data-slide-index="1"
data-slide-index="2"
I am thinking something like this.
int theCount = 0;
theCount += 1; // Adds 1 to count
But I dont know how to use it correctly in the code.
#foreach (var image in #Model.Children)
{
foreach (dynamic d in image.imageDampSingle)
{
<a data-slide-index="0" href="#DAMP_Helper.GetImageCropperUrl(d, "projectSingle")"><img src="#DAMP_Helper.GetImageCropperUrl(d, "projectSingleThumb")" title="#Model.captionText" alt="#d.Image.nodeName" /></a>
Or is there a easier / another way to do this?
Thanks in advance!
//René
Razor is just a view engine, you are using C# code in there to do some logic operation. Recursive methods are algorithmic operations that have the capability to call themselves until a certain condition is satisfied. You can use a helper in this case to achieve that. An example for your case:
#helper DoSomething(IEnumerable<Something> myList)
{
foreach (var item in myList)
{
#item.CertainProperty
#if (item.Children.Any())
{
#DoSomething(item.Children)
}
}
}
Learn and read about recursion, and a whole new world of fundamental concepts will appear.
http://en.wikipedia.org/wiki/Recursion_(computer_science)
http://learnyousomeerlang.com/recursion
It's a fundamental topic, I was actually programming some snippets right now when I read this topic, where's other example in Python:
def contaVogais(cadeia):
if not cadeia:
return 0
return (1 if cadeia[0] in 'aeiou' else 0) + contaVogais(cadeia[1:])
As you can see by the examples, recursive solutions are usually more elegant, but in some cases might have a decrease the code performance.
I found a solution. See below:
#{
var countNum = -1;
}
#foreach (var image in #Model.Children)
{
{
countNum += 1;
}
foreach (dynamic d in image.imageDampSingle)
{
<a data-slide-index="#countNum" href="#DAMP_Helper.GetImageCropperUrl(d, "projectSingle")"><img src="#DAMP_Helper.GetImageCropperUrl(d, "projectSingleThumb")" title="#Model.captionText" alt="#d.Image.nodeName" /></a>
}
}
You are welcome to comment on it regarding improvement of the code.
//René

Displaying Mediapicker field in blogpost.list.cshtml in Orchard CMS

I'm trying to edit the page when my blog displays the Parts.Blogs.BlogPost.List.cshtml. I went to ContentItems under content and added a MediaPicker Field called BlogPostImage to my BlogPosts, and I also made an alternate to Parts.Blogs.BlogPost.List.cshtml in my theme (which is the file I'm editing. The code that I have in there is:
#using Orchard.ContentManagement;
#{
IEnumerable<object> blogPosts =
Model.ContentItems;
}
#if (blogPosts == null || blogPosts.Count() < 1)
{
<p>#T("No posts.")</p>
}
else
{
int count = 0;
<div id="Blog">
<div id="slides">
<div class="slides_container">
#foreach (dynamic post in blogPosts)
{
count++;
string title = post.ContentItem.TitlePart.Title;
ContentItem item = post.ContentItem;
string text = post.ContentItem.BodyPart.Text;
string postImageUrl = post.BlogPostImage.Url;
<div class="slide">
<img src="#postImageUrl" width="625" height="400" alt="Slide #count.ToString()">
<div class="caption" style="bottom: 0">
<h4>#title</h4>
</div>
</div>
}
</div>
</div>
</div>
}
I cannot however figure out how in the world to call that mediapicker field into my list. Any way I try it comes back blank with some kind of querystring in the href. Something like "?23423455657". I took off the variable and that querystring still shows up. What I'm basically trying to accomplish is to put these into a slideshow, with the jquery to start the slideshow in the layout.cshtml. TIA
//SOLUTION:
After days and days of reading and researching I finally found a working solution.
Replacing:
string postImageUrl = post.BlogPostImage.Url;
With:
string postImageUrl = ((ContentItem)post.ContentItem).Parts.SelectMany(p => p.Fields).Where(f => f.Name == "BlogPostImage").First().Storage.Get<string>(null);
Got it from here: http://blog.cloudconstruct.com/post/Creating-a-rotating-image-gallery-in-Orchard-CMS.aspx
I hope it helps anyone stuck in the same boat. I am still curious why I couldn't simply call it the way I had it, but it's working now! :)
You can get the image url using dynamic:
dynamic postItem = post.ContentItem;
var postImageUrl = (string)postItem.BlogPost.BlogPostImage.Url;
Content item, when used as a dynamic object, exposes all its parts (here we're using the part that has the same name as the type, and where the fields are added when adding them from the admin). The part itself has dynamic members for each field (here, BlogPostImage), and from there you can get to the field's properties (Url here).
I tried the above answer with version 1.7 with no joy. I ended up having to download a copy of the source so I could delve into the objects. The below code got me the information I needed and also will help in future when I add extra fields to other content. I used part of the above answer to get to my solution...
IEnumerable<object> blogPosts = Model.ContentItems.ContentItems;
foreach (dynamic post in blogPosts) {
dynamic q = ((ContentItem)post.ContentItem).Parts.SelectMany(p => p.Fields).Where(f => f.Name == "BlogPostImage").First();
string postImageUrl = q.MediaParts[0].MediaUrl;
<img src="#postImageUrl" />
}
Hope this helps somebody.

Umbraco MediaById not working as expected

Trying to display a set of images from uComponents' MNTP, and can't get a value for the umbracoFile property - in the example below, both umbracoFile and url return empty strings:
foreach (var id in #Model.sliders) {
var media = Model.MediaById(id.InnerText);
if (media != null){
var url = media.umbracoFile;
<p>name = #media.Name</p>
<p>alt = #media.altText</p>
<p>url = #media.umbracoFile</p>
<p>url = #url</p>
}
}
It's getting really really really annoying... I've worked around it in other areas like so, using Model.Media:
<img src="#Model.Media("topRightImage", "umbracoFile")" alt="#Model.Media("topightImage", "altText")" />
But that will only help if with the media picker data type, not mntp. It shouldnt' be that difficult, should it?
I can get the images to load if I rebuild the internal search index, but they're gone again on subsequent refreshes.
I've seen others having similar problems, and would really appreciate a solution...
ta
Nathan
This looks like a bug that was fixed in 4.7.2. See the following codeplex item:
http://umbraco.codeplex.com/workitem/30778

Linq to SQL : How do I get the property values from a query's results?

I m just starting with microsoft (MVC,C#, LINQ), so far so good, but i have a question about LINQ uses, How do i get the value form a LINQ like this one?
var x = from a in db.tablex
where a.eventID == eventID
select new
{
owner = a.owner,
shipper = a.shipper,
consignee = a.consignee
};
I try something like "r.owner" inside a foreach to get the value retrieved from DB
foreach (var r in x)
but its not working.. i dont get intellisense either.. how do i get the value??. I saw several examples and it seems to work like this, but for some reason its not working.. Thanks
Ok guys here was the thing, (it wasnt the typo it was just in the post), i was missing a using :
using System.Reflection;
with this C# automatically creates a class from them, and now it works
What a noob of me =).
foreach (var r in x)
{
var owner = r.owner;// not x.owner
}