编程 16

平台化项目多语言架构完成,通过TagHelper封装控件

By admin in 编程 on 2019年9月24日

品种为什么要平台化

.net core
除了三回九转保留.net
framework的HtmlHelper的写法以外,还提供了TagHelper和ViewComponent格局调换控件。

一、易维护

卷入能够大大的减少耦合,当发生变动的时候只需求修改一处地点。平台化项目和包装是有分别的,平台化项目是将品种具备组件、事件等拟订贰个规范,将那个零件基于专门的学业举办中度封装,实现配置分界面,通过配备大大的裁减编码量。

当要求完整更动的时候只须要改造那些标准便可,维护点更加的肯定。

咱俩本节说的是运用TagHelper来生成控件。然而严酷的聊到来,TagHelper是对顾客端html元素的协理类,比如渲染、扩充服务端性情等。大家能够利用
taghelper
定义自个儿的竹签或转移已知标签。使用TagHelper,VS.net编写翻译碰着也能够自动感知,并提供智能提醒。因为TagHelper生成的控件,看起来像一个原生的HTML标签同样,也更有益美工进行页面美化。

二、可扩展

1、首先有点作者要订正,多数少人都说封装性太强的事物只可以做一些意志的品种,不能够满意复杂的必要。那几个视角是谬误的,只可以说你在利用外人中度封装的框架,而没有自已的框架
只怕 没有调整别人的框架 在照旧那些框架太LOW了。优异的框架都以能够满意开辟要求的,因为他俩都留有相当多自定义的地点。

2、当项目须求无法满意的时候,可以遵照标准去扩充现存组件只怕创建新的组件。

3、尽管组件代码太垃圾也没涉及,只要保障调用处是明媒正娶的,未来随时都得以对组件进行重构。

例如说三个lable控件 <label asp-for=”Email”></label>,生成的末梢html就是这么:<label for=”Email”>xxx@xx.com</label>

三、成长性

乘机项目尤为多,规范会愈发周全,组件也会更扩充

 

多语言传统实现形式

编程,丢掉数据库部分

尽管要利用TagHelper,除了在页面中using
命名空间之外,还亟需采用@addTagHelper来使TagHelper可用。由于大家会编写不唯有一个TagHelper,且在多少个cshtml页面使用,因而大家将如下代码

一、财富文件

通过Cookie的值来支配到底调用哪个财富文件,小编用的是.NET,笔者就来吐嘈下.NET财富文件的多多不方便人民群众

编程 1

1、供给定义N多的Key。

2、为何要把粤语和土耳其共和国语分成五个文件,来回切换有多劳碌,而实际上我们要求的是如此的财富文件。

编程 2

3、品质差笨重

@using
MicroStrutLibrary.Presentation.Web.Controls

二、XML

1、要求自已布置代码

2、无法在静态文件中应用,做不到前后分离

3、查看不便利,未有EXCEL直观

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

三、三个页面

使用八个页面来落成多语言有多少个毛病:

1、当贰个页面HTML结构发掘变动的时候任何页面也急需转移

2、未有现存的文件给专门的机关去翻译,要自已整理可能翻译者就在技术员身边

@addTagHelper *, MicroStrutLibrary.Presentation.Web.Controls

据悉平台化的完毕形式

写在视图像和文字件
Views/_ViewImports.cshtml中。写在Views/_ViewImports.cshtml的意味是,私下认可全数的在
Views 和Views下级目录中的视图像和文字件都能够利用TagHelper,通配符 (“*”)
来钦定在一定程序集(Microsoft.AspNetCore.Mvc.TagHelpers和MicroStrutLibrary.Presentation.Web.Controls)中的全部的
TagHelpers
在 Views目录和子目录中的视图像和文字件中都以可用的。第三个程序集是mvc自带的,第二个是我们分甘共苦的控件程序集。具体的验证大家要么看.net
core文书档案吧。

一、设计能源文件

如下图我们接纳了EXCEL作为财富文件,依照效果与利益的例外把EXCEL划分为多少个公文,和理念的财富文件划分情势是分歧的。

编程 3

依据页面定义了多少个Sheet,有三种语言就定义几列,并非有二种言语就定义多少文件和守旧格局是质变。

编程 4

只要找个兄弟把CN整理好,就无需大家付出机构出任何体力了,只怕会有人问为啥平昔不key,对!大家正是不必要用到key那些麻烦,上边会讲到如何完成。

 

二、怎么样深入分析EXCEL

.NET能够应用Aspose.cell或许NOPI等零件把将EXCEL转为对象,可以将那一个指标存进Cache缩短IO操作

累积的构造为List<T>

public class T{

目录

模块

页面

语言A

语言B

语言C …

}

这种结构得以很轻便的筛选出当下页面所要求的言语

上面,大家依旧以上一节介绍的多选控件MultiSelect为例,表达下大家的TagHelper封装进程。

三、达成1:模版分析引擎里面作手脚完结全局替换

拿.NET MVC来举例子:

运用RazorEngine.dll自已落到实处CSHTML转HTML

public ActionResult Index(){string templateObj = GetViewByFilePath("~/Home/index.cshtml");  var model=new { id = xxx };string html = Razor.Parse(templateObj ,model ); //根据Excel转成的List<T>,筛选出当前页面的语言List<T>,对这个html 进行遍历替换处理 //代码并无封装可言,我只是为了让大家看的更明白些foreach(var it in List<T>){  html=html.Replace(it.默认语言,it.当前语言);}return View((new HtmlString,"~/Home/Shared/Language.cshtml");}

  

//全部页面最后都应用Language.CSHTML文件  

@model HtmlString@Model

MultiSelect在cshtml中的写法如下,asp-dataSource传入的是数据源,select的具备下拉内容都以通过datasource生成的,而asp-value传入的是选中的项:

上边的轮换代码只是最简便的例证更加细节的位置小编会在底下讲到  

1 @model Dictionary<string, string>
2 @{ 
3     List<string> values = ViewData.Get<List<string>>("Values");
4 }
5 
6 <multiSelect id="txtInput0" asp-dataSource="@Model" asp-value="@values"></multiSelect> 

缺点:

不怕使用了缓存也可以有一些点质量影响,至少不会比能源文件差。

 

四、达成2:生成静态文件情势

只须要开拓私下认可语言的享有页面,然后通过工具的不二等秘书籍去生成任何页面

如图: index_en.cshtml是因而工具生成出来的页面

编程 5

重写视图引擎依照库克ie自动调用相应的View文件

{    /// <summary>    /// 自定义MVC视图引擎    /// </summary>    public sealed class BestViewEngine : RazorViewEngine    {         public BestViewEngine()        {        }        /// <summary>        /// 重写FindView        /// </summary>        /// <param name="controllerContext"></param>        /// <param name="viewName"></param>        /// <param name="masterName"></param>        /// <param name="useCache"></param>        /// <returns></returns>        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)        {            var key ="languageKey";//COOKIE KEY            var cm = CookiesManager<string>.GetInstance();            if (cm.ContainsKey//验证多语言COOKIE是否有值            {                var cacheVal = cm[key]; //获取多语言后缀                 if (cacheVal.IsValuable                    viewName += "_{0}".ToFormat;//将原视图名添加后缀   比如 index 添加后缀之后就是 index_en            }            return base.FindView(controllerContext, viewName, masterName, useCache);//参数处理后调用BASE的FindView方法        }     }}

工具的逻辑很粗大略 读取文件index.cshtml HTML
=》获取语言List<T>=>筛选语言List<T>=>遍历替换来新的HTML
写入Index_en.cshtml

Model和values从controller中传过来的,具体如下:

缺点

动用的是工具,总认为少了点什么。

 1         public IActionResult MultiSelect()
 2         {
 3             Dictionary<string, string> data = new Dictionary<string, string>();
 4             data.Add("1", "Aaaaa");
 5             data.Add("2", "Aaron");
 6             data.Add("3", "Abbott");
 7             data.Add("4", "Abel");
 8             data.Add("5", "Abner");
 9             data.Add("6", "Abraham");
10             data.Add("7", "Adair");
11             data.Add("8", "Adam");
12             data.Add("9", "Addison");
13 
14             List<string> value = new List<string>();
15             value.Add("2");
16             value.Add("7");
17             ViewData["Values"] = value;
18 
19             return View(data);
20         }

五、达成3:咱们平台的兑现格局

1、页面全体的美食指南是通过平台配置生成的

编程 6

透过后台配置生成出来的导航地图

编程 7

2、将多语言工具集成到阳台配置分界面,点击生成都电子通信工程学院动创制相应的VIEW文件

编程 8

变迁后的目录

编程 9

3、数据库因为有
语言表和菜单表,Excel里面包车型地铁Sheet就更易于筛选了,只要在列里面增加叁个菜系ID便可,算法也愈加简明,EXCEL的结构也帮忙更加多花样

 

六、替换的小本事

1、JS代码普通话的提取

编程 10

JS使用页面包车型客车概念

编程 11

2、依据上海教室整理出来的Sheet,把JS部分和页面部分的粤语都收拾进去了,并且把当下菜谱ID也加进去了方便人民群众筛选

编程 12

3、拿EXCEL里面包车型的士首先行和第二行来讲吧,若是就这么单纯的交替会师世难题

页面里面包车型大巴,会化为 【Required数字】

编程 13

、大家得以通过先替换长的,在轮换短的来减轻这几个主题材料

、先替换当前页面包车型大巴在轮换公共的

、按下面2种替换格局得以确认保证99%页面替换是准明确的了,针对特殊情形们能够通过标志增加优先级
只要以^符号的始发的首先替换=》然后按长度=》按当前页和通用页,那样就能够保证99.9%,就那样推算(说白了便是在先行级上边做动作)。

这么,最后生成的html代码和页面如下:

你不给个赞吧?

 1 <div>
 2   <select id="txtInput0" name="txtInput0" multiple="multiple">
 3     <option value="1" >Aaaaa</option>
 4     <option value="2" selected>Aaron</option>
 5     <option value="3" >Abbott</option>
 6     <option value="4" >Abel</option>
 7     <option value="5" >Abner</option>
 8     <option value="6" >Abraham</option>
 9     <option value="7" selected>Adair</option>
10     <option value="8" >Adam</option>
11     <option value="9" >Addison</option>
12   </select>
13   <script>
14     require(['jquery', 'bootstrap', 'multiselect'], function ($) {
15       $(function(){
16         $("#txtInput0").multiselect({
17             nonSelectedText: '请选择',
18             enableFiltering: true,//是否显示过滤
19             filterPlaceholder: '查找',
20             includeSelectAllOption: true,//是否显示全选
21             selectAllText: '全选',
22             numberDisplayed: 5//显示条数
23         });
24           });
25     });
26   </script>
27 </div> 

 

MultiSelect在页面展现如下图

编程 14

依据布署,MultiSelect应该能够传入:1、数据源,也正是下拉列表的保有数据;2、已选拔,已选拔的数据;3、下拉列表的展现条数,避防条数过多,影响页面;4、是还是不是只读等属性,越来越好的支配控件的显得内容。当然了,还应当满含二个For属性,这一个For属性的情致是透过页面包车型客车Model绑定,自动生成控件Id和已摘取数据项等内容。

是因为具备的TagHelper都承接于三个基类TagHelper,我们首先看下TagHelper抽象类:

 1     //
 2     // 摘要:
 3     //     Class used to filter matching HTML elements.
 4     public abstract class TagHelper : ITagHelper
 5     {
 6         protected TagHelper();
 7 
 8         //
 9         // 备注:
10         //     Default order is 0.
11         public virtual int Order { get; }
12 
13         //
14         public virtual void Init(TagHelperContext context);
15         //
16         // 摘要:
17         //     Synchronously executes the Microsoft.AspNetCore.Razor.TagHelpers.TagHelper with
18         //     the given context and output.
19         //
20         // 参数:
21         //   context:
22         //     Contains information associated with the current HTML tag.
23         //
24         //   output:
25         //     A stateful HTML element used to generate an HTML tag.
26         public virtual void Process(TagHelperContext context, TagHelperOutput output);
27         //
28         // 摘要:
29         //     Asynchronously executes the Microsoft.AspNetCore.Razor.TagHelpers.TagHelper with
30         //     the given context and output.
31         //
32         // 参数:
33         //   context:
34         //     Contains information associated with the current HTML tag.
35         //
36         //   output:
37         //     A stateful HTML element used to generate an HTML tag.
38         //
39         // 返回结果:
40         //     A System.Threading.Tasks.Task that on completion updates the output.
41         //
42         // 备注:
43         //     By default this calls into Microsoft.AspNetCore.Razor.TagHelpers.TagHelper.Process(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext,Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput).
44         public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output);
45     }

 

此地最重要的就是Process方法和ProcessAsync方法。那八个格局,一个是联合,多个是异步,作用都是出口页面html代码。

我们再来看包装后的MultiSelectTagHelper的代码:

  1     [HtmlTargetElement("multiSelect", Attributes = ForAttributeName)]
  2     [HtmlTargetElement("multiSelect", Attributes = ValueAttributeName)]
  3     [HtmlTargetElement("multiSelect", Attributes = ShowItemCountAttributeName)]
  4     [HtmlTargetElement("multiSelect", Attributes = DataSourceAttributeName)]
  5     [HtmlTargetElement("multiSelect", Attributes = ReadonlyAttributeName)]
  6     public class MultiSelectTagHelper : TagHelper
  7     {
  8         private readonly IHtmlGenerator generator;
  9 
 10         public MultiSelectTagHelper(IHtmlGenerator generator)
 11         {
 12             this.generator = generator;
 13         }
 14 
 15         private const string ForAttributeName = "asp-for";
 16         private const string ValueAttributeName = "asp-value";
 17         private const string ShowItemCountAttributeName = "asp-showItemCount";
 18         private const string DataSourceAttributeName = "asp-dataSource";
 19         private const string ReadonlyAttributeName = "asp-readonly";
 20 
 21         [HtmlAttributeNotBound]
 22         [ViewContext]
 23         public ViewContext ViewContext { get; set; }
 24 
 25         [HtmlAttributeName(ForAttributeName)]
 26         public ModelExpression For { get; set; }
 27 
 28         [HtmlAttributeName(ValueAttributeName)]
 29         public List<string> Value { get; set; }
 30 
 31         [HtmlAttributeName(ShowItemCountAttributeName)]
 32         public int ShowItemCount { get; set; } = 5;
 33 
 34         [HtmlAttributeName(DataSourceAttributeName)]
 35         public Dictionary<string, string> DataSource { get; set; }
 36 
 37         [HtmlAttributeName(ReadonlyAttributeName)]
 38         public bool Readonly { get; set; }
 39 
 40         public override void Process(TagHelperContext context, TagHelperOutput output)
 41         {
 42             MicroStrutLibraryExceptionHelper.IsNull(context, this.GetType().FullName, LogLevel.Error, "context参数值为空");
 43             MicroStrutLibraryExceptionHelper.IsNull(output, this.GetType().FullName, LogLevel.Error, "output");
 44 
 45             output.TagName = "div";
 46             //output.Attributes.Add("class", "multiselect-drop");
 47 
 48             MultiSelectList selectList = new MultiSelectList(this.DataSource, "Key", "Value", this.Value);
 49 
 50             HtmlContentBuilder builder = new HtmlContentBuilder();
 51 
 52             string id;
 53             if (For == null)
 54             {
 55                 id = output.Attributes["id"].Value.ToString();
 56                 output.Attributes.Remove(output.Attributes["id"]);
 57 
 58                 string options = string.Empty;
 59                 foreach (SelectListItem item in selectList)
 60                 {
 61                     options += $"<option value=\"{item.Value}\" {(item.Selected ? "selected" : "")}>{item.Text}</option>";
 62                 }
 63 
 64                 builder.AppendHtml($"<select id=\"{id}\" name=\"{id}\" multiple=\"multiple\">{options}</select>");
 65             }
 66             else
 67             {
 68                 id = For.Name;
 69 
 70                 TagBuilder dropDown = generator.GenerateSelect(ViewContext, For.ModelExplorer, For.Name, string.Empty, selectList, true, null);
 71                 builder.AppendHtml(dropDown);
 72             }
 73 
 74             string readOnly = "";
 75             if (this.Readonly)
 76             {
 77                 readOnly = $"$('#{id} +div > button').attr('disabled', true);";
 78             }
 79             string script = string.Format(@"
 80 <script>
 81 require(['jquery', 'bootstrap', 'multiselect'], function ($) {{
 82     $(function(){{
 83         $(""#{0}"").multiselect({{
 84             nonSelectedText: '请选择',
 85             enableFiltering: true,//是否显示过滤
 86             filterPlaceholder: '查找',
 87             includeSelectAllOption: true,//是否显示全选
 88             selectAllText: '全选',
 89             numberDisplayed: {1}//显示条数
 90         }});
 91         {2}
 92     }});
 93 }});
 94 </script>
 95 ", id, this.ShowItemCount, readOnly);
 96 
 97             builder.AppendHtml(script);
 98 
 99             output.Content.AppendHtml(builder);
100 
101             base.Process(context, output);
102         }
103     }

 

为了在编写程序时不会出错,大家定义了四个常量ForAttributeName
、ValueAttributeName、ShowItemCountAttributeName、DataSourceAttributeName、ReadonlyAttributeName,分别表示MultiSelect标签的asp-for等Attribute。也正是MultiSelect传入的数据源、已摘取、下拉列表的显得条数、是不是只读等天性、For属性。

 

类定义方面[HtmlTargetElement(“multiSelect”, Attributes =
ValueAttributeName)]的效应是在multiSelect标签上生成ValueAttributeName对应值asp-value的Attribute。

性能下面

[HtmlAttributeName(ValueAttributeName)]

public List<string> Value { get; set; }

的功用是报告multiSelect标签,asp-value传入的应有是个List<string>类型。这里须要注意的是,在种种文档、教程中,大非常多景况下,Attribute传入的体系都以一对简短类型,举个例子字符串、数字等。其实Attribute是足以流传复杂的类型的,比方大家这里传出的List<string>。页面中也将要如下的利用方式:

1 @model Dictionary<string, string>
2 @{ 
3     List<string> values = ViewData.Get<List<string>>("Values");
4 }
5 
6 <multiSelect id="txtInput0" asp-dataSource="@Model" asp-value="@values"></multiSelect>

 

再有贰本品质ViewContext,这几个天性不是显式传入的,而是TagHelper创设时,系统自动赋值的,含义是时下的视图试行上下文Microsoft.AspNetCore.Mvc.Rendering.ViewContext。

[HtmlAttributeNotBound]

[ViewContext]

public ViewContext
ViewContext { get;
set; }

 

这里还应该有三个亟待器重表达的是For格局public ModelExpression For { get; set;
}。普通格局下,multiSelect的Id、Value都以从页面传入的,但是For形式是与Model绑定的,仿佛HtmlHelper的TextBox、TextBoxFor的界别一样。举个例子,一位或然有多个职务,人的职责属性是DutyList,全部任务的多少DutyDictionary,在cshtml页面中就依照如下方式写multiselect:

@model UserInfo

<multiSelect asp-dataSource=”@DutyDictionary” asp-for=”DutyList”></multiSelect>

 

MultiSelect构造函数中,传入了一个IHtmlGenerator参数,这一个是透过DI容器自动分析出来的,缺省景况下的落到实处类是DefaultHtmlGenerator。那些类的显要功效是变化各个html标签。大家在For格局利用了自动生成select标签的秘诀。TagBuilder dropDown = generator.GenerateSelect(ViewContext,
For.ModelExplorer, string.Empty, For.Name, selectList, true, null);

 

最终就是重写Process方法。其实那一个法子依然相比较轻易的,当For格局时,通过For自动生成select;否则就和好写select。我们内部还写了一段脚本,脚本中一直援引了jquery的MultiSelect脚本,

require([‘jquery’, ‘bootstrap’,
‘multiselect’], function ($) {{…

此地我们应用systemjs这几个通用的javascript模块加载器,个中的jquery、bootstrap、multiselect都以在system.config中定义的。System.config.js的代码大意如下,至于为啥那样写,大家仍旧搜英特网帮助吗:

 1     System.config({
 2         bundles: {
 3         },
 4         paths: {
 5             "external:": externalUrl+"/"
 6         },
 7         map: {
 8             "jquery": "external:lib/jquery/jquery.min.js",
 9             "bootstrap": "external:lib/bootstrap/js/bootstrap.min.js",
10 
11             //--
12             "jquery-ui": "external:lib/jquery/jquery-ui/jquery-ui.bundle.min.js",
13 
14             //--Plugins
15             "multiselect": "external:lib/plugins/multiselect/js/bootstrap-multiselect.min.js"
16             …
17 },
18         meta: {
19             '*.css': {
20                 loader: 'external:lib/system/css-loader/css.js'
21             },
22             'jquery': {
23                 format: 'global',
24                 exports: 'jQuery'
25             },
26             'bootstrap': {
27                 format: 'global',
28                 deps: ['jquery']
29             },
30             'jquery-ui': {
31                 format: 'global',
32                 deps: ['jquery','./jquery-ui.min.css']
33             },
34             'multiselect': {
35                 format: 'global',
36                 deps: ['../css/bootstrap-multiselect.min.css']
37             },
38 …
39         },
40         packages: {
41             '/js': {
42                 format: 'cjs',
43                 defaultExtension: 'js'
44             },
45 
46             //externals
47             'external:js': {
48                 format: 'cjs',
49                 defaultExtension: 'js'
50             }
51         }
52     });
53 
54     //amd require
55     window.require = System.amdRequire;

至此,壹在这之中坚的Taghelpr就完成了。

在ASP.NET Core
MVC中应当利用 TagHelpers 来替换
HtmlHelpers,因为它们进一步的轻松和易于选用。另叁个了不起的裨益正是依据注入,在HtmlHelpers中是运用持续的,因为HtmlHelpers
扩充的都以静态内容。
但TagHelpers是三个公共类,我们得以很轻便的在它的构造函数中流入服务。

 

进级:能源性视图的行使

依据上节的规矩,大家照旧还一个进级,表达下在TagHelper中如何行使cshtml,以及cshtml作为嵌入的财富该怎么着写。

作者们从上边MultiSelectTagHelper类元帅Process方法的页面代码拼接程序领抽取来,写成cshtml如下

 1 @{
 2     string id = ViewData["Id"].ToString();
 3     int showItemCount = (int)ViewData["ShowItemCount"];
 4     bool isReadonly = (bool)ViewData["Readonly"];
 5 }
 6 
 7 <script>
 8     require(['jquery', 'bootstrap', 'multiselect'], function ($) {
 9         $(function(){
10             $("#@id").multiselect({
11                 nonSelectedText: '请选择',
12                 enableFiltering: true,//是否显示过滤
13                 filterPlaceholder: '查找',
14                 includeSelectAllOption: true,//是否显示全选
15                 numberDisplayed: @(showItemCount),//显示条数
16                 selectAllText: '全选'
17             });
18             @if (isReadonly)
19         {
20             @:$("#@id +div > button").attr("disabled", true);
21                     }
22         });
23     });
24 </script>

 

像这种类型MultiSelectTagHelper类中就简化成如下:

 1     [HtmlTargetElement("multiSelect", Attributes = ForAttributeName)]
 2     [HtmlTargetElement("multiSelect", Attributes = ValueAttributeName)]
 3     [HtmlTargetElement("multiSelect", Attributes = ShowItemCountAttributeName)]
 4     [HtmlTargetElement("multiSelect", Attributes = DataSourceAttributeName)]
 5     [HtmlTargetElement("multiSelect", Attributes = ReadonlyAttributeName)]
 6     public class MultiSelectTagHelper : TagHelper
 7     {
 8         private readonly IHtmlGenerator generator;
 9         private readonly IUrlHelperFactory factory;
10         private readonly IHtmlHelper htmlHelper;
11 
12         public MultiSelectTagHelper(IHtmlHelper htmlHelper, IHtmlGenerator generator)
13         {
14             this.generator = generator;
15             this.factory = factory;
16             this.htmlHelper = htmlHelper;
17         }
18 
19         private const string ForAttributeName = "asp-for";
20         private const string ValueAttributeName = "asp-value";
21         private const string ShowItemCountAttributeName = "asp-showItemCount";
22         private const string DataSourceAttributeName = "asp-dataSource";
23         private const string ReadonlyAttributeName = "asp-readonly";
24 
25         [HtmlAttributeNotBound]
26         [ViewContext]
27         public ViewContext ViewContext { get; set; }
28 
29         [HtmlAttributeName(ForAttributeName)]
30         public ModelExpression For { get; set; }
31 
32         [HtmlAttributeName(ValueAttributeName)]
33         public List<string> Value { get; set; }
34 
35         [HtmlAttributeName(ShowItemCountAttributeName)]
36         public int ShowItemCount { get; set; } = 5;
37 
38         [HtmlAttributeName(DataSourceAttributeName)]
39         public Dictionary<string, string> DataSource { get; set; }
40 
41         [HtmlAttributeName(ReadonlyAttributeName)]
42         public bool Readonly { get; set; }
43 
44         public override void Process(TagHelperContext context, TagHelperOutput output)
45         {
46             MicroStrutLibraryExceptionHelper.IsNull(context, this.GetType().FullName, LogLevel.Error, "context参数值为空");
47             MicroStrutLibraryExceptionHelper.IsNull(output, this.GetType().FullName, LogLevel.Error, "output");
48 
49             output.TagName = "div";
50             //output.Attributes.Add("class", "multiselect-drop");
51 
52             MultiSelectList selectList = new MultiSelectList(this.DataSource, "Key", "Value", this.Value);
53 
54             HtmlContentBuilder builder = new HtmlContentBuilder();
55 
56             string id;
57             if (For == null)
58             {
59                 id = output.Attributes["id"].Value.ToString();
60                 output.Attributes.Remove(output.Attributes["id"]);
61 
62                 string options = string.Empty;
63                 foreach (SelectListItem item in selectList)
64                 {
65                     options += $"<option value=\"{item.Value}\" {(item.Selected ? "selected" : "")}>{item.Text}</option>";
66                 }
67 
68                 builder.AppendHtml($"<select id=\"{id}\" name=\"{id}\" multiple=\"multiple\">{options}</select>");
69             }
70             else
71             {
72                 id = For.Name;
73 
74                 TagBuilder dropDown = generator.GenerateSelect(ViewContext, For.ModelExplorer, null, For.Name, selectList, true, null);
75                 builder.AppendHtml(dropDown);
76             }
77 
78             output.Content.AppendHtml(builder);
79 
80             //Contextualize the html helper
81             (htmlHelper as IViewContextAware).Contextualize(ViewContext);
82 
83             ViewDataDictionary data = new ViewDataDictionary(this.ViewContext.ViewData);
84             data["Id"] = id;
85             data["ShowItemCount"] = this.ShowItemCount;
86             data["Readonly"] = this.Readonly;
87             
88             var content = htmlHelper.Partial("TagHelpers/MultiSelect/MultiSelect", data);
89             output.Content.AppendHtml(content);
90 
91             base.Process(context, output);
92         }
93     }
94 }

 

世家大概注意到构造函数中我们增添了个参数IHtmlHelper htmlHelper。这个参数是此前MVC的HtmlHelper,我们透过DI格局直接获取到htmlhelper。然则,此时DI获取的htmlhelper还无法使用,必得透过(htmlHelper as IViewContextAware).Contextualize(ViewContext);将上下文音信传播HtmlHelper。var content = htmlHelper.Partial(“TagHelpers/MultiSelect/MultiSelect”, data);
output.Content.AppendHtml(content);这两句话试行cshtml页面,将最终页面包车型大巴源委呈今后TagHelper中。

此处还会有三个难题,正是大家将有所的控件都存放到八个应用程序聚焦,控件的cshtml页面也会以能源格局打包进应用程序集中。大家控件的花色布局如下:

编程 15

MultiSelect的源委如下,有2个文件,四个cshtml,一个是taghelper程序。别的目录的构造也是近似的。

编程 16

新的.net
core的放手能源格局索要在project.json中遵从如下格局编写:

“buildOptions”: {

“embed”: [ “Components/**/*.cshtml”, “TagHelpers/**/*.cshtml” ]

}

那边的意味是我们将具备components和taghelpers目录下的第二级子目录下的兼具cshtml文件以放权方式打包进应用程序聚集。在.net
core中使用应用程序聚焦停放的文书,还算是比较有利。因为.net
core已经把无数可扩展的原委开放出来了。

大家这里写了二个恢弘方法,在RazorViewEngineOptions(RazorViewEngine程序方法的配备)中追加二个Razor视图像和文字件的一向器EmbeddedFileProvider。EmbeddedFileProvider就足以博得应用程序集中停放的cshtml文件,构造函数第一个参数是包罗嵌入cshtml文件的施用程序集,第贰个参数是命名空间。

 1     public static class EmbeddedViewServiceCollectionExtensions
 2     {
 3         public static IServiceCollection AddEmbeddComponentView(this IServiceCollection services)
 4         {
 5             if (services == null)
 6             {
 7                 throw new ArgumentNullException(nameof(services));
 8             }
 9 
10             EmbeddedFileProvider fileProvider = new EmbeddedFileProvider(typeof(EmbeddedViewServiceCollectionExtensions).GetTypeInfo().Assembly, "MicroStrutLibrary.Presentation.Web.Controls");
11 
12             services.Configure<RazorViewEngineOptions>(options => {
13                 options.FileProviders.Add(fileProvider);
14             });
15 
16             return services;
17         }
18     }

 

接下去正是在Startup.cs中应用那个增加方法:

1 public void ConfigureServices(IServiceCollection services)
2 {
3      services.AddMvc(options =>
4         {
5             …
6         });
7 
8     services.AddEmbeddComponentView();
9 }

 

未来才发觉,其实生成select标签部分也是应当放手csthml中的,实际不是在taghelper中生成,就不改了呀:)。

此处关键有多少个小技艺再唤醒下:

1、cshtml页面中,Taghelper的Attribute可以流传各样复杂对象,并非string\int\bool等简便类型

2、TagHelper即使使用cshtml,则应该选拔IHtmlHelper

3、嵌入财富格局的cshtml,须求利用embeddedfileprovider。

 

面向云的.net
core开垦框架

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2020 澳门新葡亰官网app 版权所有