MVC的验证(模型注解和非侵入式脚本的结合使用)

 

@HtmlHrlper方式创建的标签,会自动生成一些属性,其中一些属性就是关于验证

如图示例:


模型注解

通过模型注解后,MVC的验证,包括前台客户端,后台服务器的验证,MVC统统都做了包含,即使用户在客户端禁用Javascript,服务器也会将非法操作进行验证,当前前提是针对Model实体标识了注解的情况。

要能够正常进行非空等合法性验证必须做如下步骤(前提条件):

1.必须在实体的每个类型上加上Required特性,但是数字型的属性默认已经加上了。

2.必须在视图上导入如下脚本:

<script src="~/Scripts/jquery-1.7.1.js"></script>   

<script src="~/Scripts/jquery.validate.js"></script>

<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>  ——非嵌入式脚本

3.配置文件里的属性配置如下:

  <appSettings>
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>

MVC默认自带的样式:

<link href="~/Content/Site.css" rel="stylesheet" />

关键命名空间:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.Web.Mvc;

使用实例

一、非空验证

在属性上打标:

  [Required(ErrorMessage="不能为空")]
  public string dUserName { get; set; }

在视图创建标签处加上@Html.ValidationMessageFor,此标签是当验证错误时,会有相应提示,本质是一个span标签

  @Html.TextBoxFor(d=>d.dUserName)
  @Html.ValidationMessageFor(d=>d.dUserName)

二、约束文本框输入的长度

关键代码:

[StringLength(10, MinimumLength = 4, ErrorMessage = "名称长度只能介于4到10之间")]
public string dUserName { get; set; }

三、给表单项的控件加上描述表示

关键代码:

[DisplayName("姓名")]
public string dUserName { get; set; }

视图代码加上相应代码:

@Html.DisplayNameFor(d=>d.dUserName)

相应效果:

四、约束整数的取值范围,在属性上打标如下:

[Range(100,1000,ErrorMessage="最小为100元,最多捐1000元")]

五,保证该文本框输入与另一个要相同 (可用于两次密码输入保持一致)

[Compare("Pwd1",ErrorMessage="两次输入密码不一致")]

第一个参数是要匹配的属性名称

六、使用正则表达式

[RegularExpression("\\d+",ErrorMessage="密码必须为纯数字")]

七、自定义类型表单标签

后台代码:

     [DataType(DataType.EmailAddress)]
        [DisplayName("电子邮件")]
        public string Email { get; set; }

前台使用:

  @Html.DisplayNameFor(d=>d.Email)  ----提示文本
  @Html.EditorFor(d=>d.Email)    -----自定义类型标签 为email格式
  @Html.ValidationMessageFor(d=>d.Email)  ---提示错误消息标签

这里输入错误的提示消息,默认是英文,需要修改文件可以改成中文,修改图解:

八、Remote标注属性对,文本框输入,通过Ajax连接数据库,判断有效性 (此方法是效验时配合ajax连接数据库)

例:注册时可用于检查用户名是否被使用过,神奇效果:

注意:Remote是通过Ajax请求来进行验证,为了防止缓存一般写成post请求

打标:

[Remote("checkUsername","Donation",ErrorMessage="用户名已经存在",HttpMethod="post")]   

checkUsername (action方法)

Donation (控制器名称)

Action方法配合使用示例:

    [HttpPost]
        public ActionResult checkUsername()
        {
                    //1.获取检查的值
            string uname = Request["dUserName"];

            //2.连接数据库判断
         DonationEntities db=new DonationEntities ();
          var model=db.DonationDetail.FirstOrDefault(d=>d.dUserName==uname);

            if (model!=null&&model.dUserName==uname)
            {
                return Content("false");
            }

            return Content("true");
        }

九、后台验证

MVC验证客户端,需要依赖js脚本文件,如果用户在浏览器里禁用了JavaScript,

这时我在后台可使用以下相应对策。

//表示验证实体对象中所有标注了特性标签的属性是否合法,如果其中有一个不合法则返回false
            if (ModelState.IsValid==false)
            {
                /*
                 对于验证失败返回视图相应的提示消息
                 * 视图中需要 @Html.ValidateionSummry(true)标签配合使用
                 */
                ModelState.AddModelError("","实体验证失败");
                return View();
            }

.Net中初探Redis

 

一、简介

Redis是著名的NOSQL数据库,本质就是存储键值对结构的数据,为存储键值对数据做了优化,在大型网站中应用很多。Redis提供了数据的自动过期处理,因此适合存储临时数据。

和Redis类似的还有Memcached, Redis可以把数据持久化到硬盘中,而Memcached是放到内存中,重启后就消失,一般用Memcached做缓存。


二、Redis服务器的部署(Windows)

Redis服务器有Linux、Windows版,Linux版性能好适合生产环境。这里只说明Windows里配置Redis服务器,用于开发。

1.安装Redis服务

文件下载:redisbin_x32

安装路径不要包含中文或其他特殊符号,解压后服务相关文件如下:

redis-server.exe单击该文件虽然可以开启服务,但是要一直保证这个文件不能关闭,双击点开如图:

2.把Redis服务配置到Windows服务里

说明:配置此项后,不必去通过找到“redis-server.exe”文件单击打开一直挂着,才能使用服务。

文件下载:RedisWatcher1

解压安装后相关文件如下:

修改“watcher.conf”文件里,打开文件,进行图片说明的操作

修改后去Windows服务里开启Redis服务,如图:


三、在.net中操作Redis

1.在项目中导入相关的.dll文件的引用

文件下载:Redis.Net驱动

相关.dll如图:

2.创建一个RedisManage类

写入以下关键代码:

 
 1 using ServiceStack.Redis;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7
 8 namespace Redis_Test
 9 {
10     class RedisManage
11     {
12
13         public static PooledRedisClientManager ClientManager { get; private set; }
14         static RedisManage()
15         {
16             RedisClientManagerConfig redisConfig = new RedisClientManagerConfig();
17             redisConfig.MaxWritePoolSize = 128;
18             redisConfig.MaxReadPoolSize = 128;
19
20             //可以读写分离,指定一台服务器读,一台写。
21             // new PooledRedisClientManage(读写的服务器地址,只读的服务器地址
22             ClientManager = new PooledRedisClientManager(new string[] { "127.0.0.1" },
23                 new string[] {"127.0.0.1"}, redisConfig);
24         }
25
26
27     }
28 }
 

3.存储信息的方法

 
 1
 2             using (IRedisClient con = RedisManage.ClientManager.GetClient())
 3             {
 4                 //存数据
 5                 con.Set<int>("age", 18);
 6                 Dictionary<string, string> dic = new Dictionary<string, string>();
 7                 dic["yzk"] = "test";
 8                 con.Set<Dictionary<string, string>>("dic", dic);
 9
10             }
 

 4.读取数据

 
1  using (IRedisClient con = RedisManage.ClientManager.GetClient())
2             {
3                 //取数据
4                 int age = con.Get<int>("age");
5                 Console.WriteLine(age);
6                 Dictionary<string, string> dic = con.Get<Dictionary<string, string>>("dic");
7                 Console.WriteLine(dic["yzk"]);
8
9             }
 

5. 支持写入数据设置超时:

bool Set<T>(string key, T value, DateTime expiresAt);

第三个参数DateTime,可以指定数据到期时间,到期数据将不存在服务器里


四、在项目解决的一些问题

1.同一个用户名只能在一台电脑或者一个浏览器中登陆,严格来说是一个Session,Web中很难区别是否是同一台电脑,

 这里的本质是使用用户名与SessionID进行键值对关联,存储到Redis中。

技术思路:在编写用户登陆代码处,将用户名(唯一)做为键,当前的SessionId作为值,存储到Redis数据库中。然后在每次请求页面时,

就把当前SessionID取出,在把对应的Redis中的SessionId取出,两者进行比较,假如这时用户已经换了浏览器登陆,那么Redis中对应的SessionID将覆盖了,

两者不对等,那么就证明该用户在其他地方进行了登陆。

俗语:但凡登陆就要用当前SessionID覆盖Redis中的SessionID,只要每当请求,发现当前SessionID与Redis中的不同,该页面就要清除登陆,清除Session,说明这个用户去了其他位置登陆了。

代码参考,登录成功某处:

 
1   context.Session["user"] = model;
2             //用户名与SessionId键值对关系存储到Redis中
3             using (var con = RedisManage.ClientManager.GetClient())
4             {
5                 //存数据
6                 con.Set<string>(model.username,context.Session.SessionID);
7
8             }
 

由于,用户每次请求页面都要检查,我将此操作配置到Global文件中:

参考代码:

 
 1 using Common;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Web;
 6 using System.Web.Security;
 7 using System.Web.SessionState;
 8 using Model;
 9 namespace rupeng
10 {
11     public class Global : System.Web.HttpApplication
12     {
13
14         public override void Init()
15         {
16             base.Init();
17             //必须到Init()中监听
18             //每个需要Seesion页面启动都会执行AcquireRequestState事件
19             //AcquireRequestState事件执行的时候Session已经准备好了
20             this.AcquireRequestState += Global_AcquireRequestState;
21         }
22
23         void Global_AcquireRequestState(object sender, EventArgs e)
24         {
25             if (HttpContext.Current.Session==null)
26             {
27                 return;
28             }
29
30
31             if (Context.Session["user"]==null)   //排除用户没有登录
32             {
33                 return;
34             }
35             user_guest model= Context.Session["user"] as user_guest;
36             using (var con = RedisManage.ClientManager.GetClient())
37             {
38                 string redis_sId = con.Get<string>(model.username);
39
40                 //发现不对等,用户在其他位置登陆了,销毁当前Seesion
41                 if (redis_sId!=Context.Session.SessionID)
42                 {
43                     Context.Session.Clear();
44                     Context.Session.Abandon();
45                 }
46
47             }
48
49
50         }
51
52
53         protected void Application_Start(object sender, EventArgs e)
54         {
55
56         }
57
58         protected void Session_Start(object sender, EventArgs e)
59         {
60
61         }
62
63         protected void Application_BeginRequest(object sender, EventArgs e)
64         {
65
66         }
67
68         protected void Application_AuthenticateRequest(object sender, EventArgs e)
69         {
70
71         }
72
73         protected void Application_Error(object sender, EventArgs e)
74         {
75
76         }
77
78         protected void Session_End(object sender, EventArgs e)
79         {
80
81         }
82
83         protected void Application_End(object sender, EventArgs e)
84         {
85
86         }
87     }
88 }
 

.net通过代码发送邮件

 

关键代码:

需要引用命名空间:

using System.Net.Mail;
using System.Net;

 1    MailMessage mailObj = new MailMessage();
 2
 3             mailObj.From = new MailAddress("mayun@qq.com"); //发送人邮箱地址
 4             mailObj.To.Add("mahuateng@qq.com");   //收件人邮箱地址
 5             mailObj.Subject = "账户激活";    //主题
 6             mailObj.Body = mailbody;    //正文,
 7             mailObj.IsBodyHtml = true; //表示正文内容是HTML
 8
 9             SmtpClient smtp = new SmtpClient();
10             smtp.Host = "smtp.sina.cn";         //smtp服务器名称
11             smtp.UseDefaultCredentials = true;
12             smtp.Credentials = new NetworkCredential("mayun@qq.com", "pwd");  //发送人的登录名和密码
13             smtp.Send(mailObj);                

注意细节:

一、smtp

SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组由于源地址到目的地址传送邮件的规则。

在使用时,要保证邮件里该项服务已经开启!新浪邮箱设置例如:

二、出现 “不允许使用邮箱名称。 服务器响应为:Envolope sender mismatch with login user..” 的错误

 

Log4net (Log for .net)

 

Log4net (Log for .net)

开源的记录日志的组件,是从java的Log4J移植到.net


日志文件存放的位置

在项目新建“App_Code”和“App_Data”,该文件夹客户端无法访问


滚动日志文件

例:每个日志最多100MB,一个日志满了,就新建一个日志保存,最多可以容纳10个日志文件,超过10个文件,覆盖最老的日志文件


日志级别

日志对象根据你使用的级别,匹配webconfig设置日志级别,如果使用的级别大于配置的级别,那么才把日志内容记录到日志文件中。

常用级别项:Fatal>Error>Warn>Debug ,即 严重>错误>警告>调试。


在Web.config中配置Log4net

一、

在<configuration>节点下新建节点< configSections>节点

然后在< configSections>下新增:

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />

注意:

二、

然后

<configuration>

根节点下新增:

 1  <log4net>
 2     <!-- OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL -->
 3     <!-- Set root logger level to ERROR and its appenders -->
 4     <root>
 5       <level value="ERROR" />
 6       <appender-ref ref="RollingFileTracer" />
 7     </root>
 8     <!-- Print only messages of level DEBUG or above in the packages -->
 9     <appender name="RollingFileTracer" type="log4net.Appender.RollingFileAppender,log4net">
10       <param name="File" value="App_Data/Log/" />
11       <param name="AppendToFile" value="true" />
12       <param name="RollingStyle" value="Date" />
13       <param name="MaxSizeRollBackups" value="10" />
14       <param name="MaximumFileSize" value="1MB" />
15       <param name="DatePattern" value="&quot;Logs_&quot;yyyyMMdd&quot;.txt&quot;" />
16       <param name="StaticLogFileName" value="false" />
17       <layout type="log4net.Layout.PatternLayout,log4net">
18         <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
19       </layout>
20     </appender>
21   </log4net>

三、

在Global文件的Application_Start中写(程序启动的时候读取配置)

log4net.Config.XmlConfigurator.Configure();

四、

在编写程序时,如何使用

ILog logger = LogManager.GetLogger(typeof(当前类名));

logger.Error("记录日志的内容",);

注意:Error方法代表log对象调用Error的级别写入到日志文件中,如果配置文件配置的级别高于Error,那么内容将不会记录到日志文件中


项目中常规使用处

在Global文件配置

Application_Error中记录未处理异常

protected void Application_Error(object sender, EventArgs e)

{

ILog log = LogManager.GetLogger(typeof(Global));

log.Error("系统发生未处理异常",Context.Error);

}


Web.config范例

 1 <?xml version="1.0" encoding="utf-8"?>
 2
 3 <!--
 4   有关如何配置 ASP.NET 应用程序的详细信息,请访问
 5   http://go.microsoft.com/fwlink/?LinkId=169433
 6   -->
 7
 8 <configuration>
 9
10   <!--配置Log4net-->
11   <configSections>
12     <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
13   </configSections>
14
15     <system.web>
16       <compilation debug="true" targetFramework="4.5" />
17       <httpRuntime targetFramework="4.5" />
18
19
20
21     </system.web>
22
23   <!--连接字符串-->
24   <connectionStrings>
25     <add connectionString="Data Source=.;Initial Catalog=repengDb;User ID=sa;Password=84879825" name="sqlCon" />
26   </connectionStrings>
27
28
29
30
31
32   <log4net>
33     <!-- 日志级别类型: OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL -->
34     <root>
35       <level value="ERROR" />  <!--设置日志写入级别-->
36       <appender-ref ref="RollingFileTracer" />
37     </root>
38
39     <!-- Print only messages of level DEBUG or above in the packages -->
40     <appender name="RollingFileTracer" type="log4net.Appender.RollingFileAppender,log4net"><!-- type= 设置日志的记录类型,这里采用的是滚动日志-->
41
42       <!--日志信息存储到哪个文件夹下-->
43       <param name="File" value="App_Data/Log/" />
44
45       <!--是否将内容追加到日志文件-->
46       <param name="AppendToFile" value="true" />
47
48       <!--根据日期作为日志滚动-->
49       <param name="RollingStyle" value="Date" />
50
51       <!--最大容纳10个日志文件-->
52       <param name="MaxSizeRollBackups" value="10" />
53
54       <!--一个日志文件的大小-->
55       <param name="MaximumFileSize" value="1MB" />
56
57       <!--日志文件命名方式-->
58       <param name="DatePattern" value="&quot;Logs_&quot;yyyyMMdd&quot;.txt&quot;" />
59
60       <!--有很多节点,需要时根据需求查找配置,没必要全都记住。。。。-->
61       <param name="StaticLogFileName" value="false" />
62       <layout type="log4net.Layout.PatternLayout,log4net">
63         <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n" />
64       </layout>
65     </appender>
66   </log4net>
67
68
69 </configuration>

使用GDI技术创建ASP.NET验证码

 
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Web;
  5 using System.Drawing;
  6 using System.IO;
  7 using System.Text;
  8 using System.Text.RegularExpressions;
  9 using System.Drawing.Drawing2D;
 10 using System.Drawing.Imaging;
 11 using System.Web.SessionState;
 12 namespace yzm
 13 {
 14     /// <summary>
 15     /// yzm 的摘要说明
 16     /// </summary>
 17     public class yzm : IHttpHandler,IRequiresSessionState
 18     {
 19         private const string yzmName = "yzm";
 20
 21         public void ProcessRequest(HttpContext context)
 22         {
 23
 24             //表头需要修改 MIME类型为:image/jpeg,因为此页面要以图片流的形式响应给客户端
 25             context.Response.ContentType = "image/jpeg";
 26
 27
 28
 29             //获取验证码的内容
 30             string code = CreateCode(context, 4);
 31
 32
 33             //将内容保存到Seesion,在效验时取客户端提交的值在服务器里与此Session内容验证
 34             context.Session[yzmName] = code;
 35
 36
 37
 38
 39             /*
 40              绘制样式
 41              */
 42             using (Bitmap map =new Bitmap (120,50)) //创建位图对象,构造函数指定宽、高
 43             using(Graphics grap=Graphics.FromImage(map)) //创建绘图的图纸
 44
 45             {
 46                 grap.Clear(Color.White);  //让图纸为白色
 47
 48                 /*创建一个矩形对象
 49                     构造函数(x坐标,y坐标,宽,高)
 50                  * 该参数的填写,其实是填满了整个图纸
 51                  */
 52                 Rectangle rec = new Rectangle(0,0,map.Width,map.Height);
 53
 54                 /*创建了一个画线性,并且颜色是渐变的一个画笔对象
 55                  构造函数:   画在矩形对象上,起始颜色,结束颜色,角度,是否比例
 56                  */
 57                 using (LinearGradientBrush brush = new LinearGradientBrush(rec,Color.Blue,Color.Red,1.2f,true))
 58                 using(  Font font = new Font("隶书", 20, FontStyle.Strikeout))   //为验证码指定字体
 59                 {
 60                     grap.DrawString(code, font, brush, 3, 8);  //画到图纸上,传入相应对象:内容、字体、画笔、坐标
 61                 }
 62
 63                 //画一些随机的直线,增加验证码识别度
 64                 Random random = new Random();
 65                 for (int i = 0; i < 18; i++)
 66                 {
 67                     //第一个点
 68                     int x1 = random.Next(map.Width);
 69                     int y1 = random.Next(map.Height);
 70
 71                     //第二个点
 72                     int x2 = random.Next(map.Width);
 73                     int y2 = random.Next(map.Height);
 74
 75                     /*在画纸上绘画线
 76                      * 构造函数:
 77                      * pen:创建画笔(画笔颜色,宽度)
 78                        x1, y1, x2, y2 随机生成 两个坐标点连成一条线
 79                      */
 80                     grap.DrawLine(new Pen(Color.FromArgb(random.Next()), 3), x1, y1, x2, y2);
 81
 82                 }
 83
 84
 85                 //保存到响应对象的流中 ,返回给客户端一个jpg格式图片
 86                 map.Save(context.Response.OutputStream, ImageFormat.Jpeg);
 87
 88
 89
 90
 91             } //--end
 92
 93
 94
 95         }
 96
 97
 98
 99         /// <summary>
100         /// 用txt里的汉字作为验证码数据源
101         /// </summary>
102         private string Get_yzm_DataSource(HttpContext context)
103         {
104             StringBuilder sb = new StringBuilder();
105
106             string path = context.Server.MapPath(@"~\yzmDataSource.txt");
107
108             using (Stream fs = new FileStream(path, FileMode.Open))
109             using (StreamReader read = new StreamReader(fs, Encoding.UTF8))
110             {
111                 string len;
112                 while ((len = read.ReadLine()) != null)
113                 {
114                     Regex rg = new Regex("[\\W\\s]+");
115                     sb.Append(rg.Replace(len, ""));
116                 }
117             }
118
119
120             return sb.ToString();
121         }
122
123
124         /// <summary>
125         /// 随机生成,指定个数的验证码内容
126         /// </summary>
127         /// <returns></returns>
128         private string CreateCode(HttpContext context, int length)
129         {
130             string str = Get_yzm_DataSource(context);
131
132             Random ran = new Random();
133
134
135
136             string code = "";
137             for (int i = 0; i < length; i++)
138             {
139                 int sjIndex = ran.Next(0, str.Length);
140                 code += str[sjIndex];
141             }
142
143             return code;
144         }
145
146
147         public bool IsReusable
148         {
149             get
150             {
151                 return false;
152             }
153         }
154     }
155 }

Razor模板引擎 (RazorEngine)

 

Razor模板引擎不仅在ASP.NET MVC中内置了Razor模板引擎,还有一个开源的RazorEngine,

这样以来我们可以在非ASP.NET MVC项目中使用Razor引擎,甚至在控制台,WinForm项目中都可以使用。

文件的创建

文件是一个后缀名为cshtml的文件,如果在非MVC项目中创建Razor文件,可以新建一个html,把后缀名该为cshtml。


RazorEngine使用初体验

一、前台:

二、后台代码

解释:

使用RazorEngine需提前在项目中引入它的程序集文件dll。

后台代码首先获得cshtml文件将其读成文本文件,在通过Razor.Parse将文本解析为,含义为Razor的模板,将其展出。访问的话应访问代码页面,cshtml只是一个展示模板,等待代码动态绘制内容使用cshtml模板展示.


Razor.Parse()方法

1.通过第二个参数,可以传一个object类型的对象,到前台(cshtml)模板。

string razor = RazorEngine.Razor.Parse(html, new { name = "zs", age = 12 });

注意:传入对象的访问权限,需为public

前台输出这个对象的值:

<h1>@Model.name</h1>

<h2>@Model.age</h2>


RazorEngine原理

1.net在编译的时候会把.cshtml文件生成一个动态程序集,每次调用,就会每次生成一个不重复的动态程序集,这样看出会给服务器造成不容小视的压力。

解决办法:

Razor.Parse()方法的第三个参数cacheName

如果传入一个cacheName(名字随意),一旦编译成功,下次会使用缓存,不会重复生成新的动态程序集。

2.关于cacheName的问题

从上面的原理得知,如果给Razor.Parse()传入cacheName,下次调用可以使用缓存,那么会产生一个问题,cshtml文件如果发生了修改,如果还去调用缓存的话,那么结果会不如意。

解决办法:

将cacheName的值转为动态的:

1.根据文件名+修改时间

2.文件的MD5值作为cacheName

3.文件流转换为新的文本字符串(获取文件内容)

........

cacheName细节:

即使cacheName写成一个固定的值,当cshtml发生改变的时候Parse()方法执行后的结果,也会是发生改变的内容。


自己封装一个Razor.Parse()方法

 1     /// <summary>
 2         /// 自己封装一个Razor.Parse()方法
 3         /// </summary>
 4         /// <param name="context">上下文对象</param>
 5         /// <param name="cshtmlPath">.cshtml文件的相对路径</param>
 6         /// <param name="obj">要传入的对象参数</param>
 7         /// <returns>返回一个解析过的Razor模板字符串</returns>
 8         private string RazorParse(HttpContext context, string cshtmlPath,params object[] obj)
 9         {
10             //获得.cshtml文件的绝对路径
11             string path = context.Server.MapPath(cshtmlPath);
12             //通过路径将文件读成文本
13             string txt = File.ReadAllText(path);
14
15             //为模板准备一个缓冲,根据文件的修改时间动态组合
16             string cacheName = path + File.GetLastWriteTime(path);
17
18             //根据需求是否要传入对象参数,在调用Razor.Parse方法返回解析好的Razor模板
19             return obj.Length > 0 ? RazorEngine.Razor.Parse(txt, obj[0], cacheName) : RazorEngine.Razor.Parse(txt, cacheName);
20
21         }

HtmlEncodeString()方法

在往模板传入字符串的格式,如果为html格式,该方法会将其转义,在模板显示字符串本身,而不会被模板解析为html标签

代码:

public static HtmlEncodedString Test1()

{

return new HtmlEncodedString("<input type='text' />");

}


RawString()方法

可以将类似于html的字符串,传入前台模板,可以被解析标签相应的含义

代码:

public static RawString Test2()

{

return new RawString("<input type='text' />");

}


Razor模板调用外部方法(在.cshtml模板页上调用在后台用C#写好的一个方法)

1.在.cshtml顶部引入方法的命名空间

@using 命名空间名称

2.调用

@类名.方法() ,不需要";"号。  如:@Handler1.Test1()

业务实例

通过外部方法生成一个Checked标签

 1     public static RawString CreateChecked_input(string id,bool isChecked)
 2
 3         {
 4
 5             StringBuilder sb = new StringBuilder();
 6
 7             sb.Append("<input type='checkbox' id=" + id).Append("  checked="+ (isChecked==true?"checked":"")).Append(" />");
 8
 9
10             return new RawString(sb.ToString());
11
12
13
14         }

调用

 1 @using Demo.Razor
 2 <!DOCTYPE html>
 3 <html xmlns="http://www.w3.org/1999/xhtml">
 4 <head>
 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 6     <title></title>
 7 </head>
 8 <body>
 9
10      @Handler1.CreateChecked_input("t1", true)
11
12 </body>
13 </html>

总结:因为在后台很多数据时动态读取数据库的信息而组成的,将繁琐的拼接封装在后台,前台页面清晰,而封装的方法还可以重复利用到其他业务中


.Net程序员应该掌握的正则表达式

 

Regular Expression

Net程序员必然要掌握正则的核心内容:匹配提取替换常用元字符

正则表达式是用来进行文本处理的技术,是语言无关的,在几乎所有语言中都有实现。


常用元字符

.:代表除了换行之外的任意字符,一个字符占位。

*:代表前面的子表达式出现0次或者多次。如果需要*代表的子表达式是多个字符,就将多个字符用()包含。

+:代表前面的表达式出现1次或者多次。

?:代表前面的表达式出现0次或者出现1次。

{n}:代表前面的子表达式要出现n次。

^代表开始$代表结束

{n,m}:代表前面的子表达式最少出现n次,最多出现m次。

{n,}:说明前面的子表达式最少出现n次,最多没有限制。

[]:输入的内容必须是在括号内有的一个字符。

():改变优先级、分组。

\d:代表0-9的数字。

\D:代表非数字。

\w:代表0-9a-zA-Z_中文   (经过实例证明C#里\w包含中文,JavaScript里不包含中文)

\W:代表其他特殊字符(除了0-9a-zA-Z_中文)

\s:代表看不到的字符,如:回车、空格、制表符。

\S:代表所有可见字符

项目实战:

1.运用场合:不包含某些特定的字符情况下

((?![@:]).)+:代表不是@和:的字符。

2.匹配中文

[\u4E00-\u9FFF]

 


正则表达式进行匹配的原则:

1.(有没有)只关注是否存在,而不关注它的位置,也就意味着只需要能够匹配其中一个就可以 。

2.贪婪模式:如果找到了能匹配的字符,那么他还继续往下匹配尽可能多的字符,只到最后


.net中的正则表达式

正则表达式在.net中就是用字符串来表示,这个字符串格式比较特殊,无论多么特殊,在C#语言看来都是普通的字符出,具体什么含义由Regex类内部进行语法分析。

常用的4种情况:

  1. 判断是否匹配(是否有):Regex.IsMatch("字符串","正则表达式");
  2. 字符串提取:Regex.Match("字符串","要提取的字符出的正则表达式"); ——只能提取一个(提取一次)。
  3. 字符串提取(循环提取所有):Regex.Matches(),可以提取所有匹配的字符串。
  4. 字符串替换:Regex.Replace("字符串","正则","替换内容");

提取只有一个匹配项的字符串,进行分组,提取。

string str = "tiantianjcx@qq.com";

Match match = Regex.Match(str, @"^(\w+)[@](\w+)[.](\w+)$");

if (match.Success) //匹配成功

{

Console.WriteLine(match.Groups[0].Value);  //结果:tiantianjcx@qq.com

Console.WriteLine(match.Groups[1].Value);  //结果:tiantianjcx

Console.WriteLine(match.Groups[2].Value);  //结果:qq

Console.WriteLine(match.Groups[3].Value);  //结果:com

}


JavaScript正则表达式

创建:

字面值:var regex=/元字符/;

构造函数:var regex=new RegExp("元字符");

匹配:

bool 正则表达式对象.test("字符串");

var regex = /\d*/;

alert(regex.test("122"));   //true

提取:

像数组的对象 正则表达式对象.exec("字符串");

这个对象的[0]是匹配到的结果,[1],[2]....是各个组

1.单个提取

2.单个提取并分组

var str = "我的邮箱是tiantianjcx@qq.com";

var regex = /(\w+)@(\w+[.]\w{2,3})/;

var arr= regex.exec(str);

alert(arr.length);

for (var i = 0; i < arr.length; i++) {

alert(arr[i]);

}

3.循环提取

var str = "我的邮箱是tiantianjcx@qq.com,你的是sukun@163.com号吧";

var regex = /\w+@\w+[.]\w{2,3}/g;

var arr = [];

var item = null;

while ((item = regex.exec(str)) != null) {

arr.push(item);

}

注意:创建正则表达式对象里的字符必须加上g(全局匹配),否则会陷入是循环

4.替换

javascript的正则替换,是使用String的Replace()方法将正则表达式作为参数处理。

var str = "a--b---------c---------------d---------------e---------------f";

str = str.replace(/-+/g,"-");

var str = "2016年7月26日";

str = str.replace(/(\d+)年(\d+)月(\d+)日/,"$1-$2-$3");


自测题:

 1     /*
 2              192.168.10.5[port=21,type=ftp]”,这个字符串表示IP地址为192.168.10.5的服务器的21端口提供的是ftp服务,
 3              * 其中如果“,type=ftp”部分被省略,则默认为http服务。请用程序解析此字符串,然后打印出“IP地址为***的服务器的***端口提供的服务为***”
 4              */
 5
 6
 7             string str = "192.168.10.5[port=21,type=ftp]";
 8             Match match = Regex.Match(str, @"^(\d{1,3}[.]?\d{1,3}[.]?\d{1,3}[.]?\d{1,3}[.]?)[[]\w+=(\w+),?\w*=?(\w*)[]]$");
 9             if (match.Success) //匹配成功
10             {
11                 Console.WriteLine("IP地址为:{0}", match.Groups[1].Value);
12                 Console.WriteLine("端口::{0}", match.Groups[2].Value);
13                 if (string.IsNullOrEmpty(match.Groups[3].Value))
14                 {
15                     Console.WriteLine("端口提供的服务为:http");
16                 }
17                 else
18                 {
19                     Console.WriteLine("端口提供的服务为:{0}", match.Groups[3].Value);
20                 }
21             }
 1             /*
 2              读取网站的内容,用正则表达式匹配邮箱,并提取
 3              * 注意:做循环匹配不能加"^"和$(开始和结束),否则就只能匹配一项
 4              */
 5             string path = @"E:\视频大全\传智播客.NET2014.3.26-07.09期\6--2014-4-03 文件操作和正则表达式\资料\正则表达式-素材\正则表达式\大家留下email交友吧_email_天涯社区.htm";
 6
 7             string txt = File.ReadAllText(path);
 8
 9             MatchCollection arr = Regex.Matches(txt, @"[a-zA-Z0-9]+[@][a-zA-Z0-9]+[.]+[a-zA-Z]{2,3}");
10
11             using (Stream fs = new FileStream("E:\\mail.txt", FileMode.Create))
12             using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
13             {
14
15                 for (int i = 0; i < arr.Count; i++)
16                 {
17                     Match match = arr[i];
18                     sw.WriteLine(match.Groups[0].Value);
19
20                 }
21             }

MVC的验证(模型注解和非侵入式脚本的结合使用) .Net中初探Redis .net通过代码发送邮件 Log4net (Log for .net) 使用GDI技术创建ASP.NET验证码 Razor模板引擎 (RazorEngine) .Net程序员应该掌握的正则表达式的更多相关文章

  1. MVC的验证(模型注解和非侵入式脚本的结合使用)

    @HtmlHrlper方式创建的标签,会自动生成一些属性,其中一些属性就是关于验证 如图示例: 模型注解 通过模型注解后,MVC的验证,包括前台客户端,后台服务器的验证,MVC统统都做了包含,即使用户 ...

  2. 使用phpAnalysis打造PHP应用非侵入式性能分析器

    使用phpAnalysis打造PHP应用非侵入式性能分析器,查找PHP性能瓶颈. 什么是phpAnalysis phpAnalysis是一款轻量级非侵入式PHP应用性能分析器,适用于开发.测试及生产环 ...

  3. Razor - 模板引擎 / 代码生成 - RazorEngine

    目录 Brief Authors Official Website RazorEngine 的原理 - 官方解释 安装记录 Supported Syntax (默认实现支持的语法) 测试记录 - ca ...

  4. Razor模板引擎 (RazorEngine)

    Razor模板引擎不仅在ASP.NET MVC中内置了Razor模板引擎,还有一个开源的RazorEngine, 这样以来我们可以在非ASP.NET MVC项目中使用Razor引擎,甚至在控制台,Wi ...

  5. Razor模板引擎

    Razor模板引擎 阅读目录 一.简介 二.非Mvc中使用Razor 三.总结 回到目录 一.简介 在MVC以外的场景中,我们往往需要完成一些模板引擎生成代码或页面的工作:在以前我们一般常用的有Raz ...

  6. 脱离MVC使用Razor模板引擎

    关于Razor模板引擎 1.简介 模板引擎:Razor.Nveocity.Vtemplate.Razor有VS自动提示.使用起来会方便一点. 但是Razor大多是在MVC下使用的. 那么如何在非MVC ...

  7. Asp.net MVC Razor模板引擎技巧分享

    Razor是Asp.net MVC中新的默认模板类型, 语法简单易用.这篇文章不涉及Razor的语法,主要介绍Razor的一些在MVC项目中的使用技巧,以及脱离MVC环境下,如何使用Razor. 阅读 ...

  8. [转]MVC Razor模板引擎 @RenderBody、@RenderPage、@RenderSection及Html.RenderPartial、Html.RenderAction

    本文参考自下面文章整理 MVC Razor模板引擎 @RenderBody.@RenderPage.@RenderSection及Html.RenderPartial.Html.RenderActio ...

  9. MVC Razor模板引擎输出HTML或者生产HTML文件

    以前做CMS的时候都会根据模板来生成输出HTML或者生成HTML文件. 常用的引擎有VTemplate.NVelocity等等,这个我就布做介绍了. 这里我想说的是.当mvc出现Razor模板引擎的时 ...

随机推荐

  1. js实现音量拖拽的效果模拟

    <!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>js ...

  2. CentOS 7的docker安装初始化

    1: 安装必要的一些系统工具 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 2: 添加软件源信息 添加阿里源这样下载 ...

  3. github 获取 token

    登录github 地址:https://github.com 点击settings 在点击Developer settings 继续 继续 描述栏随意写  复选框是token的权限 都选上吧 点击红框 ...

  4. HDU 1242 Rescue 营救天使

    Description Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The prison is describe ...

  5. Codeforces 879C/878A - Short Program

    传送门:http://codeforces.com/contest/879/problem/C 本题是一个位运算问题——位运算的等价变换. 假设位运算符“&”“|”“^”是左结合的,且优先级相 ...

  6. xtu summer individual 4 C - Dancing Lessons

    Dancing Lessons Time Limit: 5000ms Memory Limit: 262144KB This problem will be judged on CodeForces. ...

  7. [luoguP2216] [HAOI2007]理想的正方形(二维单调队列)

    传送门 1.先弄个单调队列求出每一行的区间为n的最大值最小值. 2.然后再搞个单调队列求1所求出的结果的区间为n的最大值最小值 3.最后扫一遍就行 懒得画图,自己体会吧. ——代码 #include ...

  8. SQL中distinct的用法(四种示例分析)

    在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只 用它来返回不重复记录的条数,而不是用它来返回不重记录的 ...

  9. make only output error/warning message( 编译时,只输出错误信息和警告信息)

    make > /dev/null 这样,正常的信息被重定向输出到/dev/null,错误和警告信息会输出到标准错误设备(standard error,相对于标准输入/输出设备来说).

  10. CodeForces 595A Vitaly and Night

    水题. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> u ...