Servicestack Razor, setting Layout to Null - razor

Using ServiceStack.Razor and having a slight issue.
I have a default _Layout.cshtml page that is my base layout, but for some pages, I don't want a layout, I just want to a full html page with no templating, similar to how setting the Layout to null in ASP.NET MVC would work.
I cannot figure out how to do this, and can't find anything in the documentation (not saying it's not there, just can't find it).
Things I've tried:
Setting the Layout property to null on the actual view page:
#{
Layout = null;
}
Returning a null template from the actual service:
return HttpResult(dto) { Template = null; };
Moving my view page out of the Views folder (this just took it back to the default ServiceStack view page)
Any help greatly appreciated.
Thanks, and sorry if I missed something simple

Layout=null indicates no Layout was specified, so will use the default _Layout.cshtml.
You can use an empty string "" for no Layout, e.g:
#{
Layout = "";
}
Otherwise if preferred, create an "Empty" layout e.g: /Views/Shared/Empty.cshtml containing just:
#RenderBody()

Related

Orchard CMS: How to display a Layout Part in a view?

I'm trying to specify a different Query Layout for a query that returns several pages and completely take over the rendering of the list following this excellent guide: http://www.ideliverable.com/blog/ways-to-render-lists-of-things
I have the basic implementation setup and know it to be working by using the following simple code for the rendering:
#using Orchard.ContentManagement
#using Orchard.Core.Title.Models
#using Orchard.Layouts.Models
#{
var webPages = ((IEnumerable<ContentItem>)Model.ContentItems).ToList();
}
#foreach (var wp in webPages)
{
var titlePart = wp.As<TitlePart>();
var wpTitle = titlePart.Title;
<p>#T("{0} Title is ", wpTitle)</p>
}
Problem:
However, when attempting to include the Layout of each page, I can't seem to work out how? Using the code below, only the text 'Orchard.Layouts.Models.LayoutPart' is rendered erroneously in the HTML.
var layoutPart = wp.As<LayoutPart>();
#Display(layoutPart)
Therefore, I'm assuming the LayoutPart is different to other common Parts in Orchard, because I have also tested many other parts which all successfully render, except Layouts (I'm thinking the LayoutPart has to be constructed somehow before being displayed, but that is clutching at straws)?
So how does one go about such?
Funnily enough, you're basically right. Layouts have to built before displaying:
#Display(BuildDisplay(layoutPart, "#display type#")) //display type: Summary / Detail

how can i remove a index page from other pages in angularjs

I have a template html page(say Index page) containing a header and three other pages and i want that Header on first two pages but not on third page .Using angularjs routing I am able to have that header on all three pages but cant hide that header from the third page.The pages have different controllers as well .Can anybody help me how to achieve this.
This is not a good practice, not at all! But as your question lacks of code...
You say "The pages have different controllers", so let's say you have PageOneCtrl, PageTwoCtrl and PageThreeCtrl.
If you want to show the header on the page with controllers, let's say: PageOneCtrl and PageTwoCtrl, set a $scope (remember you have to define $scope on that controller first) variable just like:
$scope.showHeader = true;
And in PageThreeCtrl (where you want to HIDE the header element) write
$scope.showHeader = false;
Then in the html you should write:
<header ng-if="showHeader">This is your header content</header>
the ng-if will do the trick, check angularjs documentation for more information: https://docs.angularjs.org/api/ng/directive/ngIf
Doesn't work? Try $rootScope instead of $scope, but watch out! If you use $rootScope then you should declare that variable on every controller.
This is not a good practice, not at all! But as your question lacks of code...
A better practice, and one of the bests in my opinion, would be to use angular-ui-router and set a data attribute to the state (route) with something like
.state('myRoute', {
templateUrl: 'views/my-route-view.html',
controller: 'MyrouteCtrl',
data: {
hideHeader: true;
}
})
, in a .run() function set something like $rootScope.$state = $state (read more about it in the ui.router docs) and then simply: <header ng-if="!$state.current.data.hideHeader">. But I believe you're not an advanced developer to do it :) So keep learning.

Orchard - Add an additional shape name (i.e. an alternate) for the main List shape

Introduce the Problem
I would like to profoundly modify the layout of the Orchard CMS Tags list.
Here is an example page with Shape Tracing enabled.
The only alternate that it suggests for the List shape is ~/Themes/TheThemeMachine/Views/List.cshtml, because the page is rendering the default List shape. I would like to have other alternates that are specific to the page.
After reading Orchard list customization, I have been able to implement the default List.cshtml in razor. What I would like to do, though, is to add another alternate, such as ~/Themes/TheThemeMachine/Views/Parts.Tags.List.cshtml instead of implementing the default List.cshtml template.
The problem seems to be that the page is rendering the generic List shape.
In contrast, the blog post list page is rendering a Parts_Blogs_BlogPost_List shape, which means that a ~/Themes/TheThemeMachine/Views/Parts.Blogs.BlogPost.List.cshtml is available.
Search and Research
All quotes below are from the Orchard list customization blog post, which explains how to add a list item alternate (whereas I would like to add a list alternate).
What we really want is an alternate template... aptly called Shape
Alternates... [so] enable Shape Tracing... and select a post in the list...
[you will see that] we already have some possible alternates.
My example page also has some possible alternates for the List Content. Cool.
we need to somehow get into list rendering... [t]he default is defined
in code... [which] can be override by a new [cshtml] template in our
theme.
Okay. That makes sense. We can override the list rendering.
As Shape Tracing can show, we can override the list rendering for a
blog by creating a Parts.Blog.BlogPost.List.cshtml template.
This works for alog but not for the blog Tag page (example page). You see, the blog displays a **Parts_Blogs_BlogPost_List shape and suggests an appropriate alternate but the blog tags page displays the default List shape with no alternates other than List.cshtml.
Blog Page with alternates galore
Blog Tags Page with one alternate List.cshtml
So, I created a List.cshtml not a Parts.Blog.BlogPost.List.cshtml template, and save it in my theme's Views directory. (One problem here is that, once we get it working, we will b overriding the default List rendering.)
Then I add the Razor code (copy and pasted from Bertrand's post) to override the default rendering for Lists. When I refresh the site, the browser renders a blank page. It isn't working. Here's the code:
This Does NOT Work in List.cshtml
#using Orchard.DisplayManagement.Shapes;
#{
var list = Model.ContentItems;
var items = list.Items;
var count = items.Count;
var listTag = Tag(list, "ul");
listTag.AddCssClass("content-items");
listTag.AddCssClass("blog-posts");
var index = 0;
}
#listTag.StartElement
#foreach (var item in items) {
var itemTag = Tag(item, "li");
if (index == 0) {
itemTag.AddCssClass("first");
}
else if (index == count - 1) {
itemTag.AddCssClass("last");
}
#itemTag.StartElement
#Display(item)
#itemTag.EndElement
++index;
}
#listTag.EndElement
As a trouble shooting step, I replace the List.cshtml with <p>Hello world.</p>. Orchard renders the markup as expected. So, something is incompatible between the Razor code from Bertrand's blog and the Tags List.
To find out what exactly is incompatible, I try Betrand's code one line at time to see where it breaks (yup, VS would be better than WM here). At each change, I restart WebMatrix and view the results. This is the minimal code that breaks it.
The Culprit
#using Orchard.DisplayManagement.Shapes;
#{
var list = Model.ContentItems;
var items = list.Items;
}
list.Items isn't appropriate here. So I comment it out again and run the <p>Hello World</p> version again. Also, Shape Tracing reveals that on my Tags/tagname page, the Content Zone is now rendering the List twice. Is that normal?
As another step, I replace Model.ContentItems just with Model. It works. It seems that, to override the List.cshtml template, we cannot use the ContentItems property of Model. Here is the new, working code:
This Does Work in List.cshtml
#using Orchard.DisplayManagement.Shapes;
#{
//var list = Model.ContentItems;
//var items = list.Items;
var items = Model.Items;
var count = items.Count;
//var listTag = Tag(list, "ul");
var listTag = Tag(Model, "ul");
listTag.AddCssClass("content-items");
listTag.AddCssClass("blog-posts");
var index = 0;
}
#listTag.StartElement
#foreach (var item in items) {
var itemTag = Tag(item, "li");
if (index == 0) {
itemTag.AddCssClass("first");
}
else if (index == count - 1) {
itemTag.AddCssClass("last");
}
#itemTag.StartElement
#Display(item)
#itemTag.EndElement
++index;
}
#listTag.EndElement
Onward through the article.
So far so good, we have effectively taken over the rendering of the
list, but the actual HTML [will] be... identical to what we had before
[except for] the implementation.
Okay. I'm following. We want to modify the rendering not just re-implement it.
Alternates are a collection of strings that describe additional shape
names for the current shape... in the Metadata.Alternates property of any shape.
Gotcha. Now, why doesn't the Tags/tagname page show an alternate other than just List.cshtml for the rendering of the List shape?
All we need to do is add to this list [of alternates]... [and make sure] to respect the lifecycle...
Great. Maybe we can we add another alternate for the List shape on the Tags/tagname page. But, doing that is different from what Betrand is explaining. While Betrand's blog post is excellent, it is explaining how to add an alternate for an item, whereas I would like to add an alternate for the list.
The List.cshtml template is where I would add an alternate for a List Item as follows:
ShapeMetadata metadata = item.Metadata;
string alternate = metadata.Type + "_" +
metadata.DisplayType + "__" +
item.ContentItem.ContentType +
"_First";
metadata.OnDisplaying(ctx => {
metadata.Alternates.Add(alternate);
});
So that...
[t]he list of alternates from Shape Tracing now contains a new item.
Where and how, though, would I add an alternate for the List shape? Bertrand has recommended to check out the Shape Table Providers blog post for this. The quotes below are from that post.
But what if you want to change another shape template for specific
pages, for example the main Content shape on the home page?
This looks like a fit, because my example is the main List shape on the tags page. To do this we...
... handle an event that is triggered every time a shape named "Content"
[in our case "List"] is about to be displayed. [It] is implemented in a shape table provider which is where you do all shape related site-wide operations.
Great! Here is my implementation for adding another template for the main List shape.
TheThemeMachine > ListShapeProvider.cs
namespace Themes.TheThemeMachine
{
using Orchard.DisplayManagement.Descriptors;
public class ListShapeProvider : IShapeTableProvider
{
public void Discover(ShapeTableBuilder builder)
{
System.Diagnostics.Debugger.Break(); // break not hit
builder.Describe("List").OnDisplaying(displaying => {
// do stuff to the shape
displaying.ShapeMetadata.Alternates.Add("Tags__List");
});
}
}
}
The above builds and runs but does not hit the breakpoint nor add an alternate for the List shape on the /tags page. So I looked into the Orchard.Azure.MediaServices module and its CloudVideoPlayerShape which implements IShapeTableProvider. Its breakpoint does get hit. How is my code for ListShapeProvider fundamentally different than the code for the CloudVideoPlayerShape?
Also, I installed the Orchard.Themes.CustomLayoutMachine.1.0.nupkg as suggested in Bertrand's blog post. It unfortunately no longer contains an implementation of IShapeTableProvider.
I have also looked at this szmyd post, which does not explain where to put the IShapeTableProvider code.
Further, I installed the Contoso theme from the Orchard Gallery. It works and builds after adding a reference to Microsoft.CSharp. It also includes an implementation of the IShapeTableProvider. Hooray! Comparing its ContentShapeProvider with my ListShapeProvider reveals a subtle but important difference:
Contoso.csproj
<ItemGroup>
<Compile Include="Code\ContentShapeProvider.cs" />
</ItemGroup>
My implementation didn't include the .cs file in the compilation, because my theme has neither a .csproj nor a App_Code folder. So, I recreated my theme with the following code generation:
orchard.exe
feature enable Orchard.CodeGeneration
codegen theme My.FirstTheme /CreateProject:true
theme enable My.FirstTheme
feature enable Orchard.DesignerTools
When adding the ListShapeProvider.cs file, Visual Studio automatically added a ItemGroup/Compile entry for the file, which included the code in compilation. Hooray!
These two posts will help.
Shape Shifting
List Customization
Here are steps of my own minimum solution.
Download and unzip Orchard.Source.1.8.zip.
Open "\Downloads\Orchard.Source.1.8\src\Orchard.sln" in Visual Studio.
Build the solution to create orchard.exe.
Generate a new theme with orchard.exe. Use CreateProject:true because you will need a csproj to include your .cs file.
orchard.exe
setup /SiteName:SITE /AdminUsername:ME /AdminPassword:PWD /DatabaseProvider:SqlCe
feature enable Orchard.CodeGeneration
codegen theme My.FirstTheme /CreateProject:true
theme enable My.FirstTheme
In VS, add a ListShapeProvier.cs file to the root (or any folder) in your theme.
Add the following code to ListShapeProvider.cs.
namespace My.FirstTheme
{
using Orchard.DisplayManagement.Descriptors;
public class ListShapeProvider : IShapeTableProvider
{
public void Discover(ShapeTableBuilder builder)
{
System.Diagnostics.Debugger.Break();
// implementation here
}
}
}
Build the solution.
Run Orchard.Web.
Visual Studio will break at System.Diagnostics.Debugger.Break(). If it doesn't, go to the Orchard Dashboard and make My.FirstTheme the Current Theme.
Now read Shape Shifting to implement public void Discover(ShapeTableBuilder builder).
This post should give you a full response: http://weblogs.asp.net/bleroy/archive/2011/05/23/orchard-list-customization-first-item-template.aspx

Razor: Retrieving variable from component template on page template

Hi all,
I've been working on a set of Razor templates that is either Site Editable with the Experience Manager and at the same time is fully responsive for several screenwidths with the Twitter bootstrap. As a result, I need to dynamically manipulate the DOM output based on what the Experience Manager editor adds or deletes but still maintain the responsive design. Part of this construction is adhering to the rules the twitter bootstrap dictates.
The twitter bootstrap allows for excellent responsive design by introducing dynamically calculated div widths using classes. A <div class="span12> uses the entire width of the wrapper, for example. A "span6" effectively uses half, with a certain margin calculated as well to allow for another div with "span6". However, this only works if the preceding class is called <div class="row-fluid">,and as long as the span<numbers> actually add up to exactly 12. The problem arises when I need to close the <div class="row-fluid"> when this number is actually reached.
To clarify: it has to output like this
<div class="row-fluid">
<div class="span6">..code</div>
<div class="span4">..code</div>
<div class="span2">..code</div>
</div>
The <div class="span[#]"> are rendered with a component template, in order to allow for multiple components within the <div class="row-fluid>, which the Page Template renders.
However, from a component template level I cannot seem to retrieve the actual amount of components of this template actually exist on the Page itself. I calculate the width of the component used based on a schema option of the component itself. I use the following Component Template code to render it correctly:
#{
var spanClass = String.Empty;
if (Fields.HasField("component_width") && Fields.component_width != null) {
if (Fields.component_width.ToLower() == "full") {
spanClass = "span12";
} else if (Fields.component_width.ToLower() == "half") {
spanClass = "span6";
} else if (Fields.component_width == "40%") {
spanClass = "span5";
} else if (Fields.component_width == "35%") {
spanClass = "span4";
} else if (Fields.component_width == "25%") {
spanClass = "span3";
}
}
}
<div class="#spanClass">...code
To get to my question: I need to be able to close the <row-fluid> div if the number 12 has been reached. So if one component with the options 'Full' (width) is selected, the following output code needs to appear:
<div class="row-fluid">
<div class="span12">..code</div>
</div>
If there are two components on the page with the option "half" are selected, it must allow
<div class="row-fluid">
<div class="span6">..code</div>
<div class="span6">..code</div>
</div>
mind the closing div on the end. Is there some way I can reach the variable i created on the Component Template var spanClass = String.Empty; from Page Template? Something like:
#foreach (var cp in GetComponentPresentationsByTemplate("XM_Generic Content")) {
#if (cp.Component.spanClass == "span6") {
<div class="row-fluid">
#cp.RenderComponentPresentation()
#if (cp.Index == 1) {
</div>
}
}
}
I'm still getting to know Razor templates, the practicalities of Responsive design and ofcourse StackOverflow. Chances are that I completely missed something, made dumb errors in my code of just asked a silly question. By all means, let me know.
The package is not shared between template runtimes, so this behavior is normal (not being able to see variables set in one template from a different instance).
There are ways around this, but you should consider that perhaps there is a good reason why Tridion chose to isolate the template execution.
See here for one of the ways to go around this.
Standard techniques using the ContextVariables dictionary don't allow you to set something in the CT and access it from the PT. Effectively, each time a Component is rendered, the render context gets a fresh copy of the variables from the page render context. Writing back to them, therefore isn't effective. There is a technique that gets round this, which is described in detail on tridion-practice. As already noted, resorting to these kinds of techniques shouldn't be your first option, but sometimes you need to.
Currently, its seems, the user is defining the width position in the component field. I think, its quite typical, but if you create 5 Component Template which will call a same Razor TBB, and also define, a parameter schema on component Template where can set the width of component then afterwards you can easily call these different CTs in the page template.

Orchard CMS: Custom Taxonomy View Template not working

I'm using a taxonomy part in one of my custom content types, and using the shape tracer, I was able to create a custom view template for that control (Fields.Contrib.TaxonomyField.cshtml).
When I shape trace the element on the page, under template it indeed shows my custom template exactly as I have it on the external file:
#using Orchard.Utility.Extensions;
#using Orchard.ContentManagement;
#{
var terms = (IEnumerable<Contrib.Taxonomies.Models.TermPart>)Model.Terms;
string name = #Model.ContentField.Name;
}
#if (Model.Terms.Count > 0) {
#(new HtmlString( string.Join(", ", terms.Select(t => Html.ItemDisplayLink(Html.Encode(t.Name), t.ContentItem ).ToString()).ToArray()) ))
}
<div>TEST TEXT</div>
However, when I tab over to the actual outputted HTML, it is showing the standard, built in template, and isn't using my customizations.
<p class="taxonomy-field">
Coffee Shop
</p>
According to the shape tracer, it is using my custom template:
Shape Fields_Contrib_TaxonomyField
Active Template
~/Themes/Continuum/Views/Fields.Contrib.TaxonomyField.cshtml
Display Type Detail
this feels like a bug... everything looks like it's wired up correctly... is there something else I need to do to use my custom view template for taxonomy?
Many thanks!
I figured out the problem. Turns out there was another template created (likely by accident) which was url-specific:
Fields.Contrib.TaxonomyField-url-venues.cshtml
that's the url I was on, and this had the default template still in it. After deleting it, it finally used my custom template.
User error, sorry!!