• MVC Beta 做的网站实践总结(上)


    最近自己亲自用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里.

    代码如下:  

    routes.MapRoute(
                    
    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参数 

    routes.MapRoute(
                    “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里  

    public static void RegisterRoutes(RouteCollection routes)
            {
              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的使用例子:

     public ActionResult Update([Bind(Include = "InformationId,Title,Abstract,KeyWord,Detail,CategoryId", Prefix = "")]Information information)

    {
    .

    }

    这样子,网页上只要绑定就ok了

    <%= Html.TextBox("KeyWord"nullnew { style = "85%;" })%>

    BindAttributer使用注意事项是

    a.  注意使用Prefix = "",如果不定义Prefix,则Prefix为null。因为是string类型,默认新一个string对象是null.这又回到编码细节的问题了。呵。

    从MVC源代码里看到 

    private static string GetFieldPrefix(ParameterInfo parameterInfo) {
                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事件中加入如下代码:

    Cache.Insert(“key”,DateTime.UtcNow);
     Response.AddCacheItemDependency(
    "key");

    在页面上配置了输出缓存后,

    手动清除输出缓存的代码: 

    Cache.Remove("key");

    这个时候就会把与 关键字为"key"的Cache对象清除,同时把与之相关联的页面输出缓存都清除掉.

    然后, 我们要看看MVC源代码,发现了OutputCachedPage类。

    我的方法是扩展修改OutputCachedPage类。

    由于OutputCachedPage类是private sealed, 并且是继承: Page类。即 private sealed class OutputCachedPage : Page  由于我懒得去写个wrapper。就直接修改它的源代码了。

    代码如下 

    protected override void OnLoad(EventArgs e)
                {
                    
    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);
                }

    清除缓存代码如下: 

                    foreach (DictionaryEntry item in HttpRuntime.Cache)
                    {
                        HttpRuntime.Cache.Remove(item.Key.ToString());                    
                    }

    当然建议还是写个包装类出来,这样在新版本出来的时候移植也方便些。

    四, 谈谈MVC的可扩展性,如何创建自定义 ViewUserControl

    比如说51音乡网刚开始考虑的是可以注册多用户,就像是小型的CMS一样。我需要对用户名做一些额外处理,这个时候就可以自定义UserViewUserControl 类: 

    public class UserViewUserControl : ViewUserControl
        {

              
    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方法  

            [ActionName("Search")]
            [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的页面生命周期等等。

  • 相关阅读:
    unity3d 中文乱码解决方法——cs代码文件格式批量转化UTF8
    Unity SteamVR插件集成
    Unity3D Layer要点
    Unity利用Sapi进行windows语音开发
    Scratch入门课程(1)——把工具准备好
    【blockly教程】Blockly编程案例
    【blockly教程】第六章 Blockly的进阶
    【blockly教程】第五章 循环结构
    【blockly教程】第三章Blockly顺序程序设计
    【blockly教程】第四章 Blockly之选择结构
  • 原文地址:https://www.cnblogs.com/webfpc/p/1374974.html
Copyright © 2020-2023  润新知