I've come across an issue while creating a custom MVC add-on. I have managed to find work-arounds to get it working but it would be useful to know if I'm doing anything wrong or missing anything.
I have created an MVC GuiPlugin but I seem to have issues with Episerver recognising referenced namespaces in the razor views. As far as I can tell, the issue seems to be that Episerver is ignoring the web.config in the root of my view folder.
This is the web config for my Views folder https://github.com/zone/Zone.Episerver.PropertyViewer/blob/develop/src/Zone.Episerver.PropertyViewer/Views/web.config
Is there anyway to get Epi to recognise the referenced namespaces so I can write razor views in a more standard way?
where do you put web.config file when packing addon as nuget?
It's in my Views folder inside the zip:
I have narrowed this down a bit further - I can use @model and referenced namespaces in the views if the module is not zipped. This only seems to occur for a zipped module.
These posts might help:
Thanks David, however the problem I am getting is not that it can't find the views, as described in forum post above. My controller is finding the view, but the view errors if I use the @model syntax. If I use @inherits System.Web.Mvc.WebViewPage, the view renders correctly.
I haven't tried yet using the Geta package so I can give that a go, but I thought Razor views were supported officially.
Razor views support was added at some Episerver version v10.10.x (can't remeber precisely which was it). So Geta's pacakge if I recall correctly became obsolete at that point. There were somes bugs in shell view engine resolutions that were fixed in v11.4.1.
I'm checking your repo..
try to set view engine to "razor" in module.config file:
There was a bug as valdis mentioned https://world.episerver.com/documentation/Release-Notes/ReleaseNote/?releaseNoteId=CMS-9794
basically if you use Razor and you zip your files, then you should be using at least 11.4.1
I'm testing on the latest version of Episerver so that bug shouldn't be present. As I say, the issue is not that the view cannot be found - which is what is described in the bug fix you link to. The issue is that it doesn't recognise @model syntax, and any other referenced namespaces in the Views web.config.
The exact same razor code works when the module is not zipped, so it seems like my Views folder web.config is not read for a zipped module.
@valdis I already have the view engine already set as you suggest:https://github.com/zone/Zone.Episerver.PropertyViewer/blob/develop/src/Zone.Episerver.PropertyViewer/module.config
can you share nuget pacakge? (maybe for now can commit to repo?)
Sure, here you go: https://github.com/zone/Zone.Episerver.PropertyViewer/blob/feature/standardise-razor/src/Zone.Episerver.PropertyViewer/Packager/Zone.Episerver.PropertyViewer.126.96.36.199506.nupkg
If you install this and access the plugin (from Admin -> Property Viewer) you'll see the error. If you unzip the package to the module folder and run it again, you should see that it works.
indeed. I saw Ollie, you pushed out package. did you just give up and used @inherits?
I checked also zip view engine source code. nothing fancy there. so I think you should contact Episerver support for this case. they do have source code which is much nicer during debug session :)
@valdis Yeah I stuck with the workaround for now. I've raised a ticket with Epi support and they confirmed that they could reproduce, so looks like it could be a bug.
@Ollie, could you please try with this one?
I fixed the issues in your nuget file, just replace the zip in your _protected folder to test it.
The issue was that you should use:
in few places you were missing the full namespace to one of your types.
@Bartosz, but what is root cause for this? I've debugged (as far as I could with decompiled source) - seems like request for web.config file does not land on module zip view engine. therefore it seems like it's completely ignored. you can enter junk in web.config file and it still runs..
Thanks for taking a look @bartosz.
You are correct that it works if you use `@inherits` and full namespaces - I actually mentioned this workaround in my original post:
However, as discussed above, the @model syntax does works - but only when the package is not included in a zip file.
Sorry guys, somehow I missed the workaround thing you wrote ; ) I will try to find out what's happening.
When the module is zipped and served via ZipArchiveVirtualPathProvider the aspnet runtime will not discover and read the web.config from the Views folder.
That's why even if we write junk content there nothing happens.
Since the web.config is ignored the razor engine is not fully initialized (@model not working) the <namespaces> section is missing so we have to use full namespaces etc.
The last reasonable workaround is to stop using web.config in the Views folder and add a bit more to your Web.config transformation so apart from adding a new protectedModule you would also add:
factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=188.8.131.52, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="Zone.Episerver.PropertyViewer.Models" />
<add key="webpages:Enabled" value="false" />
<remove name="BlockViewHandler" />
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode"
<add assembly="System.Web.Mvc, Version=184.108.40.206, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
The only downside is that <configSections> has to be registered under <configuration>, we can't add it under our custom <location>.
<?xml version="1.0" encoding="utf-8"?>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=220.127.116.11, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=18.104.22.168, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=22.214.171.124, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="episerver" type="EPiServer.Configuration.EPiServerSection, EPiServer.Configuration" restartOnExternalChanges="true" />
<sectionGroup name="episerverModules" />
<section name="episerver.shell" type="EPiServer.Shell.Configuration.EPiServerShellSection, EPiServer.Shell" />
<section name="episerver.framework" type="EPiServer.Framework.Configuration.EPiServerFrameworkSection, EPiServer.Framework.AspNet" restartOnExternalChanges="true" />
<section name="episerver.search" type="EPiServer.Search.Configuration.SearchSection, EPiServer.Search.Cms" />
<section name="episerver.search.indexingservice" type="EPiServer.Search.IndexingService.Configuration.IndexingServiceSection, EPiServer.Search.IndexingService" />
<section name="staticFile" type="EPiServer.Framework.Configuration.StaticFileSection, EPiServer.Framework.AspNet" allowLocation="true" />
Is it an acceptable solution?
Thanks @bartosz, that seems like a good solution since it sounds like it wouldn't be possible to use a View folder web.config in the standard way.
To summarize for anyone who comes across the same challenge, if you want to use razor views in a custom add-on, you can either:
do you know the reason why web.config is being ignored?