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. EmailTagHelper 클래스를 모든 Razor 뷰에서 사용할 수 있도록 하려면 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 뒤의 첫 번째 문자열은 로드할 태그 도우미(모든 태그 도우미에 "*" 사용)를 지정하고 두 번째 문자열 "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. 또한 두 번째 줄은 와일드 카드 구문을 사용하여 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>). 지원마케팅은 링크로 렌더링되지만 작동하도록 하는 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:

  • 태그 도우미에 대한 파스칼식 클래스 및 속성 이름이 kebab 소문자로 번역됩니다.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" 특성에 대해 작동합니다.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. 모델 폴더를 추가합니다.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# 클래스 이름과 태그 도우미 속성을 kebab 소문자로 변환합니다.As mentioned previously, tag helpers translates Pascal-cased C# class names and properties for tag helpers into lower kebab case. 따라서 Razor에서 WebsiteInformationTagHelper를 사용하려면 <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. 다음 특성을 적용한 경우(kebab 대/소문자는 아니지만 클래스 이름 일치):If you applied the following attribute (note it's not kebab case but matches the class name):

    [HtmlTargetElement("WebsiteInformation")]
    

    kebab 소문자 태그 <website-information />은 일치하지 않습니다.The lower kebab case tag <website-information /> wouldn't match. [HtmlTargetElement] 특성을 사용하려는 경우 아래와 같이 kebab 대/소문자를 사용합니다.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. 강조 표시된 태그는 웹 사이트 정보를 표시합니다.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. 앱을 실행하고 About 뷰로 이동하여 웹 사이트 정보를 확인합니다.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 연산자를 사용하여 bold 태그 도우미에서와 마찬가지로 문자열을 지정하지 않고 대상에 특성을 지정합니다.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. 첫 번째는 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). 두 번째는 WWW로 시작하는 URL에 대해 동일한 작업을 수행합니다.The second will do the same for a URL starting with WWW.

이러한 두 도우미는 밀접하게 관련되어 있으며 향후 리팩터링할 수 있으므로 동일한 파일에 유지합니다.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. www 텍스트를 원본 www 텍스트를 포함하는 앵커 태그로 변환할 AutoLinkerWwwTagHelper를 포함하도록 AutoLinker 클래스를 업데이트합니다.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 태그 도우미가 실행될 때, 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. 앱을 실행하고 두 링크가 예상대로 작동하는지 확인합니다.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;   }
        }
    

    위의 코드는 HTTP 태그 도우미가 WWW 태그 도우미보다 먼저 실행되도록 보장합니다.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.
  • GetContentGetChildContentAsync의 결과를 검사할 수 있습니다.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.