ASP.NET Core のタグ ヘルパー作成Author Tag Helpers in ASP.NET Core

作成者: Rick AndersonBy Rick Anderson

サンプル コードを表示またはダウンロードします (ダウンロード方法)。View or download sample code (how to download)

タグ ヘルパーの概要Get started with Tag Helpers

このチュートリアルでは、タグ ヘルパーのプログラミングの概要を提供します。This tutorial provides an introduction to programming Tag Helpers. タグ ヘルパーの概要に関するページでは、タグ ヘルパーが提供する利点について説明しています。Introduction to Tag Helpers describes the benefits that Tag Helpers provide.

タグ ヘルパーは、ITagHelper インターフェイス実装する任意のクラスです。A tag helper is any class that implements the ITagHelper interface. ただし、タグ ヘルパーを作成する場合は、通常は TagHelper から派生させます。こうすることで、Process メソッドにアクセスできるようになります。However, when you author a tag helper, you generally derive from TagHelper, doing so gives you access to the Process method.

  1. AuthoringTagHelpers という新しい ASP.NET Core プロジェクトを作成します。Create a new ASP.NET Core project called AuthoringTagHelpers. このプロジェクトに認証は必要ありません。You won't need authentication for this project.

  2. タグ ヘルパーを保持する TagHelpers というフォルダーを作成します。Create a folder to hold the Tag Helpers called TagHelpers. TagHelpers フォルダーは必須ではありませんが、あると便利です。The TagHelpers folder is not required, but it's a reasonable convention. それでは、いくつか単純なタグ ヘルパーを記述してみましょう。Now let's get started writing some simple tag helpers.

最小のタグ ヘルパーA minimal Tag Helper

このセクションでは、電子メール タグを更新するタグ ヘルパーを記述します。In this section, you write a tag helper that updates an email tag. 例:For example:

<email>Support</email>

サーバーは、電子メール タグ ヘルパーを使用して、そのマークアップを以下に変換します。The server will use our email tag helper to convert that markup into the following:

<a href="mailto:Support@contoso.com">Support@contoso.com</a>

つまり、これを電子メール リンクにするアンカー タグです。That is, an anchor tag that makes this an email link. ブログ エンジンを記述していて、マーケティング、サポート、およびその他の連絡先の電子メールをすべて同じドメインに送信するためにそれが必要な場合に、これを行うことができます。You might want to do this if you are writing a blog engine and need it to send email for marketing, support, and other contacts, all to the same domain.

  1. 次の EmailTagHelper クラスを TagHelpers フォルダーに追加します。Add the following EmailTagHelper class to the TagHelpers folder.

    
    using Microsoft.AspNetCore.Razor.TagHelpers;
    using System.Threading.Tasks;
    
    namespace AuthoringTagHelpers.TagHelpers
    {
        public class EmailTagHelper : TagHelper
        {
            public override void Process(TagHelperContext context, TagHelperOutput output)
            {
                output.TagName = "a";    // Replaces <email> with <a> tag
            }
        }
    }
    

    注:Notes:

    • タグ ヘルパーは、ルート クラス名の要素 (クラス名部分から TagHelper 部分を引いたもの) をターゲットとする名前付け規則です。Tag helpers use a naming convention that targets elements of the root class name (minus the TagHelper portion of the class name). この例では、EmailTagHelper のルート名は email となるため、<email> タグがターゲットとなります。In this example, the root name of EmailTagHelper is email, so the <email> tag will be targeted. この命名規則は、ほとんどのタグ ヘルパーで機能します。オーバーライドの方法については、後述します。This naming convention should work for most tag helpers, later on I'll show how to override it.

    • EmailTagHelper クラスは TagHelper から派生したものです。The EmailTagHelper class derives from TagHelper. TagHelper クラスはタグ ヘルパーを記述するためのメソッドとプロパティを提供します。The TagHelper class provides methods and properties for writing Tag Helpers.

    • オーバーライドされた Process メソッドは、実行時のタグ ヘルパーの動作を制御します。The overridden Process method controls what the tag helper does when executed. TagHelper クラスには、同じパラメーターを使用する非同期バージョン (ProcessAsync) も用意されています。The TagHelper class also provides an asynchronous version (ProcessAsync) with the same parameters.

    • Process (および ProcessAsync) のコンテキスト パラメーターには、現在の HTML タグの実行に関連付けられている情報が含まれています。The context parameter to Process (and ProcessAsync) contains information associated with the execution of the current HTML tag.

    • Process (および ProcessAsync) の出力パラメーターには、HTML タグとコンテンツの生成に使用された元のソースを代表するステートフル HTML 要素が含まれています。The output parameter to Process (and ProcessAsync) contains a stateful HTML element representative of the original source used to generate an HTML tag and content.

    • クラス名には TagHelper のサフィックスが付けられています。これは必須ではありませんが、ベスト プラクティスです。Our class name has a suffix of TagHelper, which is not required, but it's considered a best practice convention. クラスは、次のように宣言できます。You could declare the class as:

    public class Email : TagHelper
    
  2. すべての Razor ビューで EmailTagHelper クラスを使用可能にするには、addTagHelper ディレクティブを Views/_ViewImports.cshtml ファイルに追加します。[!code-html]To make the EmailTagHelper class available to all our Razor views, add the addTagHelper directive to the Views/_ViewImports.cshtml file: [!code-html]

    上記のコードでは、ワイルドカードの構文を使用して、アセンブリ内のすべてのタグ ヘルパーが使用可能になるように指定しています。The code above uses the wildcard syntax to specify all the tag helpers in our assembly will be available. @addTagHelper の後の最初の文字列は、読み込むタグ ヘルパーを指定します (すべてのタグ ヘルパーを指定するには、"*" を使用します)。2 番目の文字列 "AuthoringTagHelpers" は、タグ ヘルパーが存在するアセンブリを指定します。The first string after @addTagHelper specifies the tag helper to load (Use "*" for all tag helpers), and the second string "AuthoringTagHelpers" specifies the assembly the tag helper is in. また、2 行目で、ワイルドカードの構文を使用して ASP.NET Core MVC タグ ヘルパーを取り込むことに注目してください (これらのヘルパーについては、タグ ヘルパーの概要に関するページで説明されています)。Razor ビューでタグ ヘルパーを使用可能にするのが、@addTagHelper ディレクティブです。Also, note that the second line brings in the ASP.NET Core MVC tag helpers using the wildcard syntax (those helpers are discussed in Introduction to Tag Helpers.) It's the @addTagHelper directive that makes the tag helper available to the Razor view. または、次に示すように、タグ ヘルパーの完全修飾名 (FQN) を指定することもできます。Alternatively, you can provide the fully qualified name (FQN) of a tag helper as shown below:

@using AuthoringTagHelpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper AuthoringTagHelpers.TagHelpers.EmailTagHelper, AuthoringTagHelpers

FQN を使用してタグ ヘルパーをビューに追加するには、最初に FQN (AuthoringTagHelpers.TagHelpers.EmailTagHelper) を追加してから、アセンブリ名 (AuthoringTagHelpers) を追加します。To add a tag helper to a view using a FQN, you first add the FQN (AuthoringTagHelpers.TagHelpers.EmailTagHelper), and then the assembly name (AuthoringTagHelpers). ほとんどの開発者は、ワイルドカードの構文を使用する方を選びます。Most developers will prefer to use the wildcard syntax. タグ ヘルパーの概要に関するページでは、タグ ヘルパーの追加、削除、階層、およびワイルドカードの構文について詳しく説明されています。Introduction to Tag Helpers goes into detail on tag helper adding, removing, hierarchy, and wildcard syntax.

  1. これらの変更を加えて、Views/Home/Contact.cshtml ファイル内のマークアップを更新します。Update the markup in the Views/Home/Contact.cshtml file with these changes:

    @{
        ViewData["Title"] = "Contact";
    }
    <h2>@ViewData["Title"].</h2>
    <h3>@ViewData["Message"]</h3>
    
    <address>
        One Microsoft Way<br />
        Redmond, WA 98052<br />
        <abbr title="Phone">P:</abbr>
        425.555.0100
    </address>
    
    <address>
        <strong>Support:</strong><email>Support</email><br />
        <strong>Marketing:</strong><email>Marketing</email>
    </address>
    
  2. アプリを実行して、お好みのブラウザーを使用して HTML ソースを表示すると、電子メール タグがアンカー マークアップ (<a>Support</a> など) に置き換えられていることが確認できます。Run the app and use your favorite browser to view the HTML source so you can verify that the email tags are replaced with anchor markup (For example, <a>Support</a>). SupportMarketing はリンクとして表示されますが、リンクを機能させる href 属性を持っていません。Support and Marketing are rendered as a links, but they don't have an href attribute to make them functional. 次のセクションでこれを修正します。We'll fix that in the next section.

SetAttribute と SetContentSetAttribute and SetContent

このセクションでは、EmailTagHelper を更新して、電子メール用の有効なアンカー タグが作成できるようにします。In this section, we'll update the EmailTagHelper so that it will create a valid anchor tag for email. これを更新して、Razor ビューから (mail-to 属性の形式で) 情報を取得し、それを使用してアンカーを生成します。We'll update it to take information from a Razor view (in the form of a mail-to attribute) and use that in generating the anchor.

次のように EmailTagHelper クラスを更新します。Update the EmailTagHelper class with the following:

public class EmailTagHelper : TagHelper
{
    private const string EmailDomain = "contoso.com";

    // Can be passed via <email mail-to="..." />. 
    // Pascal case gets translated into lower-kebab-case.
    public string MailTo { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "a";    // Replaces <email> with <a> tag

        var address = MailTo + "@" + EmailDomain;
        output.Attributes.SetAttribute("href", "mailto:" + address);
        output.Content.SetContent(address);
    }
}

注:Notes:

  • タグ ヘルパーのパスカル ケースのクラス名とプロパティ名は、それぞれ小文字のケバブ ケースに変換されます。Pascal-cased class and property names for tag helpers are translated into their lower kebab case. そのため、MailTo 属性を使用するには、相当する <email mail-to="value"/> を使用します。Therefore, to use the MailTo attribute, you'll use <email mail-to="value"/> equivalent.

  • 最後の行は、最低限機能するタグ ヘルパーの完成したコンテンツを設定します。The last line sets the completed content for our minimally functional tag helper.

  • 強調表示されている行は、属性を追加するための構文を示しています。The highlighted line shows the syntax for adding attributes:

public override void Process(TagHelperContext context, TagHelperOutput output)
{
    output.TagName = "a";    // Replaces <email> with <a> tag

    var address = MailTo + "@" + EmailDomain;
    output.Attributes.SetAttribute("href", "mailto:" + address);
    output.Content.SetContent(address);
}

この方法は、属性 "href" が属性コレクションに現存していない場合に限り、属性 "href" に対して有効です。That approach works for the attribute "href" as long as it doesn't currently exist in the attributes collection. output.Attributes.Add メソッドを使用してタグ ヘルパー属性をタグ属性のコレクションの末尾に追加することもできます。You can also use the output.Attributes.Add method to add a tag helper attribute to the end of the collection of tag attributes.

  1. これらの変更を加えて Views/Home/Contact.cshtml ファイル内のマークアップを更新します。[!code-html]Update the markup in the Views/Home/Contact.cshtml file with these changes: [!code-html]

  2. アプリを実行し、適切なリンクが生成されることを確認します。Run the app and verify that it generates the correct links.

    注意

    自己終了の電子メール タグ (<email mail-to="Rick" />) を記述すると、最終的な出力も自己終了になります。If you were to write the email tag self-closing (<email mail-to="Rick" />), the final output would also be self-closing. 開始タグのみを持つタグ (<email mail-to="Rick">) を記述する機能を有効にするには、次のようにクラスを装飾する必要があります。To enable the ability to write the tag with only a start tag (<email mail-to="Rick">) you must decorate the class with the following:

    [HtmlTargetElement("email", TagStructure = TagStructure.WithoutEndTag)] 
    public class EmailVoidTagHelper : TagHelper
    {
        private const string EmailDomain = "contoso.com";
        // Code removed for brevity
    

    自己終了の電子メール タグ ヘルパーでは、出力は <a href="mailto:Rick@contoso.com" /> になります。With a self-closing email tag helper, the output would be <a href="mailto:Rick@contoso.com" />. 自己終了のアンカー タグは有効な HTML ではないため、作成することはないかもしれませんが、自己終了のタグ ヘルパーは必要な場合があります。Self-closing anchor tags are not valid HTML, so you wouldn't want to create one, but you might want to create a tag helper that's self-closing. タグ ヘルパーは、タグを読み取った後に、TagMode プロパティの型を設定します。Tag helpers set the type of the TagMode property after reading a tag.

ProcessAsyncProcessAsync

このセクションでは非同期の電子メール ヘルパーを記述します。In this section, we'll write an asynchronous email helper.

  1. EmailTagHelper クラスを次のコードで置き換えます。Replace the EmailTagHelper class with the following code:

    public class EmailTagHelper : TagHelper
    {
        private const string EmailDomain = "contoso.com";
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            output.TagName = "a";                                 // Replaces <email> with <a> tag
            var content = await output.GetChildContentAsync();
            var target = content.GetContent() + "@" + EmailDomain;
            output.Attributes.SetAttribute("href", "mailto:" + target);
            output.Content.SetContent(target);
        }
    }
    

    注:Notes:

    • このバージョンでは、非同期の ProcessAsync メソッドを使用します。This version uses the asynchronous ProcessAsync method. 非同期の GetChildContentAsyncTagHelperContent を含む Task を返します。The asynchronous GetChildContentAsync returns a Task containing the TagHelperContent.

    • output パラメーターを使用して、HTML 要素のコンテンツを取得します。Use the output parameter to get contents of the HTML element.

  2. Views/Home/Contact.cshtml ファイルに次の変更を行って、タグ ヘルパーがターゲットの電子メールを取得できるようにします。Make the following change to the Views/Home/Contact.cshtml file so the tag helper can get the target email.

    @{
        ViewData["Title"] = "Contact";
    }
    <h2>@ViewData["Title"].</h2>
    <h3>@ViewData["Message"]</h3>
    
    <address>
        One Microsoft Way<br />
        Redmond, WA 98052<br />
        <abbr title="Phone">P:</abbr>
        425.555.0100
    </address>
    
    <address>
        <strong>Support:</strong><email>Support</email><br />
        <strong>Marketing:</strong><email>Marketing</email>
    </address>
    
  3. アプリを実行し、有効な電子メール リンクが生成されることを確認します。Run the app and verify that it generates valid email links.

RemoveAll、PreContent.SetHtmlContent、PostContent.SetHtmlContentRemoveAll, PreContent.SetHtmlContent and PostContent.SetHtmlContent

  1. 次の BoldTagHelper クラスを TagHelpers フォルダーに追加します。Add the following BoldTagHelper class to the TagHelpers folder.

    using Microsoft.AspNetCore.Razor.TagHelpers;
    
    namespace AuthoringTagHelpers.TagHelpers
    {
        [HtmlTargetElement(Attributes = "bold")]
        public class BoldTagHelper : TagHelper
        {
            public override void Process(TagHelperContext context, TagHelperOutput output)
            {
                output.Attributes.RemoveAll("bold");
                output.PreContent.SetHtmlContent("<strong>");
                output.PostContent.SetHtmlContent("</strong>");
            }
        }
    }
    

    注:Notes:

    • [HtmlTargetElement] 属性は、"bold" という名前の HTML 属性を含むすべての HTML 要素を照合することを指定する属性パラメーターを渡し、クラス内で Process オーバーライド メソッドが実行されます。The [HtmlTargetElement] attribute passes an attribute parameter that specifies that any HTML element that contains an HTML attribute named "bold" will match, and the Process override method in the class will run. このサンプルでは、Process メソッドによって "bold" 属性が削除され、中にあるマークアップが <strong></strong> で囲まれます。In our sample, the Process method removes the "bold" attribute and surrounds the containing markup with <strong></strong>.

    • 既存のタグ コンテンツは置き換えたくないので、PreContent.SetHtmlContent メソッドを使用して開始タグ <strong> を記述し、PostContent.SetHtmlContent メソッドを使用して終了タグ </strong> を記述する必要があります。Because you don't want to replace the existing tag content, you must write the opening <strong> tag with the PreContent.SetHtmlContent method and the closing </strong> tag with the PostContent.SetHtmlContent method.

  2. bold 属性値を含めるように About.cshtml ビューを変更します。Modify the About.cshtml view to contain a bold attribute value. 完成したコードを以下に示します。The completed code is shown below.

    @{
        ViewData["Title"] = "About";
    }
    <h2>@ViewData["Title"].</h2>
    <h3>@ViewData["Message"]</h3>
    
    <p bold>Use this area to provide additional information.</p>
    
    <bold> Is this bold?</bold>
    
  3. アプリを実行します。Run the app. お好みのブラウザーを使用して、ソースを検査し、マークアップを確認できます。You can use your favorite browser to inspect the source and verify the markup.

    上記の [HtmlTargetElement] 属性は、"bold" という属性名を提供する HTML マークアップのみをターゲットにしています。The [HtmlTargetElement] attribute above only targets HTML markup that provides an attribute name of "bold". <bold> 要素は、タグ ヘルパーによって変更されませんでした。The <bold> element wasn't modified by the tag helper.

  4. [HtmlTargetElement] 属性の行をコメント アウトすると、既定の <bold> タグ (<bold> 形式の HTML マークアップ) が再度ターゲットになります。Comment out the [HtmlTargetElement] attribute line and it will default to targeting <bold> tags, that is, HTML markup of the form <bold>. 既定の名前付け規則は、クラス名 BoldTagHelper を <bold> タグと一致させることに注意してください。Remember, the default naming convention will match the class name BoldTagHelper to <bold> tags.

  5. アプリを実行して、<bold> タグがタグ ヘルパーによって処理されることを確認します。Run the app and verify that the <bold> tag is processed by the tag helper.

複数の [HtmlTargetElement] 属性でクラスを修飾すると、結果はターゲットの論理 OR になります。Decorating a class with multiple [HtmlTargetElement] attributes results in a logical-OR of the targets. たとえば、次のコードを使用すると、bold タグまたは bold 属性が一致します。For example, using the code below, a bold tag or a bold attribute will match.

[HtmlTargetElement("bold")]
[HtmlTargetElement(Attributes = "bold")]
public class BoldTagHelper : TagHelper
{
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.Attributes.RemoveAll("bold");
        output.PreContent.SetHtmlContent("<strong>");
        output.PostContent.SetHtmlContent("</strong>");
    }
}

同じステートメントに複数の属性を追加すると、ランタイムではそれらが論理 AND として扱われます。When multiple attributes are added to the same statement, the runtime treats them as a logical-AND. たとえば、次のコードでは、一致させるために、"bold" という名前の属性 (<bold bold />) を使って HTML 要素に "bold" と名前を付ける必要があります。For example, in the code below, an HTML element must be named "bold" with an attribute named "bold" (<bold bold />) to match.

[HtmlTargetElement("bold", Attributes = "bold")]

また、[HtmlTargetElement] を使用してターゲット要素の名前を変更することもできます。You can also use the [HtmlTargetElement] to change the name of the targeted element. たとえば、BoldTagHelper<MyBold> タグをターゲットにするには、次の属性を使用します。For example if you wanted the BoldTagHelper to target <MyBold> tags, you would use the following attribute:

[HtmlTargetElement("MyBold")]

タグ ヘルパーにモデルを渡すPass a model to a Tag Helper

  1. Models フォルダーを追加します。Add a Models folder.

  2. 次の WebsiteContext クラスを Models フォルダーに追加します。Add the following WebsiteContext class to the Models folder:

    using System;
    
    namespace AuthoringTagHelpers.Models
    {
        public class WebsiteContext
        {
            public Version Version { get; set; }
            public int CopyrightYear { get; set; }
            public bool Approved { get; set; }
            public int TagsToShow { get; set; }
        }
    }
    
  3. 次の WebsiteInformationTagHelper クラスを TagHelpers フォルダーに追加します。Add the following WebsiteInformationTagHelper class to the TagHelpers folder.

    using System;
    using AuthoringTagHelpers.Models;
    using Microsoft.AspNetCore.Razor.TagHelpers;
    
    namespace AuthoringTagHelpers.TagHelpers
    {
        public class WebsiteInformationTagHelper : TagHelper
        {
            public WebsiteContext Info { get; set; }
    
          public override void Process(TagHelperContext context, TagHelperOutput output)
          {
             output.TagName = "section";
             output.Content.SetHtmlContent(
    $@"<ul><li><strong>Version:</strong> {Info.Version}</li>
    <li><strong>Copyright Year:</strong> {Info.CopyrightYear}</li>
    <li><strong>Approved:</strong> {Info.Approved}</li>
    <li><strong>Number of tags to show:</strong> {Info.TagsToShow}</li></ul>");
             output.TagMode = TagMode.StartTagAndEndTag;
          }
       }
    }
    

    注:Notes:

    • 前述したように、タグ ヘルパーは、パスカルケースの C# クラス名とタグ ヘルパーのプロパティを小文字のケバブ ケースに変換します。As mentioned previously, tag helpers translates Pascal-cased C# class names and properties for tag helpers into lower kebab case. そのため、WebsiteInformationTagHelper を Razor で使用するには、<website-information /> を記述します。Therefore, to use the WebsiteInformationTagHelper in Razor, you'll write <website-information />.

    • [HtmlTargetElement] 属性を使用してターゲット要素を明示的に識別しないため、website-information の既定がターゲットになります。You are not explicitly identifying the target element with the [HtmlTargetElement] attribute, so the default of website-information will be targeted. 次の属性を適用した場合 (ケバブ ケースではありませんが、クラス名が一致します):If you applied the following attribute (note it's not kebab case but matches the class name):

    [HtmlTargetElement("WebsiteInformation")]
    

    小文字のケバブ ケース タグ <website-information /> は一致しません。The lower kebab case tag <website-information /> wouldn't match. [HtmlTargetElement] 属性を使用する場合は、次に示すようにケバブ ケースを使用します。If you want use the [HtmlTargetElement] attribute, you would use kebab case as shown below:

    [HtmlTargetElement("Website-Information")]
    
    • 自己終了の要素にはコンテンツがありません。Elements that are self-closing have no content. この例では、Razor マークアップは自己終了タグを使用しますが、タグ ヘルパーは section 要素を作成します (これは自己終了ではなく、section 要素内のコンテンツを記述しています)。For this example, the Razor markup will use a self-closing tag, but the tag helper will be creating a section element (which isn't self-closing and you are writing content inside the section element). そのため、TagModeStartTagAndEndTag に設定して出力を記述する必要があります。Therefore, you need to set TagMode to StartTagAndEndTag to write output. または、TagMode を設定する行をコメント アウトして、終了タグを使ってマークアップを記述することもできます。Alternatively, you can comment out the line setting TagMode and write markup with a closing tag. (サンプルのマークアップは、後ほどこのチュートリアルで提供します。)(Example markup is provided later in this tutorial.)

    • 次の行の $ (ドル記号) は、挿入文字列を使用しています。The $ (dollar sign) in the following line uses an interpolated string:

    $@"<ul><li><strong>Version:</strong> {Info.Version}</li>
    
  4. About.cshtml ビューに次のマークアップを追加します。Add the following markup to the About.cshtml view. 強調表示されたマークアップは、Web サイトの情報を表示します。The highlighted markup displays the web site information.

    @using AuthoringTagHelpers.Models
    @{
        ViewData["Title"] = "About";
    }
    <h2>@ViewData["Title"].</h2>
    <h3>@ViewData["Message"]</h3>
    
    <p bold>Use this area to provide additional information.</p>
    
    <bold> Is this bold?</bold>
    
    <h3> web site info </h3>
    <website-information info="new WebsiteContext {
                                        Version = new Version(1, 3),
                                        CopyrightYear = 1638,
                                        Approved = true,
                                        TagsToShow = 131 }" />
    

    注意

    Razor マークアップを次に示します。In the Razor markup shown below:

    <website-information info="new WebsiteContext {
                                        Version = new Version(1, 3),
                                        CopyrightYear = 1638,
                                        Approved = true,
                                        TagsToShow = 131 }" />
    

    Razor は info 属性を文字列ではなくクラスとして認識し、ユーザーは C# コードを記述します。Razor knows the info attribute is a class, not a string, and you want to write C# code. 文字列以外のタグ ヘルパー属性はすべて、@ 文字を使わずに記述する必要があります。Any non-string tag helper attribute should be written without the @ character.

  5. アプリを実行し、[バージョン情報] ビューに移動して、Web サイトの情報を確認します。Run the app, and navigate to the About view to see the web site information.

    注意

    終了タグを持つ次のマークアップを使用して、タグ ヘルパー内の TagMode.StartTagAndEndTag を持つ行を削除できます。You can use the following markup with a closing tag and remove the line with TagMode.StartTagAndEndTag in the tag helper:

    <website-information info="new WebsiteContext {
                                        Version = new Version(1, 3),
                                        CopyrightYear = 1638,
                                        Approved = true,
                                        TagsToShow = 131 }" >
    </website-information>
    

条件タグ ヘルパーCondition Tag Helper

条件タグ ヘルパーは、true 値が渡されたときに出力をレンダリングします。The condition tag helper renders output when passed a true value.

  1. 次の ConditionTagHelper クラスを TagHelpers フォルダーに追加します。Add the following ConditionTagHelper class to the TagHelpers folder.

    using Microsoft.AspNetCore.Razor.TagHelpers;
    
    namespace AuthoringTagHelpers.TagHelpers
    {
        [HtmlTargetElement(Attributes = nameof(Condition))]
        public class ConditionTagHelper : TagHelper
        {
            public bool Condition { get; set; }
    
            public override void Process(TagHelperContext context, TagHelperOutput output)
            {
                if (!Condition)
                {
                    output.SuppressOutput();
                }
            }
        }
    }
    
  2. Views/Home/Index.cshtml ファイルの内容を次のマークアップに置き換えます。Replace the contents of the Views/Home/Index.cshtml file with the following markup:

    @using AuthoringTagHelpers.Models
    @model WebsiteContext
    
    @{
        ViewData["Title"] = "Home Page";
    }
    
    <div>
        <h3>Information about our website (outdated):</h3>
        <Website-InforMation info="Model" />
        <div condition="Model.Approved">
            <p>
                This website has <strong surround="em">@Model.Approved</strong> been approved yet.
                Visit www.contoso.com for more information.
            </p>
        </div>
    </div>
    
  3. Home コントローラーの Index メソッドを次のコードで置き換えます。Replace the Index method in the Home controller with the following code:

    public IActionResult Index(bool approved = false)
    {
        return View(new WebsiteContext
        {
            Approved = approved,
            CopyrightYear = 2015,
            Version = new Version(1, 3, 3, 7),
            TagsToShow = 20
        });
    }
    
  4. アプリを実行して、ホーム ページに移動します。Run the app and browse to the home page. 条件付き div ではマークアップはレンダリングされません。The markup in the conditional div won't be rendered. クエリ文字列 ?approved=true を URL に付加します (例: http://localhost:1235/Home/Index?approved=true)。Append the query string ?approved=true to the URL (for example, http://localhost:1235/Home/Index?approved=true). approved は true に設定され、条件付きマークアップが表示されます。approved is set to true and the conditional markup will be displayed.

注意

nameof 演算子を使用して、太字タグ ヘルパーで行ったように文字列を指定するのではなく、ターゲットにする属性を指定します。Use the nameof operator to specify the attribute to target rather than specifying a string as you did with the bold tag helper:

[HtmlTargetElement(Attributes = nameof(Condition))]
 //   [HtmlTargetElement(Attributes = "condition")]
 public class ConditionTagHelper : TagHelper
{
   public bool Condition { get; set; }

   public override void Process(TagHelperContext context, TagHelperOutput output)
   {
      if (!Condition)
      {
         output.SuppressOutput();
      }
   }
}

nameof 演算子は、コードがリファクタリングされないように保護します (名前は RedCondition に変更できます)。The nameof operator will protect the code should it ever be refactored (we might want to change the name to RedCondition).

タグ ヘルパーの競合を回避するAvoid Tag Helper conflicts

このセクションでは、自動リンク タグ ヘルパーのペアを記述します。In this section, you write a pair of auto-linking tag helpers. 1 つ目のヘルパーは HTTP で始まる URL を含むマークアップを、同じ URL を含む HTML アンカー タグに置き換えます (この URL へのリンクも生成されます)。The first will replace markup containing a URL starting with HTTP to an HTML anchor tag containing the same URL (and thus yielding a link to the URL). 2 つ目のヘルパーは WWW で始まる URL に対して同じことを行います。The second will do the same for a URL starting with WWW.

これら 2 つのヘルパーは密接に関連しており、将来的にそれらをリファクターする可能性があるため、これらを同じファイルで保持します。Because these two helpers are closely related and you may refactor them in the future, we'll keep them in the same file.

  1. 次の AutoLinkerHttpTagHelper クラスを TagHelpers フォルダーに追加します。Add the following AutoLinkerHttpTagHelper class to the TagHelpers folder.

    [HtmlTargetElement("p")]
    public class AutoLinkerHttpTagHelper : TagHelper
    {
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var childContent = await output.GetChildContentAsync();
            // Find Urls in the content and replace them with their anchor tag equivalent.
            output.Content.SetHtmlContent(Regex.Replace(
                 childContent.GetContent(),
                 @"\b(?:https?://)(\S+)\b",
                  "<a target=\"_blank\" href=\"$0\">$0</a>"));  // http link version}
        }
    }
    

    注意

    AutoLinkerHttpTagHelper クラスは p 要素をターゲットとし、Regex を使用してアンカーを作成します。The AutoLinkerHttpTagHelper class targets p elements and uses Regex to create the anchor.

  2. 次のマークアップを Views/Home/Contact.cshtml ファイルの末尾に追加します。Add the following markup to the end of the Views/Home/Contact.cshtml file:

    @{
        ViewData["Title"] = "Contact";
    }
    <h2>@ViewData["Title"].</h2>
    <h3>@ViewData["Message"]</h3>
    
    <address>
        One Microsoft Way<br />
        Redmond, WA 98052<br />
        <abbr title="Phone">P:</abbr>
        425.555.0100
    </address>
    
    <address>
        <strong>Support:</strong><email>Support</email><br />
        <strong>Marketing:</strong><email>Marketing</email>
    </address>
    
    <p>Visit us at http://docs.asp.net or at www.microsoft.com</p>
    
  3. アプリを実行し、タグ ヘルパーがアンカーを正しくレンダリングすることを確認します。Run the app and verify that the tag helper renders the anchor correctly.

  4. AutoLinker クラスを更新して AutoLinkerWwwTagHelper を含めます。これは www テキストを元の www テキストも含むアンカー タグに変換します。Update the AutoLinker class to include the AutoLinkerWwwTagHelper which will convert www text to an anchor tag that also contains the original www text. 以下では、更新されたコードが強調表示されています。The updated code is highlighted below:

        [HtmlTargetElement("p")]
        public class AutoLinkerHttpTagHelper : TagHelper
        {
            public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
            {
                var childContent = await output.GetChildContentAsync();
                // Find Urls in the content and replace them with their anchor tag equivalent.
                output.Content.SetHtmlContent(Regex.Replace(
                     childContent.GetContent(),
                     @"\b(?:https?://)(\S+)\b",
                      "<a target=\"_blank\" href=\"$0\">$0</a>"));  // http link version}
            }
        }
    
        [HtmlTargetElement("p")]
        public class AutoLinkerWwwTagHelper : TagHelper
        {
            public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
            {
                var childContent = await output.GetChildContentAsync();
                // Find Urls in the content and replace them with their anchor tag equivalent.
                output.Content.SetHtmlContent(Regex.Replace(
                    childContent.GetContent(),
                     @"\b(www\.)(\S+)\b",
                     "<a target=\"_blank\" href=\"http://$0\">$0</a>"));  // www version
            }
        }
    }
    
  5. アプリを実行します。Run the app. www テキストはリンクとしてレンダリングされていますが、HTTP テキストはそのようになっていないことに注目してください。Notice the www text is rendered as a link but the HTTP text isn't. 両方のクラスにブレークポイントを配置すると、HTTP タグ ヘルパー クラスが最初に実行されることがわかります。If you put a break point in both classes, you can see that the HTTP tag helper class runs first. 問題は、タグ ヘルパーの出力がキャッシュされ、WWW タグ ヘルパーを実行するときに、WWW タグ ヘルパーが HTTP タグ ヘルパーからのキャッシュされた出力を上書きすることです。The problem is that the tag helper output is cached, and when the WWW tag helper is run, it overwrites the cached output from the HTTP tag helper. タグ ヘルパーの実行順序を制御する方法については、このチュートリアルで後ほど説明します。Later in the tutorial we'll see how to control the order that tag helpers run in. コードを次のように修正します。We'll fix the code with the following:

      public class AutoLinkerHttpTagHelper : TagHelper
      {
          public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
          {
              var childContent = output.Content.IsModified ? output.Content.GetContent() :
                  (await output.GetChildContentAsync()).GetContent();
    
              // Find Urls in the content and replace them with their anchor tag equivalent.
              output.Content.SetHtmlContent(Regex.Replace(
                   childContent,
                   @"\b(?:https?://)(\S+)\b",
                    "<a target=\"_blank\" href=\"$0\">$0</a>"));  // http link version}
          }
      }
    
      [HtmlTargetElement("p")]
      public class AutoLinkerWwwTagHelper : TagHelper
      {
          public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
          {
              var childContent = output.Content.IsModified ? output.Content.GetContent() : 
                  (await output.GetChildContentAsync()).GetContent();
    
              // Find Urls in the content and replace them with their anchor tag equivalent.
              output.Content.SetHtmlContent(Regex.Replace(
                   childContent,
                   @"\b(www\.)(\S+)\b",
                   "<a target=\"_blank\" href=\"http://$0\">$0</a>"));  // www version
          }
      }
    

    注意

    自動リンク タグ ヘルパーの最初のエディションで、次のコードを使用してターゲットのコンテンツを取得しました。In the first edition of the auto-linking tag helpers, you got the content of the target with the following code:

    var childContent = await output.GetChildContentAsync();
    

    つまり、ProcessAsync メソッドに渡された TagHelperOutput を使用して GetChildContentAsync を呼び出します。That is, you call GetChildContentAsync using the TagHelperOutput passed into the ProcessAsync method. 前述したように、出力はキャッシュされるため、最後に実行されたタグ ヘルパーによって上書きされます。As mentioned previously, because the output is cached, the last tag helper to run wins. 次のコードを使用してこの問題を修正しました。You fixed that problem with the following code:

    var childContent = output.Content.IsModified ? output.Content.GetContent() : 
        (await output.GetChildContentAsync()).GetContent();
    

    上記のコードは、コンテンツが変更されているかどうかをチェックし、変更されている場合は、出力バッファーからコンテンツを取得します。The code above checks to see if the content has been modified, and if it has, it gets the content from the output buffer.

  6. アプリを実行して、2 つのリンクが期待どおりに動作することを確認します。Run the app and verify that the two links work as expected. 自動リンカー タグ ヘルパーが正しく完全に機能しているように見えても、微妙な問題があります。While it might appear our auto linker tag helper is correct and complete, it has a subtle problem. WWW タグ ヘルパーを最初に実行すると、www リンクが不正確になります。If the WWW tag helper runs first, the www links won't be correct. Order オーバーロードを追加してコードを更新し、タグの実行順序を制御します。Update the code by adding the Order overload to control the order that the tag runs in. Order プロパティを、同じ要素をターゲットとする他のタグ ヘルパーと比べることで実行順序が決まります。The Order property determines the execution order relative to other tag helpers targeting the same element. 既定の順序の値は 0 で、より低い値を持つインスタンスの方が先に実行されます。The default order value is zero and instances with lower values are executed first.

    public class AutoLinkerHttpTagHelper : TagHelper
    {
        // This filter must run before the AutoLinkerWwwTagHelper as it searches and replaces http and 
        // the AutoLinkerWwwTagHelper adds http to the markup.
        public override int Order
        {
            get  {  return int.MinValue;   }
        }
    

    上記のコードにより、WWW タグ ヘルパーの前に、HTTP タグ ヘルパーが実行されることが保証されます。The above code will guarantee that the HTTP tag helper runs before the WWW tag helper. OrderMaxValue に変更し、WWW タグの生成されたマークアップが正しいことを確認します。Change Order to MaxValue and verify that the markup generated for the WWW tag is incorrect.

子コンテンツを検査して取得するInspect and retrieve child content

タグ ヘルパーには、コンテンツを取得するための複数のプロパティが用意されています。The tag helpers provide several properties to retrieve content.

  • GetChildContentAsync の結果を output.Content に付加できます。The result of GetChildContentAsync can be appended to output.Content.
  • GetContent を使用して GetChildContentAsync の結果を検査できます。You can inspect the result of GetChildContentAsync with GetContent.
  • output.Content を変更すると、この自動リンカー サンプルのように、GetChildContentAsync を呼び出すまで、TagHelper ボディは実行またはレンダリングされません。If you modify output.Content, the TagHelper body won't be executed or rendered unless you call GetChildContentAsync as in our auto-linker sample:
public class AutoLinkerHttpTagHelper : TagHelper
{
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        var childContent = output.Content.IsModified ? output.Content.GetContent() :
            (await output.GetChildContentAsync()).GetContent();

        // Find Urls in the content and replace them with their anchor tag equivalent.
        output.Content.SetHtmlContent(Regex.Replace(
             childContent,
             @"\b(?:https?://)(\S+)\b",
              "<a target=\"_blank\" href=\"$0\">$0</a>"));  // http link version}
    }
}
  • GetChildContentAsync を複数回呼び出すと、同じ値が返され、キャッシュされた結果を使用しないことを示す false パラメーターを渡さない限り、TagHelper ボディは再実行されません。Multiple calls to GetChildContentAsync returns the same value and doesn't re-execute the TagHelper body unless you pass in a false parameter indicating not to use the cached result.