2

我目前正在使用 MVC 3 组合一个多租户 Web 应用程序。至少 30 个不同的网站将共享一个公共代码库,并且在共享类似的底层功能的同时,它们需要看起来有很大的不同。因此,我使用 URL 在内部分离客户端,并使用重写的 Razor 视图引擎(至少在查找视图方面)自动选择给定操作的自定义视图或默认视图。

为了帮助“划分”一个复杂的页面,任何特定的视图都将使用几个局部视图,通常呈现为独立的操作,因此通常自定义视图或局部视图只有很小的 HTML 差异,有助于最小化任何特定于客户的网站。

我希望你遵循这个背景!

因此,一个 HTML 页面可能由许多少量的 HTML 部分视图组成,这些视图可能来自客户端的特定文件夹或通用版本。我希望通过轻松查看文件夹结构中他想要更改的 HTML 位的位置,使我们的设计师更容易对页面进行细微的更改

我的建议是,每个部分都将用 HTML 注释“括起来”,例如:

{部分内容}

显然我可以手动输入这些内容,但这只是自找麻烦、拼写错误、复制然后修改的客户端版本没有使用正确的 URL 更新。我认为应该可以从某些上下文中获取并注入它。

同时,我需要不能对某些 Actions 执行此操作。例如,partial可能会在 textarea 内生成文本,例如,因此评论不适合在那里。总的来说,我很乐意发表这些评论,除非我指定它不合适。

对我来说,这建议在操作上使用 ActionFilter,我可以在站点范围内应用它,然后针对某些操作关闭它。我希望其中一个可覆盖的事件能让我确定这条路径,但我似乎无法找到它存储的任何地方。此外, OnResultExecuting 似乎在选择 Partial 之前触发,而 OnResultExecuted 似乎已经写出了 Partial 的内容,所以我无法在此处插入起始注释。我也找不到对所选部分路径的任何引用。

为了完整起见,我的意图是这个属性只在调试模式下编译时才写这些注释。

那么,有谁知道我如何能够在 FindPartialView 和属性之间没有任何破解的情况下获得所选视图的路径?我的 Attribute 方法是最佳选择还是有更简单的方法来做到这一点?也许已经内置了一些东西!

非常感谢您的帮助。

4

1 回答 1

0

好吧,我从来没有忘记想要这个,并且一直希望有一天我能解决它,谢天谢地我做到了。

我已经覆盖了默认的 WebViewPage(我使用 Razor 引擎),特别是 ExecutePageHierarchy 来注入评论:

public abstract class PaladinWebViewPage : PaladinWebViewPage<dynamic>
{
}

public abstract class PaladinWebViewPage<TModel> : WebViewPage<TModel>
{
    public bool DisplaySourceCodeComments
    {
        get { return ((bool?) ViewBag.__DisplaySourceCodeComments) ?? false; }
        set { ViewBag.__DisplaySourceCodeComments = value; }
    }

    public override void ExecutePageHierarchy()
    {
        base.ExecutePageHierarchy();

        // Filters can be used to set and clear this value so we can decide when to show this comment
        if (!DisplaySourceCodeComments) return;

        var sw = Output as StringWriter;
        if (sw == null) return;

        var sb = sw.GetStringBuilder();
        sb.Insert(0, string.Format("<!-- Start of {0} -->", VirtualPath));
        sb.AppendFormat("<!-- End of {0} -->", VirtualPath);
    }

VirtualPath 告诉我们用于构建 HTML 的确切文件,因此我们可以在之前和之后注入文件名。这目前没有做任何事情,因为默认设置是显示评论(DisplaySourceCodeComments 中的“?? false”)。

此外,要使用此视图页面,您需要编辑 Views/Web.config 并将 pageBaseType 更改为此类型。

我想有选择地打开和关闭这些评论,所以我创建了一个 ActionFilter:

public class DisplaySourceCodeCommentsAttribute : ActionFilterAttribute
{
    private readonly bool _displaceSourceCodeComments;

    public DisplaySourceCodeCommentsAttribute(bool displaceSourceCodeComments)
    {
        _displaceSourceCodeComments = displaceSourceCodeComments;
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        var viewResult = filterContext.Result as ViewResultBase;
        if (viewResult == null) return;

        viewResult.ViewBag.__DisplaySourceCodeComments = _displaceSourceCodeComments;
    }
}

我有点不高兴我不得不在这里使用 ViewBag 并在视图页面覆盖中单独使用,因为它们没有紧密链接,但我找不到过滤器直接与视图页面交互的方法,所以这是一个必要的软糖。它确实有一个好处,即显示视图或部分的源代码也会自动为任何子部分显示它,直到您再次将其关闭,因为 ViewBag 是沿着链传递的。

有了这个,任何操作都可以使用 [DisplaySourceCodeComments(true)] 打开源代码注释

或者,显然用 false 再次关闭它

Attribute 检查上下文结果是否为 ViewResultBase,这意味着只有 Views 和 Partials,因此 Json 或 Content 或重定向不受影响,这也非常方便。

最后,我在调试模式下运行时将此操作过滤器设为全局,以便每个视图和部分视图都包含源注释,方法是在 global.asax.cs 中添加以下行:

[#]如果调试

        // When in debug mode include HTML comments showing where a view or partial has come from
        GlobalFilters.Filters.Add(new DisplaySourceCodeCommentsAttribute(true));

[#]万一

我真的很高兴我终于把它整理好了,所以我希望这对其他人有用。

于 2011-09-23T08:54:33.400 回答