Writing an unthemed view while still using Orchard shapes and helpers
- by Bertrand Le Roy
This quick tip will show how you can write a custom view for a custom controller action in Orchard that does not use the current theme, but that still retains the ability to use shapes, as well as zones, Script and Style helpers. The controller action, first, needs to opt out of theming: [Themed(false)]
public ActionResult Index() {}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
Then, we still want to use a shape as the view model, because Clay is so awesome:
private readonly dynamic _shapeFactory;
public MyController(IShapeFactory shapeFactory) {
_shapeFactory = shapeFactory;
}
[Themed(false)]
public ActionResult Index() {
return View(_shapeFactory.MyShapeName(
Foo: 42,
Bar: "baz"
));
}
As you can see, we injected a shape factory, and that enables us to build our shape from our action and inject that into the view as the model.
Finally, in the view (that would in Views/MyController/Index.cshtml here), just use helpers as usual. The only gotcha is that you need to use “Layout” in order to declare zones, and that two of those zones, Head and Tail, are mandatory for the top and bottom scripts and stylesheets to be injected properly. Names are important here.
@{
Style.Include("somestylesheet.css");
Script.Require("jQuery");
Script.Include("somescript.js");
using(Script.Foot()) {
<script type="text/javascript">
$(function () {
// Do stuff
})
</script>
}
}
<!DOCTYPE html>
<html>
<head>
<title>My unthemed page</title>
@Display(Layout.Head)
</head>
<body>
<h1>My unthemed page</h1>
<div>@Model.Foo is the answer.</div>
</body>
@Display(Layout.Tail)
</html>
Note that if you define your own zones using @Display(Layout.SomeZone) in your view, you can perfectly well send additional shapes to them from your controller action, if you injected an instance of IWorkContextAccessor:
_workContextAccessor.GetContext().Layout
.SomeZone.Add(_shapeFactory.SomeOtherShape());
Of course, you’ll need to write a SomeOtherShape.cshtml template for that shape but I think this is pretty neat.