独立使用Asp.net Core 的razor模板 (一):Razor引擎的一些细节

摘要:
最近,我们需要编写一些界面稍好的Winform程序。如果我们使用本机控件,那么要实现更好的界面将需要很多努力。因为我们以前使用过CefSharp,所以我们发现如果我们使用CEF+Html,界面可以相对细化(事实上,在设计完成后,我们发现前端工作人员被切割到了图中)。然而,使用CEF+Html的缺点是,正常的软件、页眉和页脚通常很常见,包括一些常见的js/css引用和菜单栏,

    由于最近需要写一些界面稍微好看点的Winform程序,如果用原生控件,,想要达到好看的程度,需要花费比较大的功夫,因为之前使用过CefSharp,因此发觉如果是使用CEF+Html的方式,界面可以相对容易做的精致一点(其实就是设计完之后,找个前端人员切切图),但是,使用CEF+Html有个弊端就是,正常的软件,Header跟Footer大体是通用的,包括一些通用的js/css的引用以及菜单栏等等,,如果直接用html,有个问题就在于,,每个界面都要复制一遍,如果万一发生修改,每个页面又要来一次,或许都这里有朋友会说:"那可以使用vue或者ng的模板啊",,实际情况是,,会用的人不多,但是会用jq的人大把.

     由于服务器端有Razor模板,可以很方便的使用Layout以及各种自己封装的View,但实际情况下,如果单独把Razor拿出来,实际上是只有将模板string+model解析成新的string的功能而已,因此,想要独立的使用Razor就需要为独立的Razor引擎补充一些功能,

首先需要补充的就是Layout功能

 开始动工之前,我们先来了解一下一些功能对应到Razor中,是怎么个实现方式的:

1.先来看一段简单的cshtml文件以及生成后的类:

   _Layout.cshtml

   

独立使用Asp.net Core 的razor模板 (一):Razor引擎的一些细节第1张独立使用Asp.net Core 的razor模板 (一):Razor引擎的一些细节第2张
 1 <html>
 2 <head>
 3     <title></title>
 4 </head>
 5 <body>
 6     
 7     
 8 @RenderBody()
 9 
10 @RenderSection("test",false)
11     
12 </body>
13 </html>
View Code

   Index.cshtml

独立使用Asp.net Core 的razor模板 (一):Razor引擎的一些细节第1张独立使用Asp.net Core 的razor模板 (一):Razor引擎的一些细节第4张
 1 @{
 2     Layout = "_Layout.cshtml";
 3 }
 4 
 5 <p>sdfsdfsdfs</p>
 6 
 7 
 8 @section test{
 9     <p>ddddddddd</p>
10 }
View Code

   Index.cshtml生成后的代码:

独立使用Asp.net Core 的razor模板 (一):Razor引擎的一些细节第1张独立使用Asp.net Core 的razor模板 (一):Razor引擎的一些细节第6张
 1 #pragma warning disable 1591
 2 namespace TEst
 3 {
 4 #line hidden
 5     using System;
 6     using System.Threading.Tasks;
 7     public class TextFile1 : WindowsFormsApp2.RazorViewBase<WindowsFormsApp2.Model>
 8     {
 9 
10 #pragma warning disable 1998
11         public async override global::System.Threading.Tasks.Task ExecuteAsync()
12         {
13             WriteLiteral("

");
14             WriteLiteral("
");
15 #line 5 "TextFile1.cshtml"
16 
17             Layout = "sdfsdfsdfsf";
18 
19 #line default
20 #line hidden
21             WriteLiteral("
<html>
<head>
    <title></title>
</head>
<body>
");
22             DefineSection("ui", async () =>
23             {
24                 WriteLiteral("
    ");
25 #line 15 "TextFile1.cshtml"
26                 Write(Model.A1);
27 
28 #line default
29 #line hidden
30                 WriteLiteral(";
    ");
31 #line 16 "TextFile1.cshtml"
32                 Write(Model.A1?.StartsWith("sfdsfdf"));
33 
34 #line default
35 #line hidden
36                 WriteLiteral("
        <p></p>
    ");
37             }
38             );
39             WriteLiteral("</body>
</html>");
40         }
41 #pragma warning restore 1998
42     }
43 }
44 #pragma warning restore 1591
View Code

1.关于基类,Razor引擎可以设置本次生成的类的基类,并且,要求基类中需要实现几个函数,已供生成的子类调用

2.@section : 如果使用section关键字,编译后,其实是调用基类的DefineSection(string name, Func<Task> act)函数,

   如:在Layout 中,使用 Html.RenderSesction 函数输出

    那么在引用该Layout的页面中,如Index.csthml中,使用

   

1 @section header{
2     sdfsdfsdfsdfs
3      //TODO:其他需要输出在头部的标签
4 }

     对应到实际生成的代码,其实是这样的

 

 1 DefineSection("header", async () =>
 2             {
 3                 WriteLiteral("
    ");
 4 #line 15 "TextFile1.cshtml"
 5                 Write(Model.A1);
 6 
 7 #line default
 8 #line hidden
 9                 WriteLiteral(";
    ");
10 #line 16 "TextFile1.cshtml"
11                 Write(Model.A1?.StartsWith("sfdsfdf"));
12 
13 #line default
14 #line hidden
15                 WriteLiteral("
        <p></p>
    ");
16             }
17             )

     由生成的代码可以看到 ,@section 段的使用,需要基类实现 DefineSection(string name, Func<Task> act) 函数,并且将传入的函数存起来,等待Html.RenderSesction 触发时调用

3.RenderBody,该函数其实是直接把Index.cshtml中,非@section的部分直接输出,由ExecuteAsync函数开始,所有的WriteLiteral的结果总和,因为@section部分已经是通过DefineSection定义了,所以直接输出其他结果并不会干扰到

4.WriteLiteral和Write: WriteLiteral 直接输原始数据,Write除非是输出HtmlString,否则需要转码

5.ExecuteAsync函数:Razor其实上是把cshtml转成对ExecuteAsync函数的内容

6.VS 的IDE支持,,由于.net core 3.0还未出正式版.所以创建的项目为.net 4.5的,而引用的又是asp.net core 的Razor,所以在IDE支持上会有一点点的小区别:

   因此为了省的IDE报太多的错误,需要在基类中,添加几个用于糊弄IDE的函数和属性:

   

public HttpContextFake Context { set; get; }  //返回自己模拟的一个HttpContext的类,
   protected virtual void DefineSection(string name, Action act)  //函数签名略微不同
   public virtual void Execute() //IDE认的就是这个函数,不存在会报错,但没有实际用途
   

   [Browsable(false),Obsolete]
   public class HttpContextFake
   {
      public System.Web.HttpApplication ApplicationInstance { get; }
    }

顺带附上Razor+NaneUI的项目的地址: https://gitee.com/kugar/Kugar.UI.RazorUI

以上是Razor一些小的细节,,下篇文章就开始来说怎么创建一个支持Layout的独立Razor了

免责声明:文章转载自《独立使用Asp.net Core 的razor模板 (一):Razor引擎的一些细节》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇JavaScript网页全屏API【网络状态反馈码】下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

iOS-高仿通讯录之商品索引排序搜索

概述 TableView添加右侧索引, 将数据按照索引分组排序, 并添加搜索功能且在搜索界面复用当前页面. 详细 代码下载:http://www.demodashi.com/demo/10696.html 项目中像一些商品搜索类界面, TableView添加右侧索引的使用越来越多, 的确用户体验提高了许多. 一、主要思路 大致思路: 1....

IOS UITableView reload 刷新某一个cell 或 section

通常刷新整个列表 我们都使用[self.tableView reloadData]; 有的时候,有变化更新的只是某一行 row 或者是某个section 所以只更新这一行就好了 //一个section刷新 int section_index=10;//更新第11个sectioin [self.tableView reloadSections:[NSInde...

加密解密技术—Web.config加密和解密

    阅读目录   一:我们为什么要对web.config配置文件中的配置节加密?   二:怎么样加密和解密?   三:实例   四:运行效果   一:我们为什么要对web.config配置文件中的配置节加密?   因为在我们的项目中,有的配置节可能包含敏感信息,我们看下面的<connectionStrings/>配置节中包含了我们连接 数...

内核中的宏定义__init、__initdata和__exit、__exitdata

  __init、__initdata和__exit、__exitdata的定义位于<kernel/include/linux/init.h> 1 /* These are for everybody (although not all archs will actually 2 discard it in modules) */...

关于jQuery UI 使用心得及技巧

最近项目中使用了一些插件来做页面,这里把jQuery UI的使用分享出来,希望 对新手有帮助。文章结尾附源码下载。 1 jQuery UI 有时你仅仅是为了实现一个渐变的动画效果而不得不把javascrip 重新学习一遍然后书写大量代码。直到jQuery的出现,让开发人员从一大堆繁琐的js代码中解脱,取而代之几行jQuery代码。现今,jQuery无疑已...

C#读写INI文件

虽然微软早已经建议在WINDOWS中用注册表代替INI文件,但是在实际应用中,INI文件仍然有用武之地,尤其现在绿色软件的流行,越来越多的程序将自己的一些配置信息保存到了INI文件中。 INI文件是文本文件,由若干节(section)组成,在每个带括号的标题下面,是若干个关键词(key)及其对应的值(Value) [Section] Key=Value...