ASP筛选时间段,将一段网址不要的部分删掉

网页上如何实现按条件进行筛选功能【asp.net吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:38,017贴子:
网页上如何实现按条件进行筛选功能收藏
达内asp.net培训月末开班,先申请试听asp.net课程再选择.业余/脱产班任选!达内asp.net培训:达内美国上市上市公司-大机构就业才有保障!
多条件查询
同求,楼主这个问题解决了吗?
每组内是单选,就是每组内只能选一个,吧这些选择都做成链接形式的,链接的时候传递参数到查询页面,然后就是SQL组合查询就可以了
就是查询的sql语句的拼接而已
登录百度帐号推荐应用&&&&&&& 在网站开发中,需要注意的一个问题就是防范XSS攻击,Asp.net mvc中已经自动为我们提供了这个功能。用户提交数据时时,在生成Action参数的过程中asp.net会对用户提交的数据进行验证,一旦发现提交的数据中包含了XSS攻击的代码,就会抛出异常,用户在这时候就会看到一个出错页面。这种默认的行为保证了网站的安全性,但是对于用户体验来说却不够友好,所以大多数人都希望对用户进行提示,或者对提交的数据进行过滤,移除掉XSS攻击的代码。
&& 对于此类问题,网上有很多人问过,通过百度搜索出来的解决方法好多都只提到了&关闭页面数据验证&。确实,关闭了页面数据验证后,用户提交的任何数据都会到达服务器端的处理程序,在asp.net mvc中这一点可以通过在model的相应属性上附加AllowHtmlAttribute或者在Action上附加ValidateInputAttribute(false)来实现。但是比关闭页面数据验证更重要的一点是,关闭之后,这个数据验证和处理的重担就要由程序员来承担了。
&&&&&&&& 解决这个问题最直接的方法就是在每一个要处理提交数据的Action的开始,对相应的参数进行过滤,对于XSS攻击代码的过滤,可以使用微软发布的名为AntiXss的类库,通过Nuget可以获取该类库,在我的解决方法中也是使用此类库进行过滤的。
&&&&& 我新建了一个Asp.net mvc项目进行演示,只有一个Controller名字为PersonController,一个Model,名字为PersonModel,PersonController中只有两个Action,全部代码如下。
public class PersonModel
[AllowHtml]
//别忘了AllowHtmlAttribute,要不然提交数据就报错了
public string Name { get; set; }
public int Age { get; set; }
public class PersonController : Controller
public ActionResult Index()
return View();
public ActionResult Save(PersonModel model)
//Sanitizer为AntiXss类库提供的静态类,用于过滤XSS代码
model.Name = Sanitizer.GetSafeHtmlFragment(model.Name);
//保存到数据库中
return Content("Success");
视图文件Index.cshtml内容如下
@model AntiXss.Models.PersonModel
ViewBag.Title = "Index";
&h2&Index&/h2&
@using (Html.BeginForm("Save","Person",FormMethod.Post))
@Html.LabelFor(model=&model.Name);
@Html.EditorFor(model=&model.Name);
@Html.LabelFor(model=&model.Age)
@Html.EditorFor(model=&model.Age)
&input type="submit" value="submit"/&
&&&&&&& 这样的代码无疑是可以达到我们过来XSS攻击的目的的,但是在实际项目中,Controller往往有数十个,Action的数目更是成百上千,而且ViewModel的属性又往往很多,如果我们按照上面的方式逐个Action的逐个Model的属性进行处理,代码会变得又臭又长,而且还容易遗漏。使用这种方式来进行过滤实在是一种自虐行为呀。
&&&&&& 优秀的程序员都是懒汉,对于这种繁琐的体力劳动,一定要想方设法地避免。在asp.net mvc中,给我们提供了很多工具以实现aop编程,最常用的就是各种Filter了,所以在解决此问题时,我就想是否可以利用asp.net mvc提供的aop编程来实现XSS过滤,经过思考和翻阅蒋金楠的《ASP.NET MVC4框架揭秘》,最终找到了一种较好的解决方式,就是通过ValidationAttribute来实现XSS攻击代码过滤。
&&&&& ValidationAttribute是所有验证属性的基类,RangeAttribute, RequiredAttribute, StringLengthAttribute都是它的子类,这个类的中包有一个名为IsValid的方法,来对数据进行验证,方法声明如下:
protected virtual ValidationResult IsValid(Object value, ValidationContext validationContext)
&&&&&&& 参数value即为要验证的对象,参数ValidationContext为验证上下文,此类包含了较多的信息,比较重要的有属性ObjectInstance和MemberName。
其中ValidationContext的ObjectInstance属性可获取要验证的对象,而MemberName可获取或设置要验证的成员名称。这里要进行一下解释,按照我上面的说法,value是要验证的对象,ValidationContext.ObjectInstance也是要验证的对象,难道它们二者是同一个对象么,答案是No,(不是我故意要把他们表达成一个意思,而是MSDN太坑,本段开头摘自MSDN),对于我们示例中的PersonModel类型来说,由于其是一个复杂类型,所以最终的验证会落到它的各个属性上,假如要验证属性Name,参数value即为属性Name的值,而ValidationContext.ObjectInstance则为一个PersonModel的实例,ValidationContext.MemberName的值按照MSDN的解释,应该是一个字符串&Name&;这下大家清楚二者的区别了吧。我之所以说假如要验证属性Name,是因为属性Name上现在还没有任何的验证特性(AllowHtmlAttribute不是一个验证特性)。
&&&&&&& 到这里我想可能有的人已经想到我要怎么做了,在这里我获得了属性值value,也获得了包含该属性的实例ValidationContext.ObjectInstance,接下来我要做的就是将该属性值进行修改就可以了,修改属性值可以通过反射轻松实现,所以我的用于过滤XSS攻击代码的自定义验证属性就写出来了,如下
public class AntiXssAttribute :ValidationAttribute
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
//对于XSS攻击,只需要对string类型进行验证就可以了
var str = value as string;
if (!string.IsNullOrWhiteSpace(str) &&
validationContext.ObjectInstance != null && !
string.IsNullOrWhiteSpace(validationContext.MemberName))
str = Sanitizer.GetSafeHtmlFragment(str);
PropertyInfo pi = validationContext.ObjectType.GetProperty(validationContext.MemberName,
BindingFlags.Public | BindingFlags.Instance);
pi.SetValue(validationContext.ObjectInstance,str);
//由于这个类的目的并不是为了验证,所以返回验证成功
return ValidationResult.S
&&&&&& 然后我们将这个自定义的验证特性附加到PersonModel的Name属性上(一定不要删除AllowHtmlAttribute,要不然提交包含html标签或者js代码的数据时会出错的),当用户提交数据时,asp.net在进行model验证时就会自动为我们过滤XSS攻击代码了,一切看起来都是那么的美好,可是事实并非如此!!
&&&&&& 当程序运行时,用户提交的XSS代码并没有被过滤,原因是ValidationContext.MemberName属性根本不存在,这实在是微软的一个坑,MSDN告诉我们通过这个属性可以获取或设置要验证的成员名称,可是其实自始至终根本没有代码来设置这个属性值,这个属性值一直都是null,所以要想让我们的代码顺利进行,我们要想办法给ValidationContext.MemberName赋值才可以,要给ValidationContext的这个属性赋值,自然要在实例化它的地方。对于ValidationContext对象的实例化,我在这里不赘述,因为这涉及到Asp.net mvc的模型验证机制,这一点蒋金楠的博文早就讲清楚了,而我也自认为不会讲的比他更清楚,想了解的人请阅读蒋金楠的博客 、
&&&&&&& 最终我实现了自己的AntiXssDataAnnotationsModelValidator和AntiXssDataAnnotationsModelValidatorProvider,在AntiXssDataAnnotationsModelValidator中实例化了ValidationContext对象,并且为该对象的MemberName属性赋值。
public class AntiXssDataAnnotationsModelValidator:DataAnnotationsModelValidator
public AntiXssDataAnnotationsModelValidator(ModelMetadata metadata,ControllerContext context,AntiXssAttribute attribute)
:base(metadata,context,attribute)
public override IEnumerable&ModelValidationResult& Validate(object container)
var validationContext = new ValidationContext(container ?? base.Metadata.Model, null, null);
validationContext.DisplayName = base.Metadata.GetDisplayName();
validationContext.MemberName = base.Metadata.PropertyN
ValidationResult validationResult = this.Attribute.GetValidationResult(base.Metadata.Model, validationContext);
yield break;
public class AntiXssDataAnnotationsModelValidatorProvider : DataAnnotationsModelValidatorProvider
protected override IEnumerable&ModelValidator& GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable&Attribute& attributes)
foreach (var attribute in attributes.OfType&AntiXssAttribute&())
yield return new AntiXssDataAnnotationsModelValidator(metadata,context,attribute);
&&&&&& &&& 然后记得在Global.asax中对这个AntiXssDataAnnotationsModelValidatorProvider 进行注册。
最后我又对AntiXssAttribute类进行了一点修改,为了在标记了该特性时不需要再额外地标记AllowHtmlAttribute:
public class AntiXssAttribute :ValidationAttribute, IMetadataAware{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
//对于XSS攻击,只需要对string类型进行验证就可以了
var str = value as string;
if (!string.IsNullOrWhiteSpace(str) &&
validationContext.ObjectInstance != null && !
string.IsNullOrWhiteSpace(validationContext.MemberName))
str = Sanitizer.GetSafeHtmlFragment(str);
PropertyInfo pi = validationContext.ObjectType.GetProperty(validationContext.MemberName,
BindingFlags.Public | BindingFlags.Instance);
pi.SetValue(validationContext.ObjectInstance,str);
//由于这个类的目的并不是为了验证,所以返回验证成功
return ValidationResult.S
public void OnMetadataCreated(ModelMetadata metadata)
//实际上AllowHtmlAttribute也是实现了接口IMetadataAware,在OnMetadataCreated
//中使用了如下的代码
metadata.RequestValidationEnabled = false;
最后附上完整的代码
阅读(...) 评论()原文地址:原文作者: 本文地址:本文译者:【】学习怎样使用asp.net mvc<SPAN style="COLOR: #.&public&class&StoryController&&&&&<SPAN style="COLOR: #.&{&&&&&<SPAN style="COLOR: #.&&&&&//List&published&stories&for&all&category&or&for&a&specific&category&&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&&<SPAN style="COLOR: #.&&&&&public&void&Category(string&name,&int?&page)&&&&&<SPAN style="COLOR: #.&&&&&{&&&&&<SPAN style="COLOR: #.&&&&&}&&&&&<SPAN style="COLOR: #.&&&&&&<SPAN style="COLOR: #.&&&&&//List&all&upcoming&stories&regardless&the&category&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&<SPAN style="COLOR: #.&&&&&public&void&Upcoming(int?&page)&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&//List&Stories&for&a&specific&tag&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&<SPAN style="COLOR: #.&&&&&public&void&Tag(string&name,&int?&page)&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&//List&Stories&Posted&by&a&Specific&User&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&<SPAN style="COLOR: #.&&&&&public&void&PostedBy(string&name,&int?&page)&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&//Search&the&Stories&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&<SPAN style="COLOR: #.&&&&&public&void&Search(string&q,&int?&page)&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&//View&the&details&of&a&specific&story&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&<SPAN style="COLOR: #.&&&&&public&void&Detail(int&id)&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&//Submit&a&Story&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&<SPAN style="COLOR: #.&&&&&public&void&Submit(string&storyUrl,&string&storyTitle,&int&storyCategoryId,&&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&string&storyDescription,&string&storyTags)&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&//Kigg&the&Story&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&<SPAN style="COLOR: #.&&&&&public&void&Kigg(int&storyId)&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&//Post&a&Comment&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&<SPAN style="COLOR: #.&&&&&public&void&Comment(int&storyId,&string&commentContent)&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&}&&下面这些代码片段则展示了UserController里所以的行为方法:
&&&<SPAN style="COLOR: #.&public&class&UserController&&&&&<SPAN style="COLOR: #.&{&&&&&<SPAN style="COLOR: #.&&&&&//&Login&&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&&<SPAN style="COLOR: #.&&&&&public&void&Login(string&userName,&string&password,&bool&rememberMe)&&&&&<SPAN style="COLOR: #.&&&&&{&&&&&<SPAN style="COLOR: #.&&&&&}&&&&&<SPAN style="COLOR: #.&&&&&&<SPAN style="COLOR: #.&&&&&//Logout&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&<SPAN style="COLOR: #.&&&&&public&void&Logout()&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&//&Reset&the&current&password&and&mail&back&the&new&password&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&<SPAN style="COLOR: #.&&&&&public&void&SendPassword(string&email)&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&//User&Registration&&&&<SPAN style="COLOR: #.&&&&&[ControllerAction]&&&&<SPAN style="COLOR: #.&&&&&public&void&Signup(string&userName,&string&password,&string&email)&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&}&&注意所以的行为方法都定义为public并且使用了ControllerAction 属性。在下一个版本的ASP.NET MVC中这个属性就不再需要了,所有定义为公共的方法将自动成为一个行为方法。定义筛选规则一旦Controllers的参数签名确定就应该立刻开始声明把URLs映射到Controllers的行为方法的筛选规则。前面我提到过,这些映射规则在web.config文件中的application start事件中定义。定义筛选规则的时候你要注意,把最特殊的规则放在最上面。这个就跟try/catch块中定义错误处理规则一样,要遵循从特殊到一般的原则。如果你打开Global.asax 文件查看,你会发现我们明确的定义了两个方法来定义这些规则,并且在application start事件中调用方法。这么做是因为我们不想把不同版本iis中使用的规则弄乱。在iis7中有一个很cool的特性,所有的URLs都不需要扩展名,但是在老版本的iis中URLs都需要一个.mvc的扩展名。所以,为了同事支持这个两个版本的iis,我们就要把同一个URL定义两遍,为新的iis定义一套没扩展名的,为旧的iis定义一套有扩展名的。在这里,我们在web.confitg文件里设置当前程序是跑在什么版本的iis中,然后只把当前版本iis用的那套筛选规则读出来。这样做还有一个好处,那就是我们一会要讲的单元测试。下面这些代码展现了筛选规则是如何实现的:
&&&<SPAN style="COLOR: #.&protected&void&Application_Start(object&sender,&EventArgs&e)&&&&&<SPAN style="COLOR: #.&{&&&&&<SPAN style="COLOR: #.&&&&&RegisterRoutes(RouteTable.Routes);&&&&&<SPAN style="COLOR: #.&} public&static&void&RegisterRoutes(RouteCollection&routes)&&&&&<SPAN style="COLOR: #.&{&&&&&<SPAN style="COLOR: #.&&&&&int&iisVersion&=&Convert.ToInt32(ConfigurationManager.AppSettings["IISVersion"]);&&&&&<SPAN style="COLOR: #.&&&&&&<SPAN style="COLOR: #.&&&&&if&(iisVersion&&=&<SPAN style="COLOR: #)&&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&RegisterRoutesForNewIIS(routes);&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&else&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&RegisterRoutesForOldIIS(routes);&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&} &&&&<SPAN style="COLOR: #.&private&static&void&RegisterRoutesForNewIIS(ICollection&Route&&routes)&&&&<SPAN style="COLOR: #.&{&&&&<SPAN style="COLOR: #.&&&&&var&defaults&=&new&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&controller&=&"Story",&&&&<SPAN style="COLOR: #.&&&&&&&&&action&=&"Category",&&&&<SPAN style="COLOR: #.&&&&&&&&&name&=&(string)null,&&&&<SPAN style="COLOR: #.&&&&&&&&&page&=&(int?)null&&&&<SPAN style="COLOR: #.&&&&&};&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&routes.Add(&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&new&Route&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&Url&=&"User/Login",&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&RouteHandler&=&typeof(MvcRouteHandler),&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&Defaults&=&new&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&controller&=&"User",&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&action&=&"Login"&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&);&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&routes.Add(&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&new&Route&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&Url&=&"User/Logout",&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&RouteHandler&=&typeof(MvcRouteHandler),&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&Defaults&=&new&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&controller&=&"User",&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&action&=&"Logout"&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&);&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&routes.Add(&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&new&Route&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&Url&=&"User/Signup",&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&RouteHandler&=&typeof(MvcRouteHandler),&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&Defaults&=&new&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&controller&=&"User",&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&action&=&"Signup"&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&);&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&routes.Add(&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&new&Route&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&Url&=&"User/SendPassword",&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&RouteHandler&=&typeof(MvcRouteHandler),&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&Defaults&=&new&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&controller&=&"User",&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&action&=&"SendPassword"&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&);&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&routes.Add(&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&new&Route&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&Url&=&"Story/Detail/[id]",&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&RouteHandler&=&typeof(MvcRouteHandler),&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&Defaults&=&new&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&controller&=&"Story",&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&action&=&"Detail"&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&);&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&routes.Add(&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&new&Route&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&Url&=&"Story/Upcoming/[page]",&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&RouteHandler&=&typeof(MvcRouteHandler),&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&Defaults&=&new&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&controller&=&"Story",&&&<SPAN style="COLOR: #0.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&action&=&"Upcoming"&&&<SPAN style="COLOR: #1.&&&&&&&&&&&&&&&&&&&&&&&&&}&&&<SPAN style="COLOR: #2.&&&&&&&&&&&&&&&&&&&&&}&&&<SPAN style="COLOR: #3.&&&&&&&&&&&&&&&&&);&&&<SPAN style="COLOR: #4.&&&&<SPAN style="COLOR: #5.&&&&&routes.Add(&&&<SPAN style="COLOR: #6.&&&&&&&&&&&&&&&&&&&&&new&Route&&&<SPAN style="COLOR: #7.&&&&&&&&&&&&&&&&&&&&&{&&&<SPAN style="COLOR: #8.&&&&&&&&&&&&&&&&&&&&&&&&&Url&=&"Story/Search/[q]/[page]",&&&<SPAN style="COLOR: #9.&&&&&&&&&&&&&&&&&&&&&&&&&RouteHandler&=&typeof(MvcRouteHandler),&&&<SPAN style="COLOR: #0.&&&&&&&&&&&&&&&&&&&&&&&&&Defaults&=&new&&&<SPAN style="COLOR: #1.&&&&&&&&&&&&&&&&&&&&&&&&&{&&&<SPAN style="COLOR: #2.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&controller&=&"Story",&&&<SPAN style="COLOR: #3.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&action&=&"Search"&&&<SPAN style="COLOR: #4.&&&&&&&&&&&&&&&&&&&&&&&&&}&&&<SPAN style="COLOR: #5.&&&&&&&&&&&&&&&&&&&&&}&&&<SPAN style="COLOR: #6.&&&&&&&&&&&&&&&&&);&&&<SPAN style="COLOR: #7.&&&&<SPAN style="COLOR: #8.&&&&&routes.Add(&&&<SPAN style="COLOR: #9.&&&&&&&&&&&&&&&&&&&&&new&Route&&&<SPAN style="COLOR: #0.&&&&&&&&&&&&&&&&&&&&&{&&&<SPAN style="COLOR: #1.&&&&&&&&&&&&&&&&&&&&&&&&&Url&=&"Story/Category/[page]",&&&<SPAN style="COLOR: #2.&&&&&&&&&&&&&&&&&&&&&&&&&RouteHandler&=&typeof(MvcRouteHandler),&&&<SPAN style="COLOR: #3.&&&&&&&&&&&&&&&&&&&&&&&&&Defaults&=&defaults&&&<SPAN style="COLOR: #4.&&&&&&&&&&&&&&&&&&&&&}&&&<SPAN style="COLOR: #5.&&&&&&&&&&&&&&&&&);&&&<SPAN style="COLOR: #6.&&&&<SPAN style="COLOR: #7.&&&&&routes.Add(&&&<SPAN style="COLOR: #8.&&&&&&&&&&&&&&&&&&&&&new&Route&&&<SPAN style="COLOR: #9.&&&&&&&&&&&&&&&&&&&&&{&&&<SPAN style="COLOR: #0.&&&&&&&&&&&&&&&&&&&&&&&&&Url&=&"Story/[action]/[name]/[page]",&&&<SPAN style="COLOR: #1.&&&&&&&&&&&&&&&&&&&&&&&&&RouteHandler&=&typeof(MvcRouteHandler),&&&<SPAN style="COLOR: #2.&&&&&&&&&&&&&&&&&&&&&&&&&Defaults&=&defaults&&&<SPAN style="COLOR: #3.&&&&&&&&&&&&&&&&&&&&&}&&&<SPAN style="COLOR: #4.&&&&&&&&&&&&&&&&&);&&&<SPAN style="COLOR: #5.&&&&<SPAN style="COLOR: #6.&&&&&routes.Add(&&&<SPAN style="COLOR: #7.&&&&&&&&&&&&&&&&&&&&&new&Route&&&<SPAN style="COLOR: #8.&&&&&&&&&&&&&&&&&&&&&{&&&<SPAN style="COLOR: #9.&&&&&&&&&&&&&&&&&&&&&&&&&Url&=&"[controller]/[action]/[id]",&&&<SPAN style="COLOR: #0.&&&&&&&&&&&&&&&&&&&&&&&&&RouteHandler&=&typeof(MvcRouteHandler),&&&<SPAN style="COLOR: #1.&&&&&&&&&&&&&&&&&&&&&&&&&Defaults&=&defaults&&&<SPAN style="COLOR: #2.&&&&&&&&&&&&&&&&&&&&&}&&&<SPAN style="COLOR: #3.&&&&&&&&&&&&&&&&&);&&&<SPAN style="COLOR: #4.&&&&<SPAN style="COLOR: #5.&&&&&routes.Add(&&&<SPAN style="COLOR: #6.&&&&&&&&&&&&&&&&&&&&&new&Route&&&<SPAN style="COLOR: #7.&&&&&&&&&&&&&&&&&&&&&{&&&<SPAN style="COLOR: #8.&&&&&&&&&&&&&&&&&&&&&&&&&Url&=&"Default.aspx",&&&<SPAN style="COLOR: #9.&&&&&&&&&&&&&&&&&&&&&&&&&RouteHandler&=&typeof(MvcRouteHandler),&&&<SPAN style="COLOR: #0.&&&&&&&&&&&&&&&&&&&&&&&&&Defaults&=&defaults&&&<SPAN style="COLOR: #1.&&&&&&&&&&&&&&&&&&&&&}&&&<SPAN style="COLOR: #2.&&&&&&&&&&&&&&&&&);&&&<SPAN style="COLOR: #3.&}&&如你所见,我们把类似User/Login, User/Signup, Story/Detail, Story/Category这类比较特殊的规则放在前面,而把Story/[action], [controller]/[action]这类一般的规则放在后面。当碰到变量时候,我们用[]来表示。MVC framework有两个固定的变量名:[controller]和[action],其他的就用controller里行为方法的变量名来命名。最后一个规则我们把default.aspx映射到所有分类列表来处理路径/。测试筛选规则当上面那些筛选规则定义好以后,我们就应该立刻开始测试。这样就可以帮助我们确定现有的筛选规则能否很好的映射所有的controller行为和URL中传递的方法是否正确。下面这个表列出了我们想测试的所有映射规则:
Table 1: Tests
Functionality
Url Format
Controller
User/Login
UserController
SendPassword发送密码
User/SendPassword
UserController
SendPassword
Signup注册
User/Signup
UserController
Logout注销
User/Logout
UserController
List All Published Story列表所有发布的Story
Story/CategoryStory/Category/[page]
StoryController
List Published Stories for a specific Category列表某一类别里所有发布的Storys
Story/Category/[categoryName]Story/Category/[categoryName]/[page]
StoryController
List Upcoming Stories列表Upcoming Stories
Story/UpcomingStory/Upcoming/[page]
StoryController
List Stories for a specific Tag列表某一标签里所有Stories
Story/Tag/[tagName]Story/Tag/[tagName]/[page]
StoryController
List Stories Posted By an User列表某一用户发布的Stories
Story/PostedBy/[userName]Story/PostedBy/[userName]/[page]
StoryController
Search Stories查询Stories
Story/Search?q=queryStory/Search/[q]/[page]
StoryController
View Details of a Story查看一个Storie的详细信息
Story/Detail/[storyID]
StoryController
Submit a Story提交一个Story
Story/Submit
StoryController
Vote a Story给一个Story投票
Story/Kigg
StoryController
Post a Comment发布评论
Story/Comment
StoryController
Comment你可以在测试项目里找到我们测试所使用的Route.cs文件。我们同时创建了VSTSTest和NUnit两个版本的单元测试。我们用了Rhino Mocks来制作模仿对象。这些测试几个礼拜之前发布的一文里部分代码创建的。译注:模仿对象是单元测试时常用的一种方法。下面这些代码片段测试了筛选规则:
&&&<SPAN style="COLOR: #.&[TestInitialize]&&&&&<SPAN style="COLOR: #.&public&void&Init()&&&&&<SPAN style="COLOR: #.&{&&&&&<SPAN style="COLOR: #.&&&&&routes&=&new&RouteCollection();&&&&&<SPAN style="COLOR: #.&&&&&Global.RegisterRoutes(routes);&&&&&<SPAN style="COLOR: #.&&&&&&<SPAN style="COLOR: #.&&&&&mocks&=&new&MockRepository();&&&&&<SPAN style="COLOR: #.&}&&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&[TestMethod]&&&&<SPAN style="COLOR: #.&public&void&VerifyDefault()&&&&<SPAN style="COLOR: #.&{&&&&<SPAN style="COLOR: #.&&&&&IHttpContext&httpC&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&using&(mocks.Record())&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&httpContext&=&GetHttpContext(mocks,&"~/Default.aspx");&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&using&(mocks.Playback())&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&RouteData&routeData&=&routes.GetRouteData(httpContext);&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&&&&&Assert.IsNotNull(routeData);&&&&<SPAN style="COLOR: #.&&&&&&&&&Assert.AreEqual("Story",&routeData.Values["Controller"]);&&&&<SPAN style="COLOR: #.&&&&&&&&&Assert.AreEqual("Category",&routeData.Values["action"]);&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&[TestMethod]&&&&<SPAN style="COLOR: #.&public&void&VerifyAllCategory()&&&&<SPAN style="COLOR: #.&{&&&&<SPAN style="COLOR: #.&&&&&IHttpContext&httpC&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&using&(mocks.Record())&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&httpContext&=&GetHttpContext(mocks,&"~/Story/Category/20");&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&using&(mocks.Playback())&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&RouteData&routeData&=&routes.GetRouteData(httpContext);&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&&&&&Assert.IsNotNull(routeData);&&&&<SPAN style="COLOR: #.&&&&&&&&&Assert.AreEqual("Story",&routeData.Values["Controller"]);&&&&<SPAN style="COLOR: #.&&&&&&&&&Assert.AreEqual("Category",&routeData.Values["action"]);&&&&<SPAN style="COLOR: #.&&&&&&&&&Assert.IsNull(routeData.Values["name"]);&&&&<SPAN style="COLOR: #.&&&&&&&&&Assert.AreEqual("<SPAN style="COLOR: #",&routeData.Values["page"]);&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&}&&实现UserController&前面我们定义了UserController的签名,现在我们就来具体实现他。UserController使用了ASP.NET Membership provider来实现登录、注册和其他一些功能。这个controller和其他controller唯一的区别就是这个controller里所以方法都返回一个JSON数据而不是HTML输出。客户端通过ASP.NET AJAX Framework来调用这个controller里的方法。下面这些代码是Login方法的实现:
&&&<SPAN style="COLOR: #.&[ControllerAction]&&&&&<SPAN style="COLOR: #.&public&void&Login(string&userName,&string&password,&bool&rememberMe)&&&&&<SPAN style="COLOR: #.&{&&&&&<SPAN style="COLOR: #.&&&&&using&(new&CodeBenchmark())&&&&&<SPAN style="COLOR: #.&&&&&{&&&&&<SPAN style="COLOR: #.&&&&&&&&&JsonResult&result&=&new&JsonResult();&&&&&<SPAN style="COLOR: #.&&&&&&<SPAN style="COLOR: #.&&&&&&&&&if&(string.IsNullOrEmpty(userName))&&&&&<SPAN style="COLOR: #.&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&result.errorMessage&=&"User&name&cannot&be&blank.";&&&&<SPAN style="COLOR: #.&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&else&if&(string.IsNullOrEmpty(password))&&&&<SPAN style="COLOR: #.&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&result.errorMessage&=&"Password&cannot&be&blank.";&&&&<SPAN style="COLOR: #.&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&else&if&(!UserManager.ValidateUser(userName,&password))&&&&<SPAN style="COLOR: #.&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&result.errorMessage&=&"Invalid&login&credentials.";&&&&<SPAN style="COLOR: #.&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&&&&&else&&&&<SPAN style="COLOR: #.&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&//The&following&check&is&required&for&TDD&&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&if&(HttpContext&!=&null)&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&&&&&FormsAuthentication.SetAuthCookie(userName,&rememberMe);&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&&&&&&&&&result.isSuccessful&=&true;&&&&<SPAN style="COLOR: #.&&&&&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&&&&&RenderView("Json",&result);&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&}&&如你所见,我们在方法开头就创建了一个JsonResult对象。JsonResult是一个用来反馈controller行为是否成功的简单类,他只有两个属性isSuccessful和errorMessage, errorMessage。如果操作不成功,就把失败原因存在errorMessage里。在结尾处,我们把结果当作一个名为Json的共享视图里的view data返回。因为是一个共享视图,所以他可以被UserController和StoryController使用。我们把他放在了Views里名为Shared 的文件夹里。这个controller 里的其他方法工作原理都跟这个十分相似。我这里需要提到的一件重要的事情是,我们在构造函数里传递了一个抽象的membership provider来代替静态的Membership 类。这样做是因为在单元测试中我们可以传递一个模仿的Membership Provider,我们将在下一小节展示。在另一个构造函数中,我们传递web.config中定义的默认membership provider。测试UserController 为了测试这个Controller,我们仍然使用前几周在一文中的方法。前面一小节说过,我们把一个模仿的Membership Provider传递过去来测试这个controller。我们预想在controller 调用这个membership provider然后能够得到正确的数据并发送给view。下面这些代码展示了正确的登录和当用户名为空时错误的登录:
&&&<SPAN style="COLOR: #.&[TestInitialize]&&&&&<SPAN style="COLOR: #.&public&void&Init()&&&&&<SPAN style="COLOR: #.&{&&&&&<SPAN style="COLOR: #.&&&&&mocks&=&new&MockRepository();&&&&&<SPAN style="COLOR: #.&&&&&userManager&=&mocks.PartialMock&MembershipProvider&();&&&&&<SPAN style="COLOR: #.&&&&&controller&=&new&UserControllerForTest(userManager);&&&&&<SPAN style="COLOR: #.&}&&&&&<SPAN style="COLOR: #.&&&&&&<SPAN style="COLOR: #.&[TestMethod]&&&&<SPAN style="COLOR: #.&public&void&ShouldLogin()&&&&<SPAN style="COLOR: #.&{&&&&<SPAN style="COLOR: #.&&&&&using(mocks.Record())&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&&&&&Expect.Call(userManager.ValidateUser(DefaultUserName,&DefaultPassword)).IgnoreArguments().Return(true);&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&using(mocks.Playback())&&&&<SPAN style="COLOR: #.&&&&&{&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&&&&&controller.Login(DefaultUserName,&DefaultPassword,&true);&&&&<SPAN style="COLOR: #.&&&&&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&Assert.AreEqual(controller.SelectedView,&"Json");&&&&<SPAN style="COLOR: #.&&&&&Assert.IsInstanceOfType(controller.SelectedViewData,&typeof(JsonResult));&&&&<SPAN style="COLOR: #.&&&&&Assert.IsTrue(((JsonResult)controller.SelectedViewData).isSuccessful);&&&&<SPAN style="COLOR: #.&&&&&Assert.IsNull(((JsonResult)controller.SelectedViewData).errorMessage);&&&&<SPAN style="COLOR: #.&}&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&[TestMethod]&&&&<SPAN style="COLOR: #.&public&void&ShoudNotLoginForEmptyUserName()&&&&<SPAN style="COLOR: #.&{&&&&<SPAN style="COLOR: #.&&&&&controller.Login(string.Empty,&DefaultPassword,&false);&&&&<SPAN style="COLOR: #.&&&&&<SPAN style="COLOR: #.&&&&&Assert.AreEqual(controller.SelectedView,&"Json");&&&&<SPAN style="COLOR: #.&&&&&Assert.IsInstanceOfType(controller.SelectedViewData,&typeof(JsonResult));&&&&<SPAN style="COLOR: #.&&&&&Assert.IsFalse(((JsonResult)controller.SelectedViewData).isSuccessful);&&&&<SPAN style="COLOR: #.&&&&&Assert.AreEqual(((JsonResult)controller.SelectedViewData).errorMessage,&"User&name&cannot&be&blank.");&&&&<SPAN style="COLOR: #.&}&&综述我最初想用一篇文章搞定所有问题,但是你也发现了,这篇文章实在是太长了。译注:确实长的可以。在这篇文章中,我们首先简单了解了一下ASP.NET MVC Framework,然后讲解了如何在controllers里定义功能,如何定义筛选规则并通过URLs测试他们,我们也看见了如何在Controller 中使用JSON 数据来代替完整的HTML视图。在本文的下一个部分里,我们讲着重讲解Controller,如何展示完整的HTML视图,使用master pages和user controls来创建视图,给视图发送强类型的view data和最后创建Model。就此停笔。
阅读(...) 评论()}

我要回帖

更多关于 筛选时间段 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信