Models文件夹
public class City
{
public string Name { get; set; }
public string Country { get; set; }
public int? Population { get; set; }
}
public interface IRepository
{
IEnumerable<City> Cities { get; }
void AddCity(City newCity);
}
using System.Collections.Generic;
namespace MyTagHelper.Models
{
public class MemoryRepository : IRepository
{
private readonly List<City> _cities = new List<City>
{
new City {Name = "伦敦", Country = "英国", Population = 8539000},
new City {Name = "纽约", Country = "美国", Population = 8406000},
new City {Name = "圣荷西", Country ="美国", Population = 998537},
new City {Name = "巴黎", Country = "法国", Population = 2244000}
};
public IEnumerable<City> Cities => _cities;
public void AddCity(City newCity)
{
_cities.Add(newCity);
}
}
}
TagHelpers
文件夹
ButtonTagHelper.cs
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace MyTagHelper.TagHelpers
{
[HtmlTargetElement("button", Attributes = "bs-button-color", ParentTag = "form")]
[HtmlTargetElement("a", Attributes = "bs-button-color", ParentTag = "form")]
public class ButtonTagHelper : TagHelper
{
public string BsButtonColor { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.Attributes.SetAttribute("class", $"btn btn-{BsButtonColor}");
}
}
}
ContentWrapperTagHelper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace MyTagHelper.TagHelpers
{
[HtmlTargetElement("div", Attributes = "title")]
public class ContentWrapperTagHelper : TagHelper
{
public bool IncludeHeader { get; set; } = true;
public bool IncludeFooter { get; set; } = true;
public string Title { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.Attributes.SetAttribute("class", "panel-body");
var title = new TagBuilder("h2");
title.InnerHtml.Append(Title);
var container = new TagBuilder("div");
container.Attributes["class"] = "bg-info panel-body";
container.InnerHtml.AppendHtml(title);
if (IncludeHeader)
{
output.PreElement.SetHtmlContent(container);
}
if (IncludeFooter)
{
output.PostElement.SetHtmlContent(container);
}
}
}
}
CoordinatingTagHelpers.cs
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace MyTagHelper.TagHelpers
{
[HtmlTargetElement("div", Attributes = "theme")]
public class ButtonGroupThemeTagHelper : TagHelper
{
public string Theme { get; set; }
public override void Process(TagHelperContext context,
TagHelperOutput output)
{
context.Items["theme"] = Theme;
}
}
[HtmlTargetElement("button", ParentTag = "div")]
[HtmlTargetElement("a", ParentTag = "div")]
public class ButtonThemeTagHelper : TagHelper
{
public override void Process(TagHelperContext context,
TagHelperOutput output)
{
if (context.Items.ContainsKey("theme"))
output.Attributes.SetAttribute("class",
$"btn btn-{context.Items["theme"]}");
}
}
}
FormButtonTagHelper.cs
using System;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace MyTagHelper.TagHelpers
{
[HtmlTargetElement("formbutton")]
public class FormButtonTagHelper : TagHelper
{
public string Type { get; set; } = "Submit";
public string BgColor { get; set; } = "primary";
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "button";
output.TagMode = TagMode.StartTagAndEndTag;
output.Attributes.SetAttribute("class", $"btn btn-{BgColor}");
output.Attributes.SetAttribute("type", Type);
output.Content.SetContent(Type == "submit" ? "Add" : "Reset");
}
}
}
LabelAndInputTagHelper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace MyTagHelper.TagHelpers
{
[HtmlTargetElement("label", Attributes = "helper-for")]
[HtmlTargetElement("input", Attributes = "helper-for")]
public class LabelAndInputTagHelper : TagHelper
{
public ModelExpression HelperFor { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (output.TagName == "label")
{
output.TagMode = TagMode.StartTagAndEndTag;
output.Content.Append(HelperFor.Name);
output.Attributes.SetAttribute("for", HelperFor.Name);
} else if (output.TagName == "input")
{
output.TagMode = TagMode.SelfClosing;
output.Attributes.SetAttribute("name", HelperFor.Name);
output.Attributes.SetAttribute("class", "form-control");
if (HelperFor.Metadata.ModelType == typeof(int?))
{
output.Attributes.SetAttribute("type", "number");
}
}
}
}
}
SelectiveTagHelper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace MyTagHelper.TagHelpers
{
[HtmlTargetElement(Attributes = "show-for-action")]
public class SelectiveTagHelper : TagHelper
{
public string ShowForAction { get; set; }
[ViewContext]
[HtmlAttributeNotBound]
public ViewContext ViewContext { get; set; }
public override void Process(TagHelperContext context,
TagHelperOutput output)
{
if (!ViewContext.RouteData.Values["action"].ToString()
.Equals(ShowForAction, StringComparison.OrdinalIgnoreCase))
{
output.SuppressOutput();
}
}
}
}
TableCellTagHelper.cs
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace MyTagHelper.TagHelpers
{
[HtmlTargetElement("td", Attributes = "wrap")]
public class TableCellTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.PreContent.SetHtmlContent("<b><i>");
output.PostContent.SetHtmlContent("</i></b>");
}
}
}
HomeController.cs
using Microsoft.AspNetCore.Mvc;
using CustomTagHelper.Models;
namespace MyTagHelper.Controllers
{
public class HomeController : Controller
{
private readonly IRepository _repository;
public HomeController(IRepository repo)
{
_repository = repo;
}
public ViewResult Index() => View(_repository.Cities);
public ViewResult Create() => View();
[HttpPost]
public IActionResult Create(City city)
{
_repository.AddCity(city);
return RedirectToAction("Index");
}
}
}
视图
Index.cshtml
@model IEnumerable<City>
@{ Layout = "_Layout"; }
<table class="table table-condensed table-bordered">
<thead class="bg-primary">
<tr>
<th>名称</th>
<th>国家</th>
<th class="text-right">人口</th>
</tr>
</thead>
<tbody>
@foreach (var city in Model)
{
<tr>
<td wrap>@city.Name</td>
<td>@city.Country</td>
<td class="text-right">@city.Population?.ToString("#,###")</td>
</tr>
}
</tbody>
</table>
<a href="/Home/Create" class="btn btn-primary">创建</a>
Create.cshtml
@model City
@{ Layout = "_Layout"; }
<form method="post" action="/Home/Create">
<div class="form-group">
<label helper-for="Name" />
<input helper-for="Name" />
</div>
<div class="form-group">
<label helper-for="Country" />
<input helper-for="Country" />
</div>
<div class="form-group">
<label helper-for="Population" />
<input helper-for="Population" />
</div>
@*<formbutton type="submit" bg-color="danger" />
<formbutton type="reset" />
<a bs-button-color="primary" href="/Home/Index">Cancel</a>*@
<div theme="danger">
<button type="submit">添加</button>
<button type="reset">重置</button>
<a href="/Home/Index">取消</a>
</div>
</form>
_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>城市</title>
<link href="/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
</head>
<body class="panel-body">
<div show-for-action="Index" class="panel-body bg-danger">
<h2>重要的信息</h2>
</div>
<div title="城市列表">@RenderBody()</div>
</body>
</html>