首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >需要定制ViewEngine吗?

需要定制ViewEngine吗?
EN

Stack Overflow用户
提问于 2009-10-25 21:03:04
回答 3查看 364关注 0票数 1

我有一个网站,将有定制的设计,取决于“商店”被点击.

所以,我有一个文件夹结构,比如:

代码语言:javascript
复制
 + _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

在我的控制器中,我将根据请求中的一个参数来决定使用哪个文件夹(当一个文件不能作为自定义的文件夹可用时,应该使用默认文件夹。)

因此,控制器执行了如下操作:

代码语言:javascript
复制
    public ActionResult Index(int id)
    {
        var newRouteParamThatWouldntFitIntoTheCurrentViewMethodLikeThis = DoSomeMagicalRoutingStuff(id);

        return View(newRouteParamThatWouldntFitIntoTheCurrentViewMethodLikeThis);
        //return View();
    }

如果这里没有“每个请求的动态路由”要求,我可以使用自定义的ViewEngine或其他什么的.

有没有人对如何实现这一点有一个想法(使用MVC上的工具)?我真的很想继续使用Html.RenderPartial方法和MVC的其他“好处”。这就是为什么我更喜欢用MVC方法/overrides/等等来解决这个问题。

更新:

  • 这些网站在设计、内容、使用"RenderPartial“等方面都不尽相同。
  • 观点真的不同..。不仅仅是书页..。
  • 控制器中的ID参数是标识应该使用哪个“文件夹”(例如custom_design_01 )。
  • URL将类似于:"/Stores/{id_of_design}/“,它调用示例控制器方法。然后,ctonroller返回视图“/Stores/{id_of_design}/ view /zbf.aspx”,例如

谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-10-25 23:53:48

我建议您使用带有一些自定义搜索位置的专用ViewEngine。由于您仍然在使用WebForms页面,所以只需从集成的WebFormViewEngine派生:

代码语言:javascript
复制
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代码,以了解框架是如何完成的。

票数 2
EN

Stack Overflow用户

发布于 2009-10-26 02:42:03

解决这个问题的一种方法可能是创建Controller子类作为控制器的公共基类。您可以定义像View()这样的备用操作函数,它使用路由数据和方法params来决定应该使用哪个视图,然后只返回一个标准的ViewResult实例。(您可以从不直接用于映射到控制器或其参数的路由的URL中提取信息。)

但是,创建WebFormViewEngine的自定义子类可能更简洁(因为人们可能希望在那里找到此类代码)。然后,如果不是所有控制器都有这种行为,那么第一种方法可能会更好。

票数 0
EN

Stack Overflow用户

发布于 2009-10-26 09:06:45

这听起来很像区域,检查这里这里,以及"asp.net mvc区域“的共同点。我只是不确定“默认”区域,但我认为这是可以做到的。注意,ASP.NET MVC v2 (现在在Beta中)有本地区域支持。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1622057

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档