我目前正在处理的应用程序是一个MVC3应用程序,它结合了标准视图实例化,并在物理视图不存在时从数据库中检索视图。我在实现自定义controllerfactory和virtualpathprovider时遇到404错误的问题,并且我不太确定我可能做错了什么。
我们想要的行为如下:
1)如果请求存在“物理”视图,则直接从文件系统提供(遵循标准的mvc行为)。在这种情况下,磁盘上将有标准的控制器/视图。 2)如果控制器/视图不存在,则检查是否有必要的信息存储在数据库中并从数据库中提供。将调用一个名为GenericController的控制器,然后该控制器将从数据库中获取视图数据。
我创建了一个自定义控制器工厂:
public class ControllerFactory : DefaultControllerFactory, IControllerFactory
{
protected override Type GetControllerType(RequestContext requestContext, string controllerName)
{
// check to see if this controller name can be resolved via DI. If it can, then hand this off to the Default factory.
Type returntype = base.GetControllerType(requestContext, controllerName);
// see if this is a type that is handled via the database. If it is, then send to the generic system controller for handling.
if (returntype == null)
{
// already requested?
if (requestContext.HttpContext.Items.Contains("vc"))
{
returntype = typeof(GenericSystemController);
}
else
{
if (viewcanberetrievedfromdb())
{
// TODO: check to see if the account has access to the module.
returntype = typeof(GenericSystemController);
requestContext.HttpContext.Items["vc"] = viewcontext;
}
}
}
return returntype;
}
以及自定义虚拟路径提供程序:
public class DbPathProvider : VirtualPathProvider
{
public DbPathProvider()
: base()
{
}
public override bool FileExists(string virtualPath)
{
// first see if there is a physical version of the file. If there is, then use that. Otherwise, go to the database.
// database calls are ALWAYS overridden by physical files.
bool physicalFileExists = base.FileExists(virtualPath);
if (!physicalFileExists)
physicalFileExists = HttpContext.Current.Items.Contains("vc");
return physicalFileExists;
}
public override VirtualFile GetFile(string virtualPath)
{
if (base.FileExists(virtualPath))
return base.GetFile(virtualPath);
else
return new DbVirtualFile(virtualPath);
}
如果请求的页面在文件系统中不存在,则应用程序流似乎可以正常工作: 1)首先调用virtualpathprovider中的FileExists返回false,以便IIS不会尝试作为静态文件。 2)调用控制器工厂中的GetControllerType方法,并适当地返回我的genericcontroller类型。 3)再次调用FileExists方法,这次返回true。 4)调用所有控制器工厂方法,包括ControllerRelease方法。
然而,GenericController实际上从未被调用过。 IIS返回404异常。
我需要在MVC控制器实例化管道中的其他地方捕获MVC请求吗?我有更好的方法来完成我想要完成的任务吗?
感谢。