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=""Logs_"yyyyMMdd".txt"" /> 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=""Logs_"yyyyMMdd".txt"" /> 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种情况:
- 判断是否匹配(是否有):Regex.IsMatch("字符串","正则表达式");
- 字符串提取:Regex.Match("字符串","要提取的字符出的正则表达式"); ——只能提取一个(提取一次)。
- 字符串提取(循环提取所有):Regex.Matches(),可以提取所有匹配的字符串。
- 字符串替换: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 }