ASP.NET MVC流程解说

时间:2022-09-09 09:54:44

开始想这个标题时,,很忧郁什么标题将得到更好的叫什么,最后确定的解释,虽然稍0基金会,但是,这个概念是非常。我想出了一个相当的价格值的。

,開始。

1、MVC的基本开发流程

 

2、webform和MVC的选择

 

3、MVC的内部过程

1、MVC的开发流程

MVC的出现时微软在2009年左右開始提出的站点开发的新的发展方向。这个方面的开发官方解释是能够比較好的实现三层分离,并且分离之后。能够实现复用等相关优点,通常人们列举的样例是ui方面能够同一时候支持HTML网络或者WAP网络。可是事实上个人的理解是,动态站点的开发经过不断地证实和发展,java的struts模型。能够提高开发速度。也能够减少差多。是比較好的框架。而微软也须要提供自己的开发框架。不能够仅仅是一个界面一个界面的设计方式,设计模式逐步进入到了web开发的领域。

MVC使用vs2010进行开发时(这里介绍的是MVC2),首先须要选在一个模板,然后vs2010会帮忙创建好相应的文件夹结构。

ASP.NET MVC流程解说

每一个文件夹的基本功能:

Content:主要用于描写叙述css之类的资源

Controllers:主要就是controller的存放位置。创建controller时。都是须要在该文件夹创建的。

Models:主要就是entity的详细位置。以及跟entity相关的操作类

Scripts:javascript脚本存放的位置

Views:该部分主要是放置view显示部分的

Global.asax:眼下来看,该部分主要就是路由设置

Web.config:该配置文件而已

从开发的流程方面来看,MVC的开发方式,或者说思考的方式出现了变化,在MVC其中。须要理解一个重要的点是:

Controller才是系统的中心,一切环绕Controller展开。

Model:所谓模型,能够理解为数据,这个数据能够是数据库中相应的表中的数据,这样的数据是仅仅有属性,而没有动作的。这样的数据通常也被称之为Entity,即实体,除了这样的数据之外。MODLE起始还要包含Interface,这些接口的目标是提供能够控制Entity的接口标准,然后在提供实现的载体,通常我们称之为Mock类,为了方便,可能我们还会在Model其中创建各种factory。从而简化对象的创建。

Controller:这个部分就是核心了,事实上所谓核心,是说所有的处理,所有环绕着Controller展开,它的主要工作是訪问model,获取数据后,将參数转发给view,然后让view表现出来。

在这里主要完毕的工作有两点:

1、在client訪问一个页面后。须要跳转到Controller相应的action中去。然后在action中处理相应的view显示出来。

2、 完毕客户的表单提交对应处理,也就是Form表单处理。(还记得之前讲过,对于HTML而言。仅仅有Form表单实现了client的信息发送给服务端。然后由服务端处理相关的对应,由于MVC的设计目标就是放弃了微软原有的server控件,因此一切回归原始,採用HTML的form表单方式实现提交和相关的控制处理。)

View:顾名思义,该部分就是现实的部分,这个部分须要时刻记住的是,这个view尽管也是aspx的页面,可是已经发生了根本性的变化,不再有所谓的codebeind代码了。这个view的全部变成将採用混合式的变成。你会注意到这个部分的变成变为HTML与C#的混合。会出现非常多的<%%><%=%>类似的代码。

非常多人起始对这个部分有不同的开发。混合代码对于分层不利。可是在MVC中,由于不涉及逻辑,所以view的表现变得简单。混合编程会变为能够接受的处理方式。

另外,这样的方式带来的优点是,美工能够介入了。他们的改动对于程序猿来说。没有什么特别,也是非常easy直接引入的。

带来的坏处是Gridview这样的强大的server控件被丢弃了。

尽管是这样。可是我个人认为。这是回到了web开发的本质。

他的思想,与JSP,PHP等等变为一致。

Golabal.asax:路由表。这个部分就是所谓的全局路由表。在MVC框架中。之所以实现了MVC功能,一个重要的概念是路由表,该部分实现了地址訪问的动态。不再提供详细页面的訪问模式。

注意:给我的感觉是,记住在view文件夹和model文件夹中。加入子文件夹,每一个controller相应的view,都是一个文件夹下的view。

这个是MVC框架查找时自己主动搜索的。

2、webform和MVC的选择

这个部分的争论,我想从微软開始推出MVC框架后。大家就在不间断的讨论着,不同的人,给出的看法也是不同。就我个人而言。我认为MVC才是未来趋势。是世界最后大同的根本。虽然web form的模式。是微软开创性的创造。可是毕竟web开发不是微软首创,非常多时候,大势所趋而已。

我这里仅仅是想谈谈两者的思想出发点的区别:

  • webform模式。这个模式的思维基础,是微软在桌面开发中取得了前所未有的成功。这些成功,微软希望拷贝到网络开发中,何为form。就是窗体开发。这样的框架的逻辑是所见即所得+事件处理,微软希望可以将web实现为桌面开发的模式。可是网络开发的基础是HTML和HTTP协议,这两个部分带来的问题是HTML表现元素有限,而且仅仅可以通过form与后台server通信。另外,HTTP协议无状态,无法实现消息机制,为了解决这些问题,微软创造了新的开发模式,引入ASP.NETserver控件,实现了丰富的控件。通过postback回传机制,实现了事件模型,通过codebehind技术实现web页面与C#代码的分离。上述技术。的确非常成功,也确实非常大程度上简化了web的开发。可是随着发展,带来了问题,就是webform的开发基础是页面化的。这样的思维模式是说你开一个页面,然后在这个页面写响应事件。可是这样的模式对于频繁变化的web程序缺乏良好的复用性。而且,前端人员开发的界面。往往在合成时,须要重做,这是微软自己创造的困难。这是一种以Page为中心的开发思想。

  • MVC模式,这个模式的思维基础。是分工清晰,以Controller为核心。在开发时能够先做model再做Controller。最后做view,通过使用demo view实现。最后再替换美工的view。这样的模式变成了以数据为中心的开发思想。最大的优点是,这样的模式中每一个部分都能够灵活复用,最大限度的实现如今的各种网络须要。比方互联网和移动互联网。并且。其它的变成语言。在思想方面也基本採用这样的模式。这样的模式终于被时间证明。成为了标准思考方式和开发方式。微软提倡的桌面化开发,渐渐退却往日之光芒。

3、MVC的内部过程

这个部分是个很核心的问题,本文除了自己理解,还大量引用了其它相关的文章。

尝试解说清楚MVC的基本运转流程。

MVC的主体过程:

ASP.NET MVC流程解说

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZG9uZ2Rvbmdkb25nSkw=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

问题:

1、 浏览器请求的地址,并非详细的某个页面,如1234.aspx页面。而是controller/action方法。这是怎样做到的?

2、 Controller被訪问到以后。怎样找到详细的view进行返回的?

我个人的理解就是回答了上述的问题,也就解释清楚了MVC的基本框架。

第一个问题,浏览器请求地址的问题。MVC之所以可以找到详细的Controller是由于有一个route组件。实现了路由处理的功能。将请求转化为Controller的详细方法。须要注意该组件竟然是个独立组件。

Routing的作用:

1、 解析URL,识别其中的參数

2、 解析之后。调用详细的controller和action

比方首页地址是: localhost/home/index

我们发现訪问上面的地址,
最后会传递给 HomeController中名为index的action(即HomeController类中的index方法).

当然server端不会自己去实现这个功能, 
关键点就是在Global.asax.cs文件里的下列代码:

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 
            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );
 
        }
 
        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
        }

回来看我们的Url: localhost/home/index

localhost是域名,
所以首先要去掉域名部分: home/index

相应了上面代码中的这样的URL结构:{controller}/{action}/{id}

由于我们建立了这样的Url结构的识别规则,
所以可以识别出 Controller是home,action是index,id没有则为默认值"".

上述功能之所以可以实现,关键在MapRoute方法。尽管MapRoute方法是RouteCollection对象的方法,可是却被放置在System.Web.Mvc程序集中,
假设你的程序仅仅引用了System.Web.Routing,
那么RouteCollection对象是不会有MapRoute方法的.
可是假设你同又引用了System.Web.Mvc,
则在mvc的dll中为RouteCollection对象加入了扩展方法:

       public static void IgnoreRoute(this RouteCollection routes, string url);
        public static void IgnoreRoute(this RouteCollection routes, string url, object constraints);
        public static Route MapRoute(this RouteCollection routes, string name, string url);
        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults);
        public static Route MapRoute(this RouteCollection routes, string name, string url, string[] namespaces);
        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints);
        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, string[] namespaces);
        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces);

RouteCollection是一个集合,他的每一项应该是一个Route对象.
可是我们使用MapRoute时并没有创建这个对象,
这是由于当我们将MapRoute方法须要的參数传入时,
在方法内部会依据參数创建一个Route对象:

        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
            if (routes == null) {
                throw new ArgumentNullException("routes");
            }
            if (url == null) {
                throw new ArgumentNullException("url");
            }
 
            Route route = new Route(url, new MvcRouteHandler()) {
                Defaults = new RouteValueDictionary(defaults),
                Constraints = new RouteValueDictionary(constraints)
            };
 
            if ((namespaces != null) && (namespaces.Length > 0)) {
                route.DataTokens = new RouteValueDictionary();
                route.DataTokens["Namespaces"] = namespaces;
            }
 
            routes.Add(name, route);
 
            return route;
        }

上面就是MapRoute方法的实现,
至于在创建Route对象时第二个參数是一个MvcRouteHandler,
它是一个实现了IRouteHandler接口的类. IRouteHandler十分简单仅仅有一个方法:

IHttpHandler GetHttpHandler(RequestContext requestContext);

參数是一个RequestContext
类实例,
这个类的结构也非常easy:

    public class RequestContext
    {
        public RequestContext(HttpContextBase httpContext, RouteData routeData);
 
        public HttpContextBase HttpContext { get; }
        public RouteData RouteData { get; }
    }

当中的一个属性RouteData就包括了Routing依据Url识别出来各种參数的值,
当中就有Controller和Action的值.

归根结底, ASP.NET MVC最后还是使用HttpHandler处理请求. ASP.NET MVC定义了自己的实现了IHttpHandler接口的Handler:MvcHandler, 
由于MvcRouteHandler的GetHttpHandler方法最后返回的就是MvcHandler.

MvcHandler的构造函数须要传入RequestContext
对象,
也就是传入了全部的全部须要的数据,
所以最后能够找到相应的Controller和Action,
已经各种參数.

(引用參考:http://www.cnblogs.com/zhangziqiu/archive/2009/02/28/ASPNET-MVC-2.html

(引用參考:http://www.cnblogs.com/zhangziqiu/archive/2009/03/11/Aspnet-MVC-3.html)

第二个问题:Controller找到了,Action也找到了。此时怎样哪?

以下分层次的总结Controller处理流程:

1. 页面处理流程

发送请求 –> UrlRoutingModule捕获请求 –>MvcRouteHandler.GetHttpHandler() –> MvcHandler.ProcessRequest()

2.MvcHandler.ProcessRequest() 处理流程:

使用工厂方法获取详细的Controller –> Controller.Execute() –>
释放Controller对象

3.Controller.Execute() 处理流程

获取Action –>
调用Action方法获取返回的ActionResult –>
调用ActionResult.ExecuteResult() 方法

4.ActionResult.ExecuteResult() 处理流程

获取IView对象->
依据IView对象中的页面路径获取Page类->
调用IView.RenderView() 方法(内部调用Page.RenderView方法)

通过对MVC源码的分析,我们了解到Controller对象的职责是传递数据,获取View对象(实现了IView接口的类),通知View对象显示.View对象的作用是显示.尽管显示的方法RenderView()是由Controller调用的,可是Controller不过一个"指挥官"的作用,
详细的显示逻辑仍然在View对象中.须要注意IView接口与详细的ViewPage之间的联系.在Controller和View之间还存在着IView对象.对于ASP.NET程序提供了WebFormView对象实现了IView接口.WebFormView负责依据虚拟文件夹获取详细的Page类,然后调用Page.RenderView().

引用參考:(Http://www.cnblogs.com/zhangziqiu/archive/2009/03/11/Aspnet-MVC-3.html

说到这里。相信非常多人開始似乎明确了,又似乎不明确了,以下我做进一步的解说,先看一下。通常Controller的实现例如以下:

    public class HomeController:Controller
    {
        public ActionResult Index()
      {
            Return View(“Index”);
}
    }

先看看关键类ActionResult。这个返回值。体现了微软精心设计。为什么做这么个类,事实上本质而言,微软希望这个action能够返回很多其它内容,而不不过view。

类名

抽象类

父类

功能

ContentResult

依据内容的类型和编码,数据内容.

EmptyResult

空方法.

FileResult

abstract

写入文件内容,详细的写入方式在派生类中.

FileContentResult

FileResult

通过文件byte[]
写入文件.

FilePathResult

FileResult

通过文件路径写入文件.

FileStreamResult

FileResult

通过文件Stream
写入文件.

HttpUnauthorizedResult

抛出401错误

JavaScriptResult

返回javascript文件

JsonResult

返回Json格式的数据

RedirectResult

使用Response.Redirect重定向页面

RedirectToRouteResult

依据Route规则重定向页面

ViewResultBase

abstract

调用IView.Render()

PartialViewResult

ViewResultBase

调用父类ViewResultBase
的ExecuteResult方法. 

重写了父类的FindView方法. 

寻找用户控件.ascx文件

ViewResult

ViewResultBase

调用父类ViewResultBase
的ExecuteResult方法. 

重写了父类的FindView方法. 

寻找页面.aspx文件

这里我们主要解说viewResult的作用。

在ASP.NETMVC中,ViewResult用的最多。Controller有一个View方法,它来实例化一个ViewResult对象,并返回。

以下是View方法:

protected internal virtual ViewResult View(string viewName, string masterName, object model) {
    if (model != null) {
        ViewData.Model = model;
    }     return new ViewResult {
        ViewName = viewName,
        MasterName = masterName,
        ViewData = ViewData,
        TempData = TempData
    };
}

ViewResult类的ExecuteResult方法的详细參考例如以下:

public override void ExecuteResult(ControllerContext context) {
    if (context == null) {
        throw new ArgumentNullException("context");
    }
    if (String.IsNullOrEmpty(ViewName)) {
        ViewName = context.RouteData.GetRequiredString("action");
    }
    ViewEngineResult result = null;
    if (View == null) {
        result = FindView(context);  // 非常关键。找到详细的view
        View = result.View;
    }
    ViewContext viewContext = new ViewContext(context, View, ViewData, TempData);
// 非常关键,渲染自己
    View.Render(viewContext, context.HttpContext.Response.Output);
    if (result != null) {
        result.ViewEngine.ReleaseView(context, View);
    }
}

那么怎样FindView哪?详细例如以下:

rotectedoverrideViewEngineResult FindView(ControllerContext context) {

    ViewEngineResult result =ViewEngineCollection.FindView(context, ViewName, MasterName);

    if (result.View !=
null) {

        return result;

    }



    //we need to generate an exception containing all the locations we searched

   StringBuilder locationsText =
new StringBuilder();

    foreach (string location
in result.SearchedLocations) {

        locationsText.AppendLine();

        locationsText.Append(location);

    }

    throw
new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture,

    MvcResources.Common_ViewNotFound,ViewName, locationsText));

}

从ViewResult类的FindView方法中,得知ViewEngineResult是通过ViewEngineCollection的FindView得到的。而ViewEngineCollection正是ViewEngines的静态属性Engines,Engines返回一个仅仅有一个WebFormViewEngine类型实例的一个集合。所以。ViewEngineResult会是调用WebFormViewEngine类的FindView方法返回的结果。

假设ViewEngins的静态属性Engines有多个ViewEngine提供。那么就依次遍历它们直到找到第一个不为空的ViewEngineResult为止。这样我们就能够在同一个MVC站点中使用多种视图引擎了。

静态类ViewEngines的描写叙述例如以下:

public static class ViewEngines
 {
  private static readonly ViewEngineCollection _engines = new ViewEngineCollection { new WebFormViewEngine(), new RazorViewEngine() };
   
      public static ViewEngineCollection Engines
    {
        get { return _engines;}
     }
 }
  
  public class ViewEngineCollection : Collection<IViewEngine>
 {
     //其它成员
 public virtual ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName);
 public virtual ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName);
 }

从上述样例能够看出,起始微软为我们提供了两个ViewEngine, WebFormViewEngine和RazorViewEngine,WebFormViewEngine相应的是ASPX界面,RazorViewEngine相应的是.cshtml/.vbhtml引擎

此外,这里有一个隐藏非常深的概念,似乎非常多书都没讲清楚。每个引擎都会相应一个view。作为页面渲染使用。对于viewengine做进一步的解释,就是说,为什么一个view其中的<%%>之类的界面元素最后能够变成html。就是这些引擎在起作用。他们的内部实现,能够提供类似正則表達式或者是页面parsing的方法,完毕页面字符串解析。从而转换为相应的html,再response给client浏览器。

微软提供的两种viewengine和view例如以下:

RazorViewEngine和Razorview

(參考引用:http://www.cnblogs.com/artech/archive/2012/09/05/razor-view-engine-02.html)

WebformViewengine和Webformview

通过上边的讲述。主要的概念已经讲清楚了,假设希望实现自己的viewengine,能够查看一下微软參考实现是怎样做到的,然后我们就能够防治自己的viewengine了。这里便须要进一步说明的是。为什么MVC须要viewengine。而WEBFORM不须要,是由于,微软的webform是直接通过IHttphandler处理了,也就是说ASP.NETWEBFORM模式中的HTTPHANDLER完毕了事件处理和页面显示的双重功能。而ASP.NETMVC没有事件处理,因此页面显示被划到了viewengine其中实现了。事件处理。被controller替换处理了。

微软的Razorview和Webformview本质上是实现于IView接口,而WebformViewengine和Webformview本质上是实现于IViewEngine

以下介绍他们的实现逻辑:

public interface IView
   2: {    
   3:     void Render(ViewContext viewContext, TextWriter writer);
   4: }
   5:  
   6: public class ViewContext : ControllerContext
   7: {
   8:     //其它成员
   9:     public virtual bool ClientValidationEnabled { get; set; }
  10:     public virtual bool UnobtrusiveJavaScriptEnabled { get; set; }
  11:  
  12:     public virtual TempDataDictionary TempData { get; set; }    
  13:     [Dynamic]
  14:     public object                     ViewBag { [return: Dynamic] get; }
  15:     public virtual ViewDataDictionary ViewData { get; set; }
  16:     public virtual IView              View { get; set; }
  17:     public virtual TextWriter         Writer { get; set; }
  18: }
  19:  
  20: public abstract class HttpResponseBase
  21: {
  22:     //其它成员
  23:     public virtual TextWriter Output { get; set; }
  24: }
 
 
1: public interface IViewEngine
   2: {    
   3:     ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache);
   4:     ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache);
   5:     void ReleaseView(ControllerContext controllerContext, IView view);
   6: }
1: public class ViewEngineResult
   2: {    
   3:     public ViewEngineResult(IEnumerable<string> searchedLocations);
   4:     public ViewEngineResult(IView view, IViewEngine viewEngine);
   5:    
   6:     public IEnumerable<string> SearchedLocations { get; }
   7:     public IView               View { get; }
   8:     public IViewEngine         ViewEngine { get; }
   9: }
1: public class ViewResult : ViewResultBase
   2: {    
   3:     protected override ViewEngineResult FindView(ControllerContext context);
   4:     public string MasterName { get; set; }
   5: }
   6:  
   7: public abstract class ViewResultBase : ActionResult
   8: {   
   9:     public override void ExecuteResult(ControllerContext context);
  10:     protected abstract ViewEngineResult FindView(ControllerContext context);
  11:   
  12:     public object                     Model { get; }
  13:     public TempDataDictionary         TempData { get; set; }    
  14:     [Dynamic]
  15:     public object                     ViewBag { [return: Dynamic] get; }
  16:     public ViewDataDictionary         ViewData { get; set; }   
  17:     public string                     ViewName { get; set; }
  18:     public ViewEngineCollection       ViewEngineCollection { get; set; }
  19:     public IView                      View { get; set; }
  20: }

(參考引用:http://www.cnblogs.com/artech/archive/2012/08/22/view-engine-01.html)

自己定义的View以及相关的Viewengine,參考例如以下:

public class StaticFileView:IView
   2: {
   3:     public string FileName { get; private set; }
   4:     public StaticFileView(string fileName)
   5:     {
   6:         this.FileName = fileName;
   7:     }
   8:     public void Render(ViewContext viewContext, TextWriter writer)
   9:     {
  10:         byte[] buffer;
  11:         using (FileStream fs = new FileStream(this.FileName, FileMode.Open))
  12:         { 
  13:             buffer = new byte[fs.Length];
  14:             fs.Read(buffer, 0, buffer.Length);
  15:         }
  16:         writer.Write(Encoding.UTF8.GetString(buffer));
  17:     }
  18: }
internal class ViewEngineResultCacheKey
   2: {
   3:     public string ControllerName { get; private set; }
   4:     public string ViewName { get; private set; }
   5:  
   6:     public ViewEngineResultCacheKey(string controllerName, string viewName)
   7:     {
   8:         this.ControllerName = controllerName ??

string.Empty;
   9:         this.ViewName = viewName ?? string.Empty;
  10:     }
  11:     public override int GetHashCode()
  12:     {
  13:         return this.ControllerName.ToLower().GetHashCode() ^ this.ViewName.ToLower().GetHashCode();
  14:     }
  15:  
  16:     public override bool Equals(object obj)
  17:     {
  18:         ViewEngineResultCacheKey key = obj as ViewEngineResultCacheKey;
  19:         if (null == key)
  20:         {
  21:             return false;
  22:         }
  23:         return key.GetHashCode() == this.GetHashCode();
  24:     }
  25: }
1: public class StaticFileViewEngine : IViewEngine
   2: {
   3:     private Dictionary<ViewEngineResultCacheKey, ViewEngineResult> viewEngineResults = new Dictionary<ViewEngineResultCacheKey, ViewEngineResult>();
   4:     private object syncHelper = new object();
   5:     public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
   6:     {
   7:         return this.FindView(controllerContext, partialViewName, null, useCache);
   8:     }
   9:  
  10:     public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
  11:     {
  12:         string controllerName = controllerContext.RouteData.GetRequiredString("controller");
  13:         ViewEngineResultCacheKey key = new ViewEngineResultCacheKey(controllerName, viewName);
  14:         ViewEngineResult result;
  15:         if (!useCache)
  16:         { 
  17:             result = InternalFindView(controllerContext, viewName, controllerName);
  18:             viewEngineResults[key] = result;
  19:             return result;
  20:         }
  21:         if(viewEngineResults.TryGetValue(key, out result))
  22:         {
  23:             return result;
  24:         }
  25:         lock (syncHelper)
  26:         {
  27:             if (viewEngineResults.TryGetValue(key, out result))
  28:             {
  29:                 return result;
  30:             }
  31:  
  32:             result = InternalFindView(controllerContext, viewName, controllerName);
  33:             viewEngineResults[key] = result;
  34:             return result;
  35:         }             
  36:     }
  37:  
  38:     private ViewEngineResult InternalFindView(ControllerContext controllerContext, string viewName, string controllerName)
  39:     {
  40:         string[] searchLocations = new string[]
  41:         {
  42:             string.Format( "~/views/{0}/{1}.shtml", controllerName, viewName),
  43:             string.Format( "~/views/Shared/{0}.shtml", viewName)
  44:         };
  45:  
  46:         string fileName = controllerContext.HttpContext.Request.MapPath(searchLocations[0]);
  47:         if (File.Exists(fileName))
  48:         {
  49:             return new ViewEngineResult(new StaticFileView(fileName), this);
  50:         }
  51:         fileName = string.Format(@"\views\Shared\{0}.shtml", viewName);
  52:         if (File.Exists(fileName))
  53:         {
  54:             return new ViewEngineResult(new StaticFileView(fileName), this);
  55:         }
  56:         return new ViewEngineResult(searchLocations);
  57:     }
  58:  
  59:     public void ReleaseView(ControllerContext controllerContext, IView view)
  60:     { }
  61: }
1: public class MvcApplication : System.Web.HttpApplication
   2: {
   3:     protected void Application_Start()
   4:     {
   5:         //其它操作
   6:         ViewEngines.Engines.Insert(0, new StaticFileViewEngine());
   7:     }
   8: }
1: public class HomeController : Controller
   2: {
   3:     public ActionResult ShowNonExistentView()
   4:     {
   5:         return View("NonExistentView");
   6:     }
   7:  
   8:     public ActionResult ShowStaticFileView()
   9:     {
  10:         return View();
  11:     }
  12: }

我们为Action方法ShowStaticFileView创建一个StaticFileView类型的View文件ShowStaticFileView.shtml(该View文件保存在“~/Views/Home”文件夹下,扩展名不是.cshtml,而是shtml),其内容就是例如以下一段完整的HTML。

   1: <!DOCTYPE html>
   2: <html>
   3:     <head>
   4:         <title>Static File View</title>
   5:     </head>
   6:     <body>
   7:         这是一个自己定义的StaticFileView。
   8:     </body>
   9: </html>

(參考引用:http://www.cnblogs.com/artech/archive/2012/08/23/view-engine-02.html

版权声明:本文博主原创文章,博客,未经同意不得转载。