as it might sound quite easy task for episerver to carry out - it's actually not. episerver in this case (when you are using feature folders) have no idea in which folder view should be located. inside view path conventions `{1}` placeholder is controller name. as we do not have controller in your case - this convetion breaks basically.
if you want to dig deeper what's actually happening under the hood when episerver is asked to resolve template for the content this part of the series might be interesting for you - https://blog.tech-fellow.net/2015/05/30/content-area-under-the-hood-part-2/
also to understand who is going to "render" your content template - you could install DeveloperTools (https://nuget.episerver.com/package/?id=EPiServer.DeveloperTools) and check under content templates (Developer > Templates) section. there will be a list of all found content types and their respective renderers.
have you also considered to just install nuget package (http://marisks.net/2017/12/17/better-feature-folders/) for this task?
Hi Jason
If you are making controller-less blocks, have a look at implementing the IViewTemplateModelRegistrator
interface (documentation here). Here is a sample:
public void Register(TemplateModelCollection viewTemplateModelRegistrator)
{
viewTemplateModelRegistrator.Add(
typeof(StandardBlock),
new TemplateModel
{
Name = "StandardBlock",
AvailableWithoutTag = true,
Path = "~/Features/GenericContent/Views/StandardBlock.cshtml"
});
}
I usually create a class for this in each feature folder (where needed). You will still need to specify relative paths to the view files, though.
I was hoping I was just doing something incorrectly in my implementation. Seems I am out of luck. So my choices are use controllers or register each view manually. Sucks it requires more code, but I have a feeling the controller route may be a better option for me since it feels easier to maintain, and many blocks will have logic necessitating a controller anyway. If performance becomes an issue, I may switch to the template registration method. Thanks for your help guys.
UPDATE:
You should be able to create just one controller for all your controller-less blocks. Create a generic block controller and implement the Index method (if you need to, in order to resolve your view) and make sure to use the [TemplateDescriptor]
attribute. Make sure to set Inherit to true:
[TemplateDescriptor(Inherited = true)]
public class GenericBlockController : BlockController<BlockData>
{
public override ActionResult Index(BlockData currentContent)
{
return PartialView(currentContent.GetOriginalType().Name, currentContent);
}
}
My idea is that this controller will handle any block that doesn't have it's own dedicated controller. One controller for all your logic-less blocks is better than one controller per block :)
ORIGINAL POST:
Is this really true though? What happens if you still implement a controller, but don't override the Index method?
Looking at PartialContentController<TContentData>
(implemented by BlockController<TBlockData>
), you can see that the Index method contains the following code:
public virtual ActionResult Index(TContentData currentContent)
{
if (typeof (TContentData) == typeof (IContentData))
throw new InvalidOperationException(string.Format((IFormatProvider) CultureInfo.InvariantCulture, "The controller '{0}' tried to call the partial view '{1}', which would cause an infinite loop. Make sure it overrides the 'Index' action from 'PartialContentController'.", (object) this.GetType().Name, (object) typeof (TContentData).Name));
return (ActionResult) this.PartialView(typeof (TContentData).Name, (object) currentContent);
}
I would assume that your controller-less blocks and views (wherever they may be placed), should be resolved using that PartialView(typeof(TContentData).Name, currentContent)
statement, which in turn very likely uses your custom view engine.
I am trying to use feature folders for my first EPiServer site build and running into an issue with blocks. I can get blocks to work fine that have controllers, but for some reason using blocks without controllers does not work. I get the message that the block cannot be displayed when rendered on a page. Add the controller and it works just fine, even without specifying a path to the view so I know the view resolution logic is working. There is no logic in the controller, just a call to PartialView(model) which I want to avoid for the sake of performance. I followed some articles online on how to create a view engine to add the additional paths for feature folders, shown below: