关于“验证码的制作”的一些补充
上次写了点关于验证码制作的代码,算是学习了drawing中的一些东西,心里很快活,也乐意为大伙儿做些善事,于是便萌发了把验证码封装成简单的控件发布出去的念头——起初是用ashx(一般处理程序,俗称httphander)的做法,ok。在webform和mvc两种情况下毫无问题——代码很简单,假设把ashx放在程序根目录,那么你就在页面中对应弄上一个img即可:
<img src="/image.req"/>
这样生成img标签自动也会请求这个handler,生成图片(不要忘记配置handler就可以了)。
然后我想到要做一个dll,因为总觉得把ashx发布出去不是很正规(别人都是发布dll的嘛,呵呵),于是我自己创建了一个类库(classlibrary),创建对应的类,实现了ihttphandler和irequiressessionstate(拷贝原先ashx中正确的代码,也就是上一篇的代码全部)。然后编译成dll,在web.config的<httphandlers>进行恰当的配置:
<configuration>
<system.web>
<!---httphandler's configuration here……-->
<httphandlers>
<add path="*.req" verb="*" type="testlibrary.drawimage"/>
</httphandlers>
………………
然后在webform和mvc中同时实验——结果很奇怪:在webform一切照旧正常,可是mvc程序中死活就是红叉叉报错(显示不出图片,郁闷中……)
后来多方请教,直到遇到了大神imran_ku07之后我才恍然大悟(看到 .net/t/1800318.aspx">http://forums.asp.net/t/1800318.aspx这篇类似的问题)——原来当你写"/image.req"的时候,默认路由就会按照“controller/action/defaultoptionalvalue”去匹配:这样的话,controller就变成了“image.req”,自然没有这个controller,然后自然报错(图片无法出来)。
解决办法就是让这个路径不要通过默认的route方式解析,使用ignoreroute方式排除这个路径(粗体):
[c#]
public class mapplication : system.web.httpapplication
{
public static void registerroutes(routecollection routes)
{
routes.ignoreroute("{resource}.axd/{*pathinfo}");
routes.ignoreroute("{resource}.req/{*pathinfo}");
routes.maproute(
"default", // 路由名称
"{controller}/{action}/{id}", // 带有参数的 url
new { controller = "default", action = "index", id = urlparameter.optional } // 参数默认值
);
}
protected void application_start()
{
arearegistration.registerallareas();
registerroutes(routetable.routes);
}
}
[vb.net]
public class mvcapplication
inherits system.web.httpapplication
public shared sub registerroutes(routes as routecollection)
routes.ignoreroute("{resource}.axd/{*pathinfo}")
routes.ignoreroute("{resource}.req/{*pathinfo}")
' 路由名称
' 带有参数的 url
' 参数默认值
routes.maproute("default", "{controller}/{action}/{id}", new with { _
key .controller = "default", _
key .action = "index", _
key .id = urlparameter.[optional] _
})
end sub
protected sub application_start()
arearegistration.registerallareas()
registerroutes(routetable.routes)
end sub
end class
这样一来,果然在asp mvc中也可以咯!神啦!
“福无双至,祸不单行”——下午某时有个中软的程序员找我询问关于如何屏蔽mvc插件的事情(它的项目根目录有plugin文件夹,然后里边有大量其它重要文件,现在不想要别人访问)。我想了以下,给了两个解决方案:
1)在根目录web.config中配置如下(相对于根目录的子目录——plugin中后面子文件夹和文件均无法访问)
<system.web>
<httphandlers>
<add path="/plugin/*" verb="*" type="system.web.httpnotfoundhandler"/>
</httphandlers>
………………
2)拷贝一个web.config文件到plugin文件夹中,然后这样配置(表示当前文件夹中所有子文件夹和文件均无法访问)
<system.web>
<httphandlers>
<add path="*" verb="*" type="system.web.httpnotfoundhandler"/>
</httphandlers>
………………
他的问题是解决了,我又冒出新问题了——既然mvc可以通过:“http://localhost/文件夹名/文件”的形式直接访问文件,那么它为什么不会把“文件夹名”解析成controller,“文件”解析成action呢?我猜想如下:
1)任何网页程序默认“潜规则”解析是根据地址栏输入的虚拟路径寻找对应的文件(传统asp.net web也不例外),因此mvc也有此潜规则——如果地址栏输入的虚拟路径恰好可以映射找到真实的文件,那么直接返回结果,就不会在route了。
2)如果找不到:
2.1)尝试route(按照默认或者其它定义规则:http://localhost/{controller}/{action}/defaultoptionalparameter)进行解析。
2.2)如果解析成功,那么返回action中对应的view,解析失败,抛出异常。
3)如果某个请求地址(比如image.req纯粹是一个ashx请求,真实文件路径均不存在),直接使用route规则匹配肯定错误,此时你就应该告知“这是例外”(用ignoreroute即可)。
摘自 serviceboy