最近自己亲自用MVC Beta版+DLinq 做了个网站:
51乡音网(各种方言翻唱的流行歌等) 当作是实践。都是一些平时自己在MVC实践过程中遇到一些问题,现在总结如下,希望对大家有所帮助。
目录:
一, MVC Route的配置
1. 好好想想需求,看是不是可以把某些参数配置在Route里.
2. Route冲突的情况,使用加前缀的方法解决.
3. 配置Route,以便使用自定义的Handler.
二, Action方法的参数
1.参值的来源的优先顺序
2.BindAttributer使用及其注意事项
三, MVC如何手动清除所有的OutPutCache
四, 谈谈MVC的可扩展性,如何创建自定义 ViewUserControl
五. AcceptVerbs的使用.
一, MVC Route的配置
1. 好好想想需求,看是不是可以把某些参数配置在Route里.
例 做一个小型CMS系统,支持多用户支持。
刚开始想把用户userName做为Request.Query参数来处理。后来发现这样子做浪费了不少时间。于是我把userName参数配置在Route里.
代码如下:
new UserMvcRouteHandler(),
"Default", // Route name
"{userName}/{controller}/{action}/{id}", // URL with parameters
new { userName = "Leegool", controller = "Home", action = "Index", id = @"^\d" }
);
2. Route冲突的情况,使用加前缀的方法解决.
例子 :加了个 "p." 在pageNumber参数
“viewInfo",
"{userName}/{controller}/{action}/c.{categoryId}",
new { userName = "Leegool", controller = "Info", action = "List"));
这个时候 如何访问 Leegool/List/Info/c.1, 它就会定位到 viewInfo这个Route,而不是上例的 Default Route.
3. 配置Route,以便使用自定义的Handler.
在Global.asax.cs里
{
routes.IgnoreRoute("{resource}.ashx/{*pathInfo}");
}
这个时候你就可以使用自己的比如验证码生成之类的Handler,如:使用HIP.ashx?width=100&height=200
就不会被Route拦截到。
二, Action方法的参数
1.参数值的来源的优先顺序
从MVC 源代码中得到如下文字:
// Try to get a value for the parameter. We use this order of precedence:
// 1. Values from the RouteData (could be from the typed-in URL or from the route's default values)
// 2. URI query string
// 3. Request form submission (should be culture-aware)
也就是Action方法的参数值的来源顺序是
1.从RouteData中获得,如果没有就从2中获取
2.URL的QueryString获得,如果没有就从3中获取
3.从Form页面获得
从代码逻辑中也可以弄清这一点,相信应该很有帮助。
2.BindAttributer使用及其注意事项
先看个BindAttributer的使用例子:
{
.
}
这样子,网页上只要绑定就ok了
BindAttributer使用注意事项是
a. 注意使用Prefix = "",如果不定义Prefix,则Prefix为null。因为是string类型,默认新一个string对象是null.这又回到编码细节的问题了。呵。
从MVC源代码里看到
BindAttribute attr = (BindAttribute)Attribute.GetCustomAttribute(parameterInfo, typeof(BindAttribute));
return ((attr != null) && (attr.Prefix != null)) ? attr.Prefix : parameterInfo.Name;
}
它是null,所以会返回参数名.这里的例子就是返回information。
所以到后面去找InformationId,Title,Abstract,KeyWord,Detail,CategoryId的值的时候,它实践上就是找
information.InformationId,information.Title...
结果是Action的参数information为null。
b. 不要绑定自引用结构的类,
比如当一个Information(文章)都有一种Category(类别),这个类别的表结构是自引用的。
Category的表结构如下
CategoryId Content ParentCategoryId
这个时候如果使用Bind(Include = Category)就会出现死循环(Category会去寻找ParentCategory,而ParentCategory又会去寻找它的ParentCategory....),导致一个异常。
我自己用的时候是尽量不是去Include一个对象.
三, MVC如何手动清除所有的OutPutCache
首先, 介绍一下ASP.NET中AddCacheItemDependency方法,这个方法是将页面的输出缓存 依赖于 Cache对象。
也就是说,如果Cache对象过期,页面输出缓存也就过期。
使用方法:
通常在PageLoad事件中加入如下代码:
Response.AddCacheItemDependency("key");
在页面上配置了输出缓存后,
手动清除输出缓存的代码:
这个时候就会把与 关键字为"key"的Cache对象清除,同时把与之相关联的页面输出缓存都清除掉.
然后, 我们要看看MVC源代码,发现了OutputCachedPage类。
我的方法是扩展修改OutputCachedPage类。
由于OutputCachedPage类是private sealed, 并且是继承: Page类。即 private sealed class OutputCachedPage : Page 由于我懒得去写个wrapper。就直接修改它的源代码了。
代码如下
{
try
{
string cacheKey = "key" ;
HttpContext.Current.Cache[cacheKey] = DateTime.UtcNow.ToString();
Response.AddCacheItemDependency(cacheKey);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
base.OnLoad(e);
}
清除缓存代码如下:
{
HttpRuntime.Cache.Remove(item.Key.ToString());
}
当然建议还是写个包装类出来,这样在新版本出来的时候移植也方便些。
四, 谈谈MVC的可扩展性,如何创建自定义 ViewUserControl
比如说51音乡网刚开始考虑的是可以注册多用户,就像是小型的CMS一样。我需要对用户名做一些额外处理,这个时候就可以自定义UserViewUserControl 类:
{
protected internal string UserName
{
get
{
...
return _userName;
}
}
}
使用方法如下:
本来是 public partial class LogoTitle : ViewUserControl
改成 public partial class LogoTitle : UserViewUserControl 就可以用了.
其它如ViewPage/ViewMasterPage等类推.
当然还可以自己定义MVCHandler.
第五. AcceptVerbs的使用。
需求如下:
可以通过类别来Search产品,并可以分页。其实UI很简单:一个类别DropDownList,一个Search Button,一个分页控件。
解决方案:
遇到这种情况,应该放在两个Action方法中实现。但两个Action的ActionName是一样的。区别在于一个有AcceptVerbs(HttpVerbs.Post)标签,另一个Action方法没有。
代码如下:
单击Search Button的时候,触发了Post动作,执行的是Search1方法
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Search1(string userName, int pageNumber)
{
int categoryId = Convert.ToInt32(this.ControllerContext.HttpContext.Request.Form["CategoryId"]);
...
return View(gridViewData);
}
当你点击分页的时候,没有Post动作。触发的是Search2方法。MVC会自动根据AcceptVerbs标签去执行匹配的方法。
[ActionName("Search")]
public ActionResult Search2(string userName, int pageNumber)
{
int categoryId = Convert.ToInt32(this.ControllerContext.HttpContext.Request.QueryString["CategoryId"]);
....
return View(gridViewData);
}
第一次写博客文章,可能写的不好,请大家见谅了。后面如果有时间我想再写个MVC Beta 做的网站实践总结(下)。比如分页控件,MVC的页面生命周期等等。