Displaying only Main Content

Topics: Customizing Orchard
Jul 30, 2014 at 3:39 AM
I'm trying to add a "Print" button when they are viewing a content item. I'd like it to popup a window that will only show what's typically in the Model.Content of the theme so there isn't any of the other sections around it. Basically display the content with out the theme but I'd like the content to look the same.

I'm not sure how to go about adding a generic print button that will display any content they would be viewing.

Can anyone offer up some help?

Thanks,
Aug 1, 2014 at 2:41 AM
Anyone?? All I want to do is render the main content type in my own module.
Aug 1, 2014 at 10:23 AM
Edited Aug 1, 2014 at 4:10 PM
I did something pretty similar, it was for embeding video contents in an iframe on other web sites.

To achieve this, I made a custom controller :
    [Themed]
    public class EmbedController : Controller {
        public IOrchardServices Services { get; set; }
        private readonly IPathResolutionService _pathResolutionService;

        public EmbedController(IOrchardServices services,
            IPathResolutionService pathResolutionService) {
            Services = services;
            _pathResolutionService = pathResolutionService;
            T = NullLocalizer.Instance;
        }

        public Localizer T { get; set; }
        public dynamic Shape { get; set; }

        public ActionResult Index(string path)
        {
            var autoroute = _pathResolutionService.GetPath(path);
            if (autoroute != null) {
                var CloudVideoContentShape = Services.ContentManager.BuildDisplay(autoroute.ContentItem, "Detail");
                return new ShapeResult(this, CloudVideoContentShape);
            }
            else {
                return null;
            }
        }
    }
For a content with URL like http://mysite.com/my-slug , the embed URL is http://mysite.com/embed/my-slug

If you need to use a different theme, you can override it like that :
    public class EmbedThemeSelector : IThemeSelector {
        private readonly IOrchardServices _services;

        public EmbedThemeSelector(IOrchardServices services) {
            _services = services;
        }

        public ThemeSelectorResult GetTheme(RequestContext context) {
            if (AdminFilter.IsApplied(context)) {
                return null;
            }

            if ((string)context.RouteData.Values["area"] == "Codinlab.CloudVideo" && (string)context.RouteData.Values["controller"] == "Embed") {
                CloudVideoSettingsPart CloudVideoSettings = _services.WorkContext.CurrentSite.As<CloudVideoSettingsPart>();
                return new ThemeSelectorResult() { Priority = 10, ThemeName = CloudVideoSettings.EmbedTheme };
            }

            return null;
        }
    }
I don't know if it is the best solution, but worked for me...
Aug 1, 2014 at 3:54 PM
This is great, thank you. What did your view look like? or how did you reference the shape to display on the page?
Aug 1, 2014 at 4:39 PM
My first response was not clear.

I think you just need to create a blank new very basical theme, with only the content zone.

Doing so, all the widgets placed in other zones (menu, header, footer...) won't be displayed. You only display your main content, and you can style your document the way you want with CSS.

Once you've done this, you just need a way to override the current theme for a special URL (this is what the code I posted was for).

Maybe you can just pass a "print" parameter in the URL, and then use IThemeSelector to change the theme if your parameter is present.

If you want to display this view inside of your page, you should use an iframe.
Aug 4, 2014 at 2:33 AM
I'm really missing something because putting what you did in place in my module I get a blank screen. There's obviously something either I'm not doing or I don't understand.
Aug 4, 2014 at 9:53 AM
It's not a magic formula, you have to adapt the solution to your needs...

Here is a solution working out of the box :
using Orchard;
using Orchard.Themes;
using System.Web.Routing;

namespace test.Services {
    public class PrintThemeSelector : IThemeSelector {
        private readonly IOrchardServices _services;

        public PrintThemeSelector(IOrchardServices services) {
            _services = services;
        }

        public ThemeSelectorResult GetTheme(RequestContext context) {
            if (Orchard.UI.Admin.AdminFilter.IsApplied(context)) {
                return null;
            }
            var queryString = context.HttpContext.Request.QueryString;
            if (queryString["theme"] != null && queryString["theme"] == "print") {
                return new ThemeSelectorResult() { Priority = 100, ThemeName = "SafeMode" };
            }

            return null;
        }

    }
}
Just put it in your module, and if you just append "?theme=print" to your URL, your content will be displayed with "SafeMode" theme.
You just need to replace "SafeMode" by the name of your print theme. You also have to put the right namespace.
Aug 5, 2014 at 2:09 AM
I appreciate the help. I am getting closer. I have my controller working and the theme class in place. Stepping through the code it recognizes my querystring and returns the new themeselectorresult, but the theme isn't getting applied. The Layout.chtml it's using is from the "Core\Shapes\Views\Layout.cshtml". Since it didn't work for my theme I tried the one that came with Orchard; TheThemeMachine. That didn't work either.
Aug 5, 2014 at 2:17 AM
Scratch that ... I had to enable the theme. I got it working. Thanks for all the help.
Aug 5, 2014 at 3:30 AM
Actually, I do have one more question. How do I find the slug in my view?
Developer
Aug 5, 2014 at 6:09 AM
If in Layout.cshtml, you could do Request.Path to get the current path.
If you're in a Content shape view file (or a part or a field shape view file), you can access the current content item through Model.ContentItem.
If you want to access the current Content item from the Layout view, you have to be aware of the fact that the request doesn't necessarily have to come from the ItemController.
Developer
Aug 5, 2014 at 6:15 AM
I forgot to add: once you've got your hands on a content item in your view, you can either "cast" it to AutoroutePart like this: contentItem.As<AutoroutePart>() (and access its Path property) or use an URL helper extension method: Url.ItemDisplayUrl(contentItem). The latter is the recommended way, since it leverages the content item's metadata (to which AutouroutePart contributes if it's attached to the content item).