0
votes

I am using Orchard 1.8 and have created a new content type (called PressRelease), query for the results and projection to view the query with a custom template (using URL Alternates in the format List-ProjectionPage-url-PressRelease.cshtml) and all of that is working fine.

The one part that has me stumped is, if I use The Theme Machine as my theme (untouched), this projection view will show up in an unordered list with the corresponding AutoRoute links to the individual ContentItem entities, their metadata and so on. I'm trying to figure out how I access things such as the AutoRoute URL for a specific item, the metadata (create/publish dates) and so on for use with things like a Facebook Share button. Essentially I'm trying to recreate that default view, albeit with customizations.

Here is the code for List-ProjectionPage-url-PressRelease.cshtml:

@using Orchard.Utility.Extensions;
@using System.Linq

@functions
{
public class PressRelease
{
    public PressRelease()
    {
        this.Attachments = new List<Attachment>();
    }

    public string Title { get; set; }
    public string Source { get; set; }
    public DateTime PublishDate { get; set; }
    public string Body { get; set; }
    public List<Attachment> Attachments { get; set; }
}

    public class Attachment
    {
        public string Filename { get; set; }
        public string Path { get; set; }
    }
}

@{
    //add list of dynamic objects to strongly typed class
    var releases = new List<PressRelease>();
    foreach (var item in @Model.Items)
    {

    var release = new PressRelease
    {
        Title = item.ContentItem.TitlePart.Title,
        Source = item.ContentItem.PressRelease.Source.Value,
        PublishDate = item.ContentItem.PressRelease.Date.DateTime,
        Body = item.ContentItem.BodyPart.Text
    };

    //load attachment(s) to class
    var attachments = (Orchard.MediaLibrary.Fields.MediaLibraryPickerField)item.ContentItem.PressRelease.Attachment;
    if (attachments.MediaParts.Count() > 0)
    {
        foreach (var part in attachments.MediaParts)
        {
            release.Attachments.Add(new Attachment { Filename = part.FileName, Path = part.MediaUrl });
        }
    }

    releases.Add(release);
    }
}
@{
foreach (var item in releases)
{
    <div class="press-release">
        <div class="press-release-title">@item.Title</div>
        <div class="press-release-meta">
            <span class="press-release-source">Source: @item.Source</span>
            @if (item.PublishDate != DateTime.MinValue)
            {
                <span class="press-release-date">@item.PublishDate.ToShortDateString()</span>
            }
        </div>
        @if (item.Attachments.Count() > 0)
        {
            <div class="press-release-attachments">
                <span class="press-release-attachments-title">Attached: </span>
                @foreach (var attachment in item.Attachments)
                {
                    var linkText = attachment.Filename;
                    var url = attachment.Path;
                    @Html.Link(linkText, url);
                    if (attachment != item.Attachments.Last())
                    {
                        <span>, </span>
                    }
                }
            </div>
        }
        <div class="press-release-body">
            <p>@Html.Raw(item.Body.Replace("\r\n", "<br />"))</p>
        </div>
    </div>
    <div class="social">
        <!-- ** This is where I need AutoRoute URL so I can do FB share link **-->
        <div class="fb-share-button" data-href="" data-type="button_count"></div>
    </div>
    if (item != releases.Last())
    {
        <hr />   
    }
}
}

Thoughts?

1
Why are you trying to do everything from a single template, instead of letting each item and part do its job? The problem with such an approach is that you're opting out of all that makes Orchard great, like composition of the views. If you must, however, you can read this: weblogs.asp.net/bleroy/so-you-don-t-want-to-use-placement-info, and this: weblogs.asp.net/bleroy/…Bertrand Le Roy
Honestly, it'd be my lack of understanding on how all of this comes together. I'm trying to play with the ShapeTracer to see if I can get a better understanding on how all of these components come together, but it's erroring out as well when used with our custom theme. Let me try to dig more into placement.info and see if I can better understand how you're piecing everything together. I'm not sure placement.info would help me with the Facebook Like option though, so how can I at least gain access to the AutoRoute URL for generating that piece?Scott Salyer
Using Shape Tracer on Theme Machine helped me solve the above - ContentItem.AutoroutePart.Path had exactly what I was looking for.Scott Salyer
Shape tracer is a great help when it works :) If it didn't before, it was probably for using a theme lacking support for it (which just amounts to having a Foot zone IIRC).Bertrand Le Roy

1 Answers

0
votes

Utilizing the Shape Tracer (in conjunction with @Bertrand's assistance in the comments above) helped me get to where I need. Here is the final layout code I went with (which has some super hacky stuff in it):

@using Orchard.Utility.Extensions;
@using System.Linq

@functions
{
    public class PressRelease
    {
        public PressRelease()
        {
            this.Attachments = new List<Attachment>();
        }

        private string _NavigateUrl = string.Empty;

        public string Title { get; set; }
        public string Source { get; set; }
        public DateTime PublishDate { get; set; }
        public string Body { get; set; }
        public List<Attachment> Attachments { get; set; }
        public string NavigateUrl
        {
            get { return string.Format("{0}://{1}/{2}", HttpContext.Current.Request.Url.Scheme, HttpContext.Current.Request.Url.Authority, _NavigateUrl); }
            set { this._NavigateUrl = value; }
        }
    }

    public class Attachment
    {
        public string Filename { get; set; }
        public string Path { get; set; }
    }
}

@{
    //add list of dynamic objects to strongly typed class
    var releases = new List<PressRelease>();
    foreach (var item in @Model.Items)
    {

        var release = new PressRelease
        {
            Title = item.ContentItem.TitlePart.Title,
            Source = item.ContentItem.PressRelease.Source.Value,
            PublishDate = item.ContentItem.PressRelease.Date.DateTime,
            //this is super hacky to get a chopped version of the HTML submitted for a summary
            Body = item.ContentItem.BodyPart.Text,
            NavigateUrl = item.ContentItem.AutoroutePart.Path
        };

        //load attachment(s) to class
        var attachments = (Orchard.MediaLibrary.Fields.MediaLibraryPickerField)item.ContentItem.PressRelease.Attachment;
        if (attachments.MediaParts.Count() > 0)
        {
            foreach (var part in attachments.MediaParts)
            {
                release.Attachments.Add(new Attachment { Filename = part.FileName, Path = part.MediaUrl });
            }
        }

        releases.Add(release);
    }
}
@{
    foreach (var item in releases)
    {
        <div class="press-release">
            <div class="press-release-title"><a href="@item.NavigateUrl">@item.Title</a></div>
            <div class="press-release-meta">
                <span class="press-release-source">Source: @item.Source</span>
                @if (item.PublishDate != DateTime.MinValue)
                {
                    <span class="press-release-date">@item.PublishDate.ToShortDateString()</span>
                }
            </div>
            @if (item.Attachments.Count() > 0)
            {
                <div class="press-release-attachments">
                    <span class="press-release-attachments-title">Attached: </span>
                    @foreach (var attachment in item.Attachments)
                    {
                        <a href="@attachment.Path" target="_blank">@attachment.Filename</a>
                        if (attachment != item.Attachments.Last())
                        {
                            <span>, </span>
                        }
                    }
                </div>
            }
            <div class="press-release-body">
                @{
                    var body = new HtmlString(Html.Excerpt(item.Body, 200).ToString().Replace(Environment.NewLine, "</p>" + Environment.NewLine + "<p>"));
                    <p>@body <a href="@item.NavigateUrl">(read more)</a></p>
                }
            </div>
        </div>
        <div class="social">
            <div class="fb-share-button" data-href="@item.NavigateUrl" data-type="button_count"></div>
        </div>
        if (item != releases.Last())
        {
            <hr />
        }
    }
}