2

現在、MVC 3を使用してマルチテナンシーWebアプリを作成しています。少なくとも30の異なるWebサイトが共通のコードベースを共有し、同様の内部機能を共有する一方で、それらは大幅に異なるように見える必要があります。結果として、URLを使用してクライアントを内部的に分離し、オーバーライドされたRazorビューエンジン(少なくともビューの検索に関して)を使用して、特定のアクション用にカスタマイズされたビューまたはデフォルトのビューを自動的に選択します。

複雑なページを「コンパートメント化」するために、特定のビューはいくつかのパーシャルを使用し、通常は自己完結型のアクションとしてレンダリングされるため、通常、カスタムビューまたはパーシャルビューのHTMLの違いはわずかであり、に固有のコードを最小限に抑えるのに役立ちます。クライアントのサイト。

あなたがその背景に従ったことを願っています!

したがって、1つのHTMLページは、クライアントの特定のフォルダーまたは汎用バージョンから取得される可能性のあるHTML部分ビューの小さな断片で構成されている可能性があります。デザイナーが変更したいHTMLのビットがフォルダー構造のどこにあるかを簡単に確認できるようにすることで、デザイナーがページに小さな変更を加えやすくすることを望んでいます。

私の提案は、各パーシャルが次のようなHTMLコメントで「括弧で囲まれる」ことです。

{部分的な内容}

明らかに、これらを手動で挿入することもできますが、それは問題、タイプミス、コピーされてから変更されたクライアントバージョンが正しいURLで更新されていないことを求めているだけです。ある文脈からこれを取得して注入することは可能であると私は思います。

同時に、特定のアクションではこれを実行できないようにする必要があります。たとえば、パーシャルがテキストエリア内にテキストを生成している可能性があるため、コメントは適切ではありません全体として、適切でないことを明記しない限り、これらのコメントを喜んで入力します。

私にとって、これはアクションにActionFilterを提案します。これは、サイト全体に適用してから、特定のアクションに対してオフにすることができます。オーバーライド可能なイベントの1つでこのパスを確認できるといいのですが、保存されている場所が見つからないようです。さらに、OnResultExecutingは、Partialが選択される前に起動しているようであり、OnResultExecutedはすでにPartialの内容を書き出しているようであるため、ここに開始コメントを挿入することはできません。また、選択したパーシャルのパスへの参照が見つかりません。

完全を期すために、この属性はデバッグモードでコンパイルされた場合にのみこれらのコメントを書き込むことを意図しています。

それで、FindPartialViewと属性の間のハックなしで、選択したビューへのパスを取得する方法を誰かが知っていますか?私の属性メソッドが最良の選択ですか、それともこれを行うためのより簡単な方法がありますか?おそらく、何かがすでに組み込まれています!

助けてくれて本当にありがとうございます。

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で再度オフにします

属性は、コンテキスト結果がViewResultBaseであることを確認します。これは、ビューとパーシャルのみを意味するため、Json、コンテンツ、またはリダイレクトは影響を受けません。これも非常に便利です。

最後に、デバッグモードで実行しているときに、このアクションフィルターをグローバルにして、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));

[#] endif

ようやく仕分けできて本当に嬉しいので、他の人にも役立つといいですね。

于 2011-09-23T08:54:33.400 に答える