ASP.NET MVC 框架实践总结
我公司开发团队采用asp.net mvc大致经过了三个阶段
1、摸索期:从今年初公司开发一个新项目时选用了asp.net MVC Preview2,然后用了几天我发现routing似乎有bug,正在这时发现了已经出现了preview2-590,我赶紧将框架“升级”到了590。
2、应用期:项目开发一个多月后我们发现了一些不方便不顺手的地方,感觉缺少一些提高效率的小功能,如当一个路径的参数经过routing路由到一个action后,action及视图页(.aspx/.ascx)上下文里获取它不符合我们的开发逻辑——在应用mvc之前我们都是用Request["id"]的方式获取,但是如果此时如果一个参数被routing"美化"后就得不到了,代码如下:

 路由条目例
路由条目例1 routeCollection.Add("0", new System.Web.Routing.Route("{id}/space/{action}/{page}/{size}",
2 new RouteValueDictionary(new { controller = "space", action = "index", id = "0", page = "3", size = "76" }),
3 new RouteValueDictionary(new { controller = "[^/]+", action = "[^/]+", id = "\\d+", page = "\\d*" }),
4 null
相应的控制器和action代码如下:

 Code
Code public partial class SpaceController : AjaxController
    public partial class SpaceController : AjaxController
 
     {
{ [Bll.Filter.SpaceViewFilter]
        [Bll.Filter.SpaceViewFilter] public void Story(long id, long? classid, int? page, int? size)
        public void Story(long id, long? classid, int? page, int? size)
 
         {
{ 
            
 RenderView("Story");
            RenderView("Story"); }
        } }
}
 控制器代码
控制器代码
 现在story方法体内以及story.aspx里Request["id"],Request["page"] 获取不到相应的值!由于开发项目时有些路由规则没有写,打算以后总体调整路由规则,但是出错了,因为根本获取不到参数,我们非常郁闷!
  于是我开始下载源码、检阅、跟踪、修改,经过一周左右的时间终于将MVC的流程及原理理了个顺,最后修改加进了一些我们急需的小功能:
修改了System.Web.Mvc的控制器、视图相关的代码,实现了在Action、.aspx/.ascx/.master里可以沿用Request["key"]的方式获取参数(不论routing怎么变都不影响),不区分key的大小
修改了ViewData类,使ViewData["key"]不区分大小写;
增加了一个路由配置类,使路由器可以能过.config文件来配置,如下:

 routing配置文件
routing配置文件 <configuration>
<configuration> <configSections>
  <configSections> <section name="routeTable" type="System.Web.Mvc.RouteTableSection,System.Web.Mvc" allowDefinition="Everywhere" allowExeDefinition="MachineToApplication" restartOnExternalChanges="true" />
    <section name="routeTable" type="System.Web.Mvc.RouteTableSection,System.Web.Mvc" allowDefinition="Everywhere" allowExeDefinition="MachineToApplication" restartOnExternalChanges="true" /> </configSections>
  </configSections> <routeTable>
  <routeTable> <routes>
    <routes> <add name="StoryTaglist" url="/Story/Tag/{id}/{page}/{size}"  routeHandlerType="System.Web.Mvc.MvcRouteHandler, System.Web.Mvc">
      <add name="StoryTaglist" url="/Story/Tag/{id}/{page}/{size}"  routeHandlerType="System.Web.Mvc.MvcRouteHandler, System.Web.Mvc"> <defaults controller="Story" action="Tag" classid="0" size="null"/>
        <defaults controller="Story" action="Tag" classid="0" size="null"/> </add>
      </add>
 </routes>
    </routes> </routeTable>
  </routeTable> </configuration>
</configuration>
 给ViewData增加了一些扩展方法Get<T>(key)类方法,取得viewdata里的某个值,并且转换成指定的对象类型,如果不是该类型或如果是一个数组类型而元素为0个或没有此key都将返回null,代码如下:

 ViewData.Get
ViewData.Get var ams = ViewData.Get<IList<KeyValuePair<Duw.Mod.DB.Album, Duw.Mod.DB.ViewFriendandfriendtype>>>("albumList");
var ams = ViewData.Get<IList<KeyValuePair<Duw.Mod.DB.Album, Duw.Mod.DB.ViewFriendandfriendtype>>>("albumList"); if (ams != null)
  if (ams != null)
 
   { 。。。
{ 。。。 }
}类完整代码如下:

 ViewData.Get
ViewData.Get using System;
using System; using System.Collections;
using System.Collections; using System.Collections.Generic;
using System.Collections.Generic;

 namespace System.Web.Mvc
namespace System.Web.Mvc

 {
{ using System.Collections;
    using System.Collections; using System.Web.UI;
    using System.Web.UI;
 public static partial class CustomHelper
    public static partial class CustomHelper
 
     {
{
 /**//// <summary>
        /**//// <summary> /// 取得viewdata里的某个值,并且转换成指定的对象类型,如果不是该类型或如果是一个数组类型而元素为0个或没有此key都将返回空,
        /// 取得viewdata里的某个值,并且转换成指定的对象类型,如果不是该类型或如果是一个数组类型而元素为0个或没有此key都将返回空, /// </summary>
        /// </summary> /// <typeparam name="T">必须为一个非值类型</typeparam>
        /// <typeparam name="T">必须为一个非值类型</typeparam> /// <param name="obj"></param>
        /// <param name="obj"></param> /// <param name="key"></param>
        /// <param name="key"></param> /// <returns></returns>
        /// <returns></returns> public static T Get<T>(this System.Web.Mvc.ViewData obj, string key)
        public static T Get<T>(this System.Web.Mvc.ViewData obj, string key) where T : class
            where T : class
 
         {
{ if (!obj.ContainsDataItem(key))
            if (!obj.ContainsDataItem(key)) return null;
                return null;
 var val = obj[key];
            var val = obj[key];
 if (val == null)
            if (val == null) return null;
                return null;
 var val2 = val as T;
            var val2 = val as T; if (val2 == null)
            if (val2 == null) return null;
                return null;
 if (val2 is IEnumerable)
            if (val2 is IEnumerable)
 
             {
{ var a = (IEnumerable)(val2);
                var a = (IEnumerable)(val2);
 var b = a.GetEnumerator();
                var b = a.GetEnumerator();
 //try
                //try //{
                //{ if (b.MoveNext())
                if (b.MoveNext()) return val2;
                    return val2; else
                else return null;
                    return null; //}
                //} //catch
                //catch //{
                //{ //    return null;
                //    return null; //}
                //} }
            } else
            else
 
             {
{ return val2;
                return val2; }
            }
 }
        }


 /**//// <summary>
        /**//// <summary> /// 如果没有此key,返回""
        /// 如果没有此key,返回"" /// </summary>
        /// </summary> /// <param name="obj"></param>
        /// <param name="obj"></param> /// <param name="key"></param>
        /// <param name="key"></param> /// <returns></returns>
        /// <returns></returns> public static string GetString(this System.Web.Mvc.ViewData obj, string key)
        public static string GetString(this System.Web.Mvc.ViewData obj, string key)
 
         {
{ if (!obj.ContainsDataItem(key))
            if (!obj.ContainsDataItem(key)) return "";
                return "";
 var val = obj[key];
            var val = obj[key]; if (val == null) return "";
            if (val == null) return ""; return val.ToString();
            return val.ToString(); }
        }

 /**//// <summary>
        /**//// <summary> /// 如果没有此key或不能转换成数值类型,返回-1
        /// 如果没有此key或不能转换成数值类型,返回-1 /// </summary>
        /// </summary> /// <param name="obj"></param>
        /// <param name="obj"></param> /// <param name="key"></param>
        /// <param name="key"></param> /// <returns></returns>
        /// <returns></returns> public static long GetLong(this System.Web.Mvc.ViewData obj, string key)
        public static long GetLong(this System.Web.Mvc.ViewData obj, string key)
 
         {
{ if (!obj.ContainsDataItem(key))
            if (!obj.ContainsDataItem(key)) return -1;
                return -1; var val = obj[key];
            var val = obj[key]; if (val == null) return -1;
            if (val == null) return -1;
 long v;
            long v; if (long.TryParse(val.ToString(), out v))
            if (long.TryParse(val.ToString(), out v)) return v;
                return v; else
            else return -1;
                return -1; }
        }


 /**//// <summary>
        /**//// <summary> /// 如果没有此key或不能转换成数值类型,返回-1
        /// 如果没有此key或不能转换成数值类型,返回-1 /// </summary>
        /// </summary> /// <param name="obj"></param>
        /// <param name="obj"></param> /// <param name="key"></param>
        /// <param name="key"></param> /// <returns></returns>
        /// <returns></returns> public static int GetInt(this System.Web.Mvc.ViewData obj, string key)
        public static int GetInt(this System.Web.Mvc.ViewData obj, string key)
 
         {
{ if (!obj.ContainsDataItem(key))
            if (!obj.ContainsDataItem(key)) return -1;
                return -1; var val = obj[key];
            var val = obj[key]; if (val == null) return -1;
            if (val == null) return -1;
 int v;
            int v; if (int.TryParse(val.ToString(), out v))
            if (int.TryParse(val.ToString(), out v)) return v;
                return v; else
            else return -1;
                return -1; }
        }

 /**//// <summary>
        /**//// <summary> /// 如果没有此key或不能转换成布尔类型,返回false
        /// 如果没有此key或不能转换成布尔类型,返回false /// </summary>
        /// </summary> /// <param name="obj"></param>
        /// <param name="obj"></param> /// <param name="key"></param>
        /// <param name="key"></param> /// <returns></returns>
        /// <returns></returns> public static bool GetBool(this System.Web.Mvc.ViewData obj, string key)
        public static bool GetBool(this System.Web.Mvc.ViewData obj, string key)
 
         {
{ if (!obj.ContainsDataItem(key))
            if (!obj.ContainsDataItem(key)) return false;
                return false; var val = obj[key];
            var val = obj[key]; if (val == null) return false;
            if (val == null) return false;
 bool v;
            bool v; if (bool.TryParse(val.ToString(), out v))
            if (bool.TryParse(val.ToString(), out v)) return v;
                return v; else
            else return false;
                return false; }
        }



 /**//// <summary>
        /**//// <summary> /// 如果没有此key或不能转换成数值类型,返回-1.0
        /// 如果没有此key或不能转换成数值类型,返回-1.0 /// </summary>
        /// </summary> /// <param name="obj"></param>
        /// <param name="obj"></param> /// <param name="key"></param>
        /// <param name="key"></param> /// <returns></returns>
        /// <returns></returns> public static double GetDouble(this System.Web.Mvc.ViewData obj, string key)
        public static double GetDouble(this System.Web.Mvc.ViewData obj, string key)
 
         {
{ if (!obj.ContainsDataItem(key))
            if (!obj.ContainsDataItem(key)) return -1.0;
                return -1.0; var val = obj[key];
            var val = obj[key]; if (val == null) return -1.0;
            if (val == null) return -1.0;
 double v;
            double v; if (double.TryParse(val.ToString(), out v))
            if (double.TryParse(val.ToString(), out v)) return v;
                return v; else
            else return -1.0;
                return -1.0; }
        }

 /**//// <summary>
        /**//// <summary> /// 如果没有此key或不能转换成数值类型,返回0.0;如果超过float的范围并且在double范围内则自动截取为float类型值返回
        /// 如果没有此key或不能转换成数值类型,返回0.0;如果超过float的范围并且在double范围内则自动截取为float类型值返回 /// </summary>
        /// </summary> /// <param name="obj"></param>
        /// <param name="obj"></param> /// <param name="key"></param>
        /// <param name="key"></param> /// <returns></returns>
        /// <returns></returns> public static float GetFloat(this System.Web.Mvc.ViewData obj, string key)
        public static float GetFloat(this System.Web.Mvc.ViewData obj, string key)
 
         {
{ double val = obj.GetDouble(key);
            double val = obj.GetDouble(key); if (val == 0.0)
            if (val == 0.0) return 0.0f;
                return 0.0f; else
            else return (float)val;
                return (float)val; }
        }



 /**//// <summary>
        /**//// <summary> /// 判断某一个key值是否存在;并且如果它是一个枚举对象还要判断它是否包含一个以上的元素
        /// 判断某一个key值是否存在;并且如果它是一个枚举对象还要判断它是否包含一个以上的元素 /// </summary>
        /// </summary> /// <param name="obj"></param>
        /// <param name="obj"></param> /// <param name="key"></param>
        /// <param name="key"></param> /// <returns></returns>
        /// <returns></returns> public static bool Has(this System.Web.Mvc.ViewData obj, string key)
        public static bool Has(this System.Web.Mvc.ViewData obj, string key)
 
         {
{
 if (!obj.ContainsDataItem(key))
            if (!obj.ContainsDataItem(key)) return false;
                return false;
 var val = obj[key];
            var val = obj[key];
 if (val == null)
            if (val == null) return false;
                return false;
 if (val is IEnumerable)
            if (val is IEnumerable)
 
             {
{ var a = (IEnumerable)(val);
                var a = (IEnumerable)(val);
 var b = a.GetEnumerator();
                var b = a.GetEnumerator();
 try
                try
 
                 {
{ if (b.MoveNext())
                    if (b.MoveNext()) return true;
                        return true; else
                    else return false;
                        return false; }
                } catch
                catch
 
                 {
{ return false;
                    return false; }
                } }
            } else
            else
 
             {
{ return true;
                return true; }
            } }
        } }
    } }
}
给controller增加一个类似.aspx里的Url.Action("story","space",{id=34})的方法Util.GetUrl():

 Util.GetUrl()
Util.GetUrl() using System;
using System; using System.Collections.Generic;
using System.Collections.Generic; using System.Linq;
using System.Linq; using System.Text;
using System.Text;
 using System.Reflection;
using System.Reflection; using System.Web.Mvc;
using System.Web.Mvc; using System.Web.Routing;
using System.Web.Routing;
 namespace System.Web.Mvc
namespace System.Web.Mvc

 {
{ public class Util
    public class Util
 
     {
{ public  static string GetUrl(ControllerContext context, RouteValueDictionary values)
        public  static string GetUrl(ControllerContext context, RouteValueDictionary values)
 
         {
{ string routeName = "";
            string routeName = ""; VirtualPathData vpd = string.IsNullOrEmpty(routeName) ? RouteTable.Routes.GetVirtualPath(context, values) : RouteTable.Routes.GetVirtualPath(context, routeName, values);
            VirtualPathData vpd = string.IsNullOrEmpty(routeName) ? RouteTable.Routes.GetVirtualPath(context, values) : RouteTable.Routes.GetVirtualPath(context, routeName, values); return vpd.VirtualPath;
            return vpd.VirtualPath;
 //return UrlRewriterHelper.GetUrl(context, values, RouteTable.Routes);
            //return UrlRewriterHelper.GetUrl(context, values, RouteTable.Routes); }
        }
 }
    } }
}
 3、框架性能调优与重造,经过半年的应用开发、总结,发现MVC性能及routing不是很理想,于是又开始进行性能调优与修改,最后改成了现在的“版本”,详情请看下一篇性能调优。