2013-05-10 11 views
11

私はレイアウトがより複雑になるように進化したケースがあります。 @section styleIncludes{ ... }のような通常のものがあります。そして、現在のページブレッドクラムの構造のように、各ページがオプションで(しかしほとんどの場合は)指定できるすべての種類のものを定義するその他のセクションがあります。これらのすべてがセクションである理由は、レイアウトの構造に埋め込まれているためです。正確な彼らの綴り、またはピースミールコピー/ペーストを覚えしようとするのではなく、8かそこらの異なるセクションがありますので剃刀のセクション名のヒント/流暢?

私は、自分が前のページのコピーを作る見つけます。

これらのために流暢なAPIを作成して、8個の関数を持ち、それぞれがオブジェクトを返すようにしたいと思っています。そのため、Sections.Style(MVCテキストテンプレートやかみそりの編集?)パンフレット(等)

主な目的は、これらのセクションをガイド形式でコーディングして、完璧なタイピングやコピー/ペーストに頼るのではなく、名前を強く入力することです。

かみそり戻りMvcHtmlStringでただし、拡張/ヘルパー、と私は@sectionが完全に別のもので表されている想像してみてください。

私のために完全な解決策を書くように求めるのではなく、どのように先行するかについてのいくつかのアイデアを書いてください。

何物は@section宣言を表現するためのヘルパー返す必要がありますか?I。 MvcHtmlStringの類推。

あなたは、スタイルやブレッドクラムのような、流暢なメソッドのパラメータの型を何を示唆していますか?私は、セクション宣言の中括弧の中にカミソリを書く能力が似ているように渡されたカミソリを欲しいと思います。たとえば、通常のセクション宣言と同様に、カミソリページで宣言されたローカル変数にアクセスする機能があります。私は本当に、私のCSHTMLページの多くは

@{ 
    string title = "Edit Person" 
    ViewBag.Title = title; 
} 
@section styles{ 
    .someOneOffPageSpecificStyle { width:59px } 
} 
@section javascript{ 
    //javascript includes which the layout will place at the bottom... 
} 
@section breadcrumb{ 
    <a ...>Parent Page</a> &gt; <a ...>Sub Page</a> &gt; @title 
} 

ような何かを始める場合、私はむしろ、このような流暢なAPIのseomの並べ替えを持っているだろう、つまり.SomeSection("<div...>Bunch of html stuffed in a string</div>")

のような文字列連結のようなものをないしたくありませんコードの結果として、スタイルのためではなく、コードを書くとインテリセンスがお手伝いしますので、タイプミスなどに問題がないことが容易になりますので:

@{ 
    string title = "Edit Person" 
    ViewBag.Title = title; 
} 
@Sections 
.Styles(@<text> 
    .someOneOffPageSpecificStyle { width:59px } 
</text>) 
.Javascript(@<text> 
    //javascript includes which the layout will place at the bottom... 
</text>) 
.Breadcrumb(@<text> 
    <a ...>Parent Page</a> &gt; <a ...>Sub Page</a> &gt; @title 
</text>) 
+0

なぜ共通のレイアウトで組み立てられていないセクションがたくさんあるのですか? (そして私はあなたができるとは思わない、セクションを宣言し、それぞれの内部であなたの拡張メソッドを呼び出さなければならない) –

+0

彼らは共通のレイアウトで組み立てられています。レイアウトのさまざまな部分に多くのセクションを定義できます。ブレッドクラムは1つの場所に表示され、別の場所にはスタイルなどが表示されますが、実際は同じレイアウトになっています。 – AaronLS

+0

次に、一般的なレイアウトで一度しかやっていないので、なぜこれらのセクションをすべて生成するヘルパーメソッドが必要なのでしょうか? –

答えて

2

ほとんどの場合、これは(セクションを使用して)ことはできません。

まず、MVCがどのように動作するかを理解する必要があります。私たちはcshtmlファイルを作成しますが、これらのファイルは最終的には.Net classにコンパイルされ、インスタンス化され、メソッドが実行されます(ほとんどの場合Execute())。 RenderActionの動作とまったく同じではありません。子のアクションメソッドを呼び出し、その結果を親ビューのインラインでレンダリングします)。 HtmlHelpers(またはカスタムヘルパー)はinstaniatedクラス(delegate)から呼び出されるだけなので、cshtmlファイルのコードがコンパイルされると実行できます。

System.Web.Razor.Generator.SectionCodeGeneratorは、セクションを作成するには、文字列の定義が必要です。したがって、セクションを定義するときには、HtmlHelperやカスタムヘルパーはファイルがコンパイルされるまで実行されないので、ファイルがコンパイルされる前にcshtmlファイルに文字列が存在しなければなりません。コンパイルする前にcshtmlファイルを更新できます。

あなたはになります。は、独自のHtmlHelperやその他のカスタムヘルパーを作成して、セクションが提供するものと似たようなことを行います(実際にはセクションを使用せずに)。例えば、I wrote this because I needed to write Javascript from partial views and/or templates (which you can't do with sections)。セクションを使用する必要がある場合、これは役に立たないかもしれません。

次のコードはです。例のみこれはひげそりが実際にどのように(すべてのコードを見て)動作していません。しかし、この例を理解させるために、コードと命名規則のようなかみそりを使用します。

layout.cshtml

<html> 
<body> 
@RenderSection("MySectionName") 

@RenderBody(); 
</body> 
</html> 

Index.cshtml

@{ 
    _layout = "layout"; 
} 

@section MySection { 
    <div>MySection</div> 
} 

<div>My Body</div> 

はたぶん似ているクラスにコンパイルさ:

public class app_aspnet_layout : System.Web.Mvc.WebViewPage 
{ 

    public Execute() 
    { 
    throw new NotImplementedException(); 
    } 

    public void ExecutePageHierarchy(WebPageContext pageContext, 
            TextWriter writer) 
    { 
    writer.Write("<html>") 
    writer.Write("<body>") 

    var section = pageContext.SectionWriters["MySectionName"]; 
    section(); 

    pageContext.View.ExecutePageHierarchy(null, writer) 

    writer.Write("</body>") 
    writer.Write("</html>") 
    } 
} 

public class app_aspnet_index : System.Web.Mvc.WebViewPage 
{ 
    // generated from the _layout Definition 
    private WebViewPage startPage = new app_aspnet_layout(); 

    public Execute() 
    { 
    WebPageContext pageContext = new WebPageContext(); 
    pageContext.View = this; 

    pageContext.SectionWriters.Add("MySectionName", 
            this.Section_MySectionName); 

    var writer = HttpContext.Current.Response.Stream.AsTextWriter(); 

    if (startPage != null) 
    { 
     startPage.ExecutePageHierarchy(pageContext, writer); 
    } 
    else 
    { 
     this.ExecutePageHierarchy(pageContext, writer); 
    } 
    } 

    // html generated from non-section html 
    public void ExecutePageHierarchy(WebPageContext pageContext, 
            TextWriter writer) 
    { 
    writer.Write("<div>My Body</div>"); 
    } 

    public void Section_MySectionName(TextWriter writer) 
    { 
    writer.Write("<div>MySection</div>"); 
    } 
} 
+0

私はそれを見ていきます。一般的にうまくいくと思う。また、部分的にセクションを定義できないという、あなたが話す他の無関係な問題も解決します。 – AaronLS

+0

**しかし、これらのファイルは最終的に完全な.Netクラスにコンパイルされます**完全な.netクラスの意味を教えてください。 –

+0

'Public Class MyClass {}' –

0

あなたは別の方向から問題に取り組むことができ - t4テンプレートを使用します。

レイアウトの構造がかなり安定している(つまり、セクションを頻繁に追加したり削除したりしない)場合、新しいビューを作成するときにコピーして貼り付けるのを止めるだけで済みます。それはあなたの仕様にあなたのビューを作成する - あなたは反射や他のロジックでそれらのいくつかの非常に巧妙なものを行うことができます

"codetemplates"を検索するコードテンプレートをロードするナゲットがあります - そして彼らはかなりまっすぐです使用する。

+0

これはうまくいくが、強く型付けされるためには型をコンパイルしなければならないだろう(HtmlHelperとCustomerヘルパーはビュー/レイアウトがコンパイルされたときには実行されない。 T4テンプレートのクラスライブラリを使用すると複雑になる –

+0

t4テンプレートのどの部分を「強く型付けする」必要がありますか? – StanK

+1

OP質問 ' T4テンプレートが厳密に型指定された型を使用するためには、型定義された型を定義する必要があります。コンパイルされたクラスビューのT4テンプレート外でも使用できるようにします(そうしないと、セクションを定義するビューは強く型付けされません)。 –

1

resharperがある場合は、ライブコードテンプレート(強力なスニペット)をお勧めします。

create a templateには、1つのパラメータを指定できます。このパラメータのマクロソースは、コンマで区切られた値のリストです。 テンプレート/スニペットを使用すると、セクション名を選択できるインテリセンスボックスが表示されます。

使用するセクションの名前が変更されない場合は、という新しいセクション名を含むようにテンプレートを頻繁に編集する必要はありません。

関連する問題