ASP.NET VirtualPathProvider .Execute()': no suitable method found to override - asp.net

I am currently trying to implement Razor Web Pages in older WebForms project, and also, make it possible to render partial views from string (taken from database elsewhere). I've implemented custom VirtualPathProvider with all overrides specified here: ASP.NET MVC and Virtual views and also overwritten these methods:
public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
{
if (virtualPath.Contains("RazorMigration.cshtml") && HttpContext.Current.Items.Contains("RazorTestingPage"))
{
return null;
}
return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
public override String GetFileHash(String virtualPath, IEnumerable virtualPathDependencies)
{
if (virtualPath.Contains("RazorMigration.cshtml") && HttpContext.Current.Items.Contains("RazorTestingPage"))
{
return Guid.NewGuid().ToString();
}
return Previous.GetFileHash(virtualPath, virtualPathDependencies);
}
Then when I am trying to actually render page (completeTemplate already contains pure HTML with razor already parsed) like this:
var rt = new RouteData();
rt.Values.Add("controller", "WebFormShimController");
var httpCtx = new HttpContextWrapper(System.Web.HttpContext.Current);
var ctx = new ControllerContext(new RequestContext(httpCtx, rt), new WebFormShimController());
try
{
HttpContext.Current.Items.Add("RazorTestingPage", completeTemplate);
IView view = ViewEngines.Engines.FindPartialView(ctx, System.IO.Path.GetFileName("RazorMigration")).View;
ViewContext vctx = new ViewContext(ctx, view,
new ViewDataDictionary { Model = model },
new TempDataDictionary(), httpCtx.Response.Output);
view.Render(vctx, System.Web.HttpContext.Current.Response.Output);
}
I always catch Exception On view.Render line saying this:
c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\0e7dfb6a\c63cc9d1\App_Web_razormigration.cshtml.afd51fd3.jujzzimy.0.cs(41): error CS1009: Unrecognized escape sequence
I am not really sure what is the issue here, or where and how this path is constructed. If someone could point me in the right direction I would be very happy as I am trying to get it working for almost a week, but still no success.
EDIT: I found the bug - It was in my encoding when writing to file (so when file was written \NUL characters were added, which confused IIS)
Now I am getting this error:
CS0115: c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\0e7dfb6a\c63cc9d1\App_Web_4b7b71f4-87c2-4364-be0e-19ec2a81ceccR.0.cs.Execute()': no suitable method found to override
I am sure I don't have error in my view as it only contains this:
<h1>Hello</h1>

Related

RazorViewEngine.FindView can't find the precompiled view

App.Web and App.Views are my projects in one solution, I put my views in App.Views and precompiled with RazorGenerator. It's working well if I used App.Web like,
~/Views/Index.cshtml is virtual path of my view in App.View
It can successfully render this view in App.Web
public ActionResult Index() {
return View("~/Views/Index.cshtml");
}
But when I try to RenderViewToString, it returns null.
class FakeController : ControllerBase
{
protected override void ExecuteCore() { }
public static string RenderViewToString(string controllerName, string viewName, object viewData)
{
using (var writer = new StringWriter())
{
var routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
var fakeControllerContext = new ControllerContext(new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://google.com", null), new HttpResponse(null))), routeData, new FakeController());
var razorViewEngine = new RazorViewEngine();
var razorViewResult = razorViewEngine.FindView(fakeControllerContext, viewName, "", false);
var viewContext = new ViewContext(fakeControllerContext, razorViewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer);
razorViewResult.View.Render(viewContext, writer);
return writer.ToString();
}
}
}
And this is how can all it,
FakeController.RenderViewToString("FakeName", "~/Views/Index.csthml", MessageModel);
This is discussed and probably solved in asp.net core, but I'm working with asp.net mvc 5.
Could you please help me to figure out, why it's not working?
You are trying to use Razor View Engine for getting precompiled views. This is a mistake. Razor engine produces views based on cshtml files. However in case of precompiled views, cshtml files have been already compiled by RazorGenerator to a set of classes derivied from System.Web.Mvc.WebViewPage. These classes override method Execute() (autogenerated by RazorGenerator based on input cshtml) that write html to output TextWriter.
Original view files (cshtml) are not required anymore and thus are not deployed with the application. When you call Razor that tries to locate cshtml and build view based on it, it expectedly returns null view.
ASP.NET MVC supports multiple view engines (the classes that implement System.Web.Mvc.IViewEngine). RazorViewEngine is one of them. RazorGenerator.Mvc NuGet package adds its own view engine (PrecompiledMvcEngine) that works based on precompiled views. Registered view engines are stored in ViewEngines.Engines collection. When you install RazorGenerator.Mvc NuGet package, it adds RazorGeneratorMvcStart class that registers instance of PrecompiledMvcEngine:
[assembly: WebActivatorEx.PostApplicationStartMethod(typeof(App.Views.RazorGeneratorMvcStart), "Start")]
namespace App.Views {
public static class RazorGeneratorMvcStart {
public static void Start() {
var engine = new PrecompiledMvcEngine(typeof(RazorGeneratorMvcStart).Assembly) {
UsePhysicalViewsIfNewer = HttpContext.Current.Request.IsLocal
};
ViewEngines.Engines.Insert(0, engine);
// StartPage lookups are done by WebPages.
VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);
}
}
}
You should use this instance of PrecompiledMvcEngine instead of RazorViewEngine for accessing precompiled views. Here is adjusted code of RenderViewToString method:
public static string RenderViewToString(string controllerName, string viewName, object viewData)
{
using (var writer = new StringWriter())
{
var routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
var fakeControllerContext = new ControllerContext(new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://google.com", null), new HttpResponse(null))), routeData, new FakeController());
var viewEngine = ViewEngines.Engines.OfType<PrecompiledMvcEngine>().FirstOrDefault();
if (viewEngine == null)
{
throw new InvalidOperationException("PrecompiledMvcEngine is not registered");
}
var viewResult = viewEngine.FindView(fakeControllerContext, viewName, "", false);
var viewContext = new ViewContext(fakeControllerContext, viewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer);
viewResult.View.Render(viewContext, writer);
return writer.ToString();
}
}
One important note: you should install RazorGenerator.Mvc NuGet package into project with your views (App.Views), not into Web application project, because PrecompiledMvcEngine takes current assembly as the source for the precompiled views. Aslo make sure that RazorGeneratorMvcStart was not added to App.Web project. It happened for me when I have added reference to RazorGenerator.Mvc.dll assembly.
Sample Project on GitHub

Test ControllerFactory (pre-start initialization stage)

I want to write a unit test that verifies my route registration and ControllerFactory so that given a specific URL, a specific controller will be created. Something like this:
Assert.UrlMapsToController("~/Home/Index",typeof(HomeController));
I've modified code taken from the book "Pro ASP.NET MVC 3 Framework", and it seems it would be perfect except that the ControllerFactory.CreateController() call throws an InvalidOperationException and says This method cannot be called during the application's pre-start initialization stage.
So then I downloaded the MVC source code and debugged into it, looking for the source of the problem. It originates from the ControllerFactory looking for all referenced assemblies - so that it can locate potential controllers. Somewhere in the CreateController call-stack, the specific trouble-maker call is this:
internal sealed class BuildManagerWrapper : IBuildManager {
//...
ICollection IBuildManager.GetReferencedAssemblies() {
// This bails with InvalidOperationException with the message
// "This method cannot be called during the application's pre-start
// initialization stage."
return BuildManager.GetReferencedAssemblies();
}
//...
}
I found a SO commentary on this. I still wonder if there is something that can be manually initialized to make the above code happy. Anyone?
But in the absence of that...I can't help notice that the invocation comes from an implementation of IBuildManager. I explored the possibility of injecting my own IBuildManager, but I ran into the following problems:
IBuildManager is marked internal, so I need some other authorized derivation from it. It turns out that the assembly System.Web.Mvc.Test has a class called MockBuildManager, designed for test scenarios, which is perfect!!! This leads to the second problem.
The MVC distributable, near as I can tell, does not come with the System.Web.Mvc.Test assembly (DOH!).
Even if the MVC distributable did come with the System.Web.Mvc.Test assembly, having an instance of MockBuildManager is only half the solution. It is also necessary to feed that instance into the DefaultControllerFactory. Unfortunately the property setter to accomplish this is also marked internal (DOH!).
In short, unless I find another way to "initialize" the MVC framework, my options now are to either:
COMPLETELY duplicate the source code for DefaultControllerFactory and its dependencies, so that I can bypass the original GetReferencedAssemblies() issue. (ugh!)
COMPLETELY replace the MVC distributable with my own build of MVC, based on the MVC source code - with just a couple internal modifiers removed. (double ugh!)
Incidentally, I know that the MvcContrib "TestHelper" has the appearance of accomplishing my goal, but I think it is merely using reflection to find the controller - rather than using the actual IControllerFactory to retrieve a controller type / instance.
A big reason why I want this test capability is that I have made a custom controller factory, based on DefaultControllerFactory, whose behavior I want to verify.
I'm not quite sure what you're trying to accomplish here. If it's just testing your route setup; you're way better off just testing THAT instead of hacking your way into internals. 1st rule of TDD: only test the code you wrote (and in this case that's the routing setup, not the actual route resolving technique done by MVC).
There are tons of posts/blogs about testing a route setup (just google for 'mvc test route'). It all comes down to mocking a request in a httpcontext and calling GetRouteData.
If you really need some ninja skills to mock the buildmanager: there's a way around internal interfaces, which I use for (LinqPad) experimental tests. Most .net assemblies nowadays have the InternalsVisibleToAttribute set, most likely pointing to another signed test assembly. By scanning the target assembly for this attribute and creating an assembly on the fly that matches the name (and the public key token) you can easily access internals.
Mind you that I personally would not use this technique in production test code; but it's a nice way to isolate some complex ideas.
void Main()
{
var bm = BuildManagerMockBase.CreateMock<MyBuildManager>();
bm.FileExists("IsCool?").Dump();
}
public class MyBuildManager : BuildManagerMockBase
{
public override bool FileExists(string virtualPath) { return true; }
}
public abstract class BuildManagerMockBase
{
public static T CreateMock<T>()
where T : BuildManagerMockBase
{
// Locate the mvc assembly
Assembly mvcAssembly = Assembly.GetAssembly(typeof(Controller));
// Get the type of the buildmanager interface
var buildManagerInterface = mvcAssembly.GetType("System.Web.Mvc.IBuildManager",true);
// Locate the "internals visible to" attribute and create a public key token that matches the one specified.
var internalsVisisbleTo = mvcAssembly.GetCustomAttributes(typeof (InternalsVisibleToAttribute), true).FirstOrDefault() as InternalsVisibleToAttribute;
var publicKeyString = internalsVisisbleTo.AssemblyName.Split("=".ToCharArray())[1];
var publicKey = ToBytes(publicKeyString);
// Create a fake System.Web.Mvc.Test assembly with the public key token set
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "System.Web.Mvc.Test";
assemblyName.SetPublicKey(publicKey);
// Get the domain of our current thread to host the new fake assembly
var domain = Thread.GetDomain();
var assemblyBuilder = domain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
moduleBuilder = assemblyBuilder.DefineDynamicModule("System.Web.Mvc.Test", "System.Web.Mvc.Test.dll");
AppDomain currentDom = domain;
currentDom.TypeResolve += ResolveEvent;
// Create a new type that inherits from the provided generic and implements the IBuildManager interface
var typeBuilder = moduleBuilder.DefineType("Cheat", TypeAttributes.NotPublic | TypeAttributes.Class, typeof(T), new Type[] { buildManagerInterface });
Type cheatType = typeBuilder.CreateType();
// Magic!
var ret = Activator.CreateInstance(cheatType) as T;
return ret;
}
private static byte[] ToBytes(string str)
{
List<Byte> bytes = new List<Byte>();
while(str.Length > 0)
{
var bstr = str.Substring(0, 2);
bytes.Add(Convert.ToByte(bstr, 16));
str = str.Substring(2);
}
return bytes.ToArray();
}
private static ModuleBuilder moduleBuilder;
private static Assembly ResolveEvent(Object sender, ResolveEventArgs args)
{
return moduleBuilder.Assembly;
}
public virtual bool FileExists(string virtualPath) { throw new NotImplementedException(); }
public virtual Type GetCompiledType(string virtualPath) { throw new NotImplementedException(); }
public virtual ICollection GetReferencedAssemblies() { throw new NotImplementedException(); }
public virtual Stream ReadCachedFile(string fileName) { throw new NotImplementedException(); }
public virtual Stream CreateCachedFile(string fileName) { throw new NotImplementedException(); }
}

Asp.net MVC VirtualPathProvider views parse error

I am working on a plugin system for Asp.net MVC 2. I have a dll containing controllers and views as embedded resources.
I scan the plugin dlls for controller using StructureMap and I then can pull them out and instantiate them when requested. This works fine. I then have a VirtualPathProvider which I adapted from this post
public class AssemblyResourceProvider : VirtualPathProvider
{
protected virtual string WidgetDirectory
{
get
{
return "~/bin";
}
}
private bool IsAppResourcePath(string virtualPath)
{
var checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
return checkPath.StartsWith(WidgetDirectory, StringComparison.InvariantCultureIgnoreCase);
}
public override bool FileExists(string virtualPath)
{
return (IsAppResourcePath(virtualPath) || base.FileExists(virtualPath));
}
public override VirtualFile GetFile(string virtualPath)
{
return IsAppResourcePath(virtualPath) ? new AssemblyResourceVirtualFile(virtualPath) : base.GetFile(virtualPath);
}
public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies,
DateTime utcStart)
{
return IsAppResourcePath(virtualPath) ? null : base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
}
internal class AssemblyResourceVirtualFile : VirtualFile
{
private readonly string path;
public AssemblyResourceVirtualFile(string virtualPath)
: base(virtualPath)
{
path = VirtualPathUtility.ToAppRelative(virtualPath);
}
public override Stream Open()
{
var parts = path.Split('/');
var resourceName = Path.GetFileName(path);
var apath = HttpContext.Current.Server.MapPath(Path.GetDirectoryName(path));
var assembly = Assembly.LoadFile(apath);
return assembly != null ? assembly.GetManifestResourceStream(assembly.GetManifestResourceNames().SingleOrDefault(s => string.Compare(s, resourceName, true) == 0)) : null;
}
}
The VPP seems to be working fine also. The view is found and is pulled out into a stream. I then receive a parse error Could not load type 'System.Web.Mvc.ViewUserControl<dynamic>'. which I can't find mentioned in any previous example of pluggable views. Why would my view not compile at this stage?
Thanks for any help,
Ian
EDIT:
Getting closer to an answer but not quite clear why things aren't compiling. Based on the comments I checked the versions and everything is in V2, I believe dynamic was brought in at V2 so this is fine. I don't even have V3 installed so it can't be that. I have however got the view to render, if I remove the <dynamic> altogether.
So a VPP works but only if the view is not strongly typed or dynamic
This makes sense for the strongly typed scenario as the type is in the dynamically loaded dll so the viewengine will not be aware of it, even though the dll is in the bin. Is there a way to load types at app start? Considering having a go with MEF instead of my bespoke Structuremap solution. What do you think?
The settings that allow parsing of strongly typed views are in ~/Views/Web.Config. When the view engine is using a virtual path provider, it is not in the views folder so doesn't load those settings.
If you copy everything in the pages node of Views/Web.Config to the root Web.Config, strongly typed views will be parsed correctly.
Try to add content of Views/Web.config directly to your main web.config under specific location, e.g. for handling virtual paths like ~/page/xxx. See more details here: http://blog.sergkazakov.com/2011/01/aspnet-strongly-typed-view-and-virtual.html
Is there a way to load types at app start?
Yes, you may use BuildManager.AddReferencedAssembly(assembly), where assembly is the one, containing the requested type. So, once you use MEF, the last should be easy, but beware, everything should be done before Application_Start, so you may wish to use PreApplicationStartMethodAttribute.

ASP .NET MVC VirtualPathProvider

I am writing a VirtualPathProvider to dynamically load my MVC views, which are located in a different directory. I successfully intercept the call before MVC (in FileExists), but in my VirtualPathProvider, I get the raw, pre-routed url like:
~/Apps/Administration/Account/LogOn
Personally, I know that MVC will look for
~/Apps/Administration/Views/Account/LogOn.aspx
and that I should be reading the file contents from
D:\SomeOtherNonWebRootDirectory\Apps\Administration\Views\Account\LogOn.aspx
but I'd rather not hard code the logic to "add the directory named Views and add aspx to the end".
Where is this logic stored and how can I get it into my virtual path provider?
Thanks. Sorry if I'm not being clear.
Edited
You need to make a class that inherits WebFormViewEngine and sets the ViewLocationFormats property (inherited from VirtualPathProviderViewEngine).
The default values can be found in the MVC source code:
public WebFormViewEngine() {
MasterLocationFormats = new[] {
"~/Views/{1}/{0}.master",
"~/Views/Shared/{0}.master"
};
AreaMasterLocationFormats = new[] {
"~/Areas/{2}/Views/{1}/{0}.master",
"~/Areas/{2}/Views/Shared/{0}.master",
};
ViewLocationFormats = new[] {
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx",
"~/Views/Shared/{0}.ascx"
};
AreaViewLocationFormats = new[] {
"~/Areas/{2}/Views/{1}/{0}.aspx",
"~/Areas/{2}/Views/{1}/{0}.ascx",
"~/Areas/{2}/Views/Shared/{0}.aspx",
"~/Areas/{2}/Views/Shared/{0}.ascx",
};
PartialViewLocationFormats = ViewLocationFormats;
AreaPartialViewLocationFormats = AreaViewLocationFormats;
}
You should then clear the ViewEngines.Engines collection and add your ViewEngine instance to it.
As SLaks mentioned above, you need to create a Custom View Engine and add your view-finding logic in the FindView method.
public class CustomViewEngine : VirtualPathProviderViewEngine
{
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
//Set view path
string viewPath = GetCurrentViewPath();
//Set master path (if need be)
string masterPath = GetCurrentMasterPath();
return base.FindView(controllerContext, viewPath, masterPath, useCache);
}
}
In the Application_Start, you can register your View Engine like this:
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine());
The answer was that MVC was not finding my controller properly. If MVC does in fact find your controller properly, there should be two requests processed by the VirtualPathProvider:
An initial request with the acutal url requested (ie. http://.../Account/LogOn).
A subsequent FileExists check for http://.../Views/Account/LogOn.aspx, after the request in 1. returns false calling FileExists. This actually retuns the aspx content.

Change the Views location

I am developing a website in MVC 2.0. I want to change the View folder location in my website. I wanted to keep the views folder inside other folders, When I try to do so i am getting following errors
The view 'Index' or its master was not found. The following locations were searched:
~/Views/Search/Index.aspx
~/Views/Search/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
My Views folder will be in ~/XYZ/ABC/Views instead of ~/Views. Please solve my problem. Will I get any problems If I change the default Views folder location. Do I need to change anything in HTML Helper classes because I don't know anything in MVC as this is my starting project i dont want to risk..Please help me out...
You'll need to create a custom view engine and use that instead. Fortunately you can just inherit from the default one and change the locations on the constructor. Here's a guide to creating your own view engine: http://www.singingeels.com/Articles/Creating_a_Custom_View_Engine_in_ASPNET_MVC.aspx
From the article:
protected void Application_Start()
{
//... other things up here.
// I want to REMOVE the ASP.NET ViewEngine...
ViewEngines.Engines.Clear();
// and then add my own :)
ViewEngines.Engines.Add(new HoTMeaTViewEngine());
}
public class HoTMeaTViewEngine : VirtualPathProviderViewEngine
{
public HoTMeaTViewEngine()
{
// This is where we tell MVC where to look for our files. This says
// to look for a file at "Views/Controller/Action.html"
base.ViewLocationFormats = new string[] { "~/Views/{1}/{0}.html" };
base.PartialViewLocationFormats = base.ViewLocationFormats;
}
}
Check this place out. How to change default view location scheme in ASP.NET MVC?
base.ViewLocationFormats = new string[] {
"~/Views/{1}/{2}/{0}.aspx",
"~/Views/{1}/{2}/{0}.ascx",
"~/Views/Shared/{2}/{0}.aspx",
"~/Views/Shared/{2}/{0}.ascx" ,
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx",
"~/Views/Shared/{0}.ascx"
Even easier is this one Can I specify a custom location to “search for views” in ASP.NET MVC?
As an alternative, you can override the view engine locations for a specific controller without affecting the view engines for the other controllers.
These are some snippets from a product I am developing, but it shows the constructor for one of my controllers, and a view engine I made specificially for controllers that inherit from KBRenderMvcController.
So any controller based off KBRenderMvcController will also have my view engine.
However at no point did I clear the view engine collection, which is relevant. Because I wanted the views my product is using to fall back to default locations.
In short, if you delete \App_plugins\Product\Views\MyView And instead create a \Views\MyView it will still render from \Views\MyView instead.
Also in the ViewEngine I demonstrate code that determines the type of controller being used and if it's not a target controller I return empty view locations so they don't get used for other controllers.
#region Constructor
public KBRenderMvcController()
: base()
{
viewEngine = new KBFrontEndViewEngine();
if (!this.ViewEngineCollection.Contains(viewEngine))
this.ViewEngineCollection.Insert(0, viewEngine);
}
#endregion
public class KBFrontEndViewEngine : RazorViewEngine
{
#region Fields
private static bool _Initialized = false;
private static string[] viewLocationFormats = null;
private static string[] partialViewLocationFormats = null;
private static string[] viewEngineFileExtensions = new string[] { "cshtml" };
#endregion
#region Constructor
public KBFrontEndViewEngine()
{
if (!_Initialized)
{
viewLocationFormats = new string[]
{
string.Concat(KBApplicationCore.PluginRelUrl, "/Views/{1}/{0}.cshtml"),
string.Concat(KBApplicationCore.PluginRelUrl, "/Views/Partials/{0}.cshtml")
};
partialViewLocationFormats = new string[]
{
string.Concat(KBApplicationCore.PluginRelUrl, "/Views/{1}/Partials/_partial{0}.cshtml"),
string.Concat(KBApplicationCore.PluginRelUrl, "/Views/Partials/_partial{0}.cshtml"),
string.Concat(KBApplicationCore.PluginRelUrl, "/Views/{1}/Dialogs/_dialog{1}.cshtml"),
string.Concat(KBApplicationCore.PluginRelUrl, "/Views/Dialogs/_dialog{1}.cshtml"),
};
_Initialized = true;
}
base.ViewLocationFormats = viewLocationFormats;
base.PartialViewLocationFormats = partialViewLocationFormats;
base.MasterLocationFormats = viewLocationFormats;
base.FileExtensions = viewEngineFileExtensions;
}
#endregion
#region Methods
//Don't run on requests that are not for our hijacked controllers
public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
{
Type controllerType = controllerContext.Controller.GetType();
Type baseType = controllerType.BaseType;
if ((baseType != null) && (baseType.Name == "KBRenderMvcController`1") || (baseType.Name == "KBFrontEndBaseSurfaceController"))
return base.FindPartialView(controllerContext, partialViewName, useCache);
else
return new ViewEngineResult(new List<string>());
}
#endregion
}

Resources