我有一个定制设计的网站,具体取决于点击的“商店”...
所以,我有一个文件夹结构,如:
+ _default
- Site.Master
- Site.css
+ Views
- main.ascx
- xyz.ascx
- zbf.aspx
+ custom_design_01
- Site.Master
- Site.css
+ Views
- xyz.ascx
- zbf.aspx
+ custom_design_02
- Site.Master
- Site.css
+ Views
- xyz.ascx
- zbf.aspx
在我的控制器中,我将决定使用哪个文件夹,具体取决于请求中的参数(当文件不可用作自定义文件时,应使用默认文件夹..)
所以,控制器做了类似的事情:
public ActionResult Index(int id)
{
var newRouteParamThatWouldntFitIntoTheCurrentViewMethodLikeThis = DoSomeMagicalRoutingStuff(id);
return View(newRouteParamThatWouldntFitIntoTheCurrentViewMethodLikeThis);
//return View();
}
如果我没有“每个请求的动态路由”要求,我可以使用自定义的ViewEngine或其他东西......
有没有人知道如何实现这一点(使用MVC板载工具)?我真的想继续使用Html.RenderPartial方法和MVC的其他“好处”...这就是为什么我更喜欢用MVC方法/覆盖/等来解决这个问题。
更新
谢谢!
答案 0 :(得分:2)
我建议您使用专门的ViewEngine和一些自定义搜索位置。由于您仍在使用WebForms页面,因此您可以从集成的WebFormViewEngine中派生出来:
public class ThemedViewEngine : WebFormViewEngine {
private static readonly string[] _emptyLocations = new string[0];
//Format: {0} page name {1} controller {2} design
string[] _masterLocations = new[] {
"~/Views/{2}/{0}.master"
};
string[] _viewLocations = new[] {
"~/Views/{2}/{1}/{0}.aspx",
"~/Views/{2}/Shared/{0}.aspx",
};
#region View search
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) {
string[] viewLocationsSearched;
string[] masterLocationsSearched;
string viewPath = FindPath(controllerContext, _viewLocations, viewName, _cacheKeyPrefix_View, useCache, out viewLocationsSearched);
string masterPath = FindPath(controllerContext, _masterLocations, masterName, _cacheKeyPrefix_Master, useCache, out masterLocationsSearched);
//Check if one view missing
if (String.IsNullOrEmpty(viewPath) || (String.IsNullOrEmpty(masterPath) && !String.IsNullOrEmpty(masterName))) {
return new ViewEngineResult(viewLocationsSearched.Union(masterLocationsSearched));
}
return new ViewEngineResult(CreateView(controllerContext, viewPath, masterPath), this);
}
//Same thing as above, but without master page
public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) {
string[] viewLocationsSearched;
string viewPath = FindPath(controllerContext, _viewLocations, partialViewName, _cacheKeyPrefix_Partial, useCache, out viewLocationsSearched);
if (String.IsNullOrEmpty(viewPath)) {
return new ViewEngineResult(viewLocationsSearched);
}
return new ViewEngineResult(CreatePartialView(controllerContext, viewPath), this);
}
protected string FindPath(ControllerContext context, string[] locations, string viewName, string prefix, bool useCache, out string[] searched) {
searched = _emptyLocations;
if (string.IsNullOrEmpty(viewName))
return string.Empty;
//Prepare your data here
string controllerName = context.RouteData.GetRequiredString("controller");
string designName = /* YOUR WAY OF GETTING THE DESIGN */;
string result = FindPathGeneral(context, locations, viewName, controllerName, designName, out searched);
return result;
}
/// <summary>
/// Finds the complete path for a general view page.
/// </summary>
private string FindPathGeneral(ControllerContext context, string[] locations, string viewName, string controllerName, string designName, out string[] searched) {
string result = string.Empty;
searched = new string[locations.Length];
for (int i = 0; i < locations.Length; i++) {
//Build virtual path from the locations defined on top
string virtualPath = String.Format(CultureInfo.InvariantCulture, locations[i],
viewName, controllerName, designName);
if (FileExists(context, virtualPath)) {
searched = _emptyLocations;
return virtualPath;
}
searched[i] = virtualPath;
}
return result;
}
#endregion
}
这应该适合您的情况,前提是您在FindPath
方法中找到了所需的设计名称。
为简单起见,上面的示例未实现视图缓存。您可以使用反射器(或源代码)查看WebFormViewEngine
代码,以了解框架是如何完成的。
答案 1 :(得分:0)
您可以解决此问题的一种方法是创建一个Controller子类作为控制器的公共基类。您可以定义一个替代操作函数,如View()
,它使用路径数据和方法参数来决定应该使用哪个视图,然后只返回一个标准ViewResult
实例。 (您可以从路径中的URL中提取信息,该路径不直接用于映射到控制器或其参数。)
然而,创建WebFormViewEngine
的自定义子类可能会更清晰(因为人们可能希望找到那种代码)。然后,如果不是所有的控制器都有这种行为,第一种方法可能会更好。
答案 2 :(得分:0)