我有一个网站,将有定制的设计,取决于“商店”被点击.
所以,我有一个文件夹结构,比如:
+ _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方法/overrides/等等来解决这个问题。
更新:
谢谢!
发布于 2009-10-25 23:53:48
我建议您使用带有一些自定义搜索位置的专用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代码,以了解框架是如何完成的。
发布于 2009-10-26 02:42:03
解决这个问题的一种方法可能是创建Controller子类作为控制器的公共基类。您可以定义像View()这样的备用操作函数,它使用路由数据和方法params来决定应该使用哪个视图,然后只返回一个标准的ViewResult实例。(您可以从不直接用于映射到控制器或其参数的路由的URL中提取信息。)
但是,创建WebFormViewEngine的自定义子类可能更简洁(因为人们可能希望在那里找到此类代码)。然后,如果不是所有控制器都有这种行为,那么第一种方法可能会更好。
发布于 2009-10-26 09:06:45
这听起来很像区域,检查这里和这里,以及"asp.net mvc区域“的共同点。我只是不确定“默认”区域,但我认为这是可以做到的。注意,ASP.NET MVC v2 (现在在Beta中)有本地区域支持。
https://stackoverflow.com/questions/1622057
复制相似问题