欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET MVC 4 视图页去哪里儿

程序员文章站 2024-01-30 19:09:10
这里特别感谢 swagon 提到了displaymodeprovider,所以才有了本篇博客,也使我对【view的呈现】中寻找视图页的过程有了清晰的认识!   前戏   在mvc...
这里特别感谢 swagon 提到了displaymodeprovider,所以才有了本篇博客,也使我对【view的呈现】中寻找视图页的过程有了清晰的认识!

 

前戏

 

在mvc中,执行完action之后,会返回一个actionresult对象,之后再执行该对象的executeresult方法,这也就是【view的呈现】的入口!

 

【view的呈现】包括了:根据模版去寻找请求的视图页、编译视图页、再执行视图页的内容。本篇就来介绍寻找视图页的详细过程,其中涉及到了mvc 4的一个新特性--“手机视图页”

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

public abstract class viewresultbase : actionresult

{

    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)

        {

            //通过视图引擎去创建视图对象,并将视图对象和该视图相关的信息封装在viewengineresult对象中。

            result = findview(context);

            view = result.view;

        }

 

        textwriter writer = context.httpcontext.response.output;

        viewcontext viewcontext = new viewcontext(context, view, viewdata, tempdata, writer);

        view.render(viewcontext, writer);

 

        if (result != null)

        {

            result.viewengine.releaseview(context, view);

        }

    }

}

 

public class viewresult : viewresultbase

{

    protected override viewengineresult findview(controllercontext context)

    {

        //寻找当前请求的视图页,如果能找到则创建视图对象。

        //遍历每个视图引擎(默认有两个webformengine、razorviewengine),并执行每一个视图引擎的findview方法。

        viewengineresult result = viewenginecollection.findview(context, viewname, mastername);

        //如果创建了视图对象,即:指定路径中存在相匹配的视图页(.cshtml文件)。

        if (result.view != null)

        {

            return result;

        }

        //没有创建视图对象,即:指定路径中不存在相匹配的视图页(.cshtml文件)。

        stringbuilder locationstext = new stringbuilder();

        foreach (string location in result.searchedlocations)

        {

            locationstext.appendline();

            locationstext.append(location);

        }

        throw new invalidoperationexception(string.format(cultureinfo.currentculture,

                                                          mresources.common_viewnotfound, viewname, locationstext));

    }

}

  viewengineresult result = viewenginecollection.findview(context, viewname, mastername);则是遍历每个视图引擎(默认有两个webformengine、razorviewengine),并执行每一个视图引擎的findview方法。

注:在执行视图引擎的findview方法时,先按照从缓存表中找是否存在请求的视图页,如果没有的话,再进行一次寻找!

 

 

 

 下面以razorviewengine为例:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

public abstract class virtualpathproviderviewengine : iviewengine

{

    //usecache先是true,该方法返回的是null。则让usecache=false,再执行一遍。即:先通过缓存去找,如果没有找到的话,就正经的去找。

    public virtual viewengineresult findview(controllercontext controllercontext, string viewname, string mastername, bool usecache)

    {

        if (controllercontext == null)

        {

            throw new argumentnullexception("controllercontext");

        }

        if (string.isnullorempty(viewname))

        {

            throw new argumentexception(mvcresources.common_nullorempty, "viewname");

        }

 

        string[] viewlocationssearched;

        string[] masterlocationssearched;

 

        string controllername = controllercontext.routedata.getrequiredstring("controller");

        //获取视图的路径,这里就是咱们本篇博文的内容的入口点!!!!!!!!!!!!!!!!!!!

        //viewlocationformats、areaviewlocationformats定义在派生类razorviewengine类中。

        //viewlocationformats:"~/views/{1}/{0}.cshtml","~/views/{1}/{0}.vbhtml", "~/views/shared/{0}.cshtml","~/views/shared/{0}.vbhtml"

        //areaviewlocationformats:"~/areas/{2}/views/{1}/{0}.cshtml", "~/areas/{2}/views/{1}/{0}.vbhtml", "~/areas/{2}/views/shared/{0}.cshtml","~/areas/{2}/views/shared/{0}.vbhtml"

        string viewpath = getpath(controllercontext, viewlocationformats, areaviewlocationformats, "viewlocationformats", viewname, controllername, cachekeyprefixview, usecache, out viewlocationssearched);

         

         

        string masterpath = getpath(controllercontext, masterlocationformats, areamasterlocationformats, "masterlocationformats", mastername, controllername, cachekeyprefixmaster, usecache, out masterlocationssearched);

 

        if (string.isnullorempty(viewpath) || (string.isnullorempty(masterpath) && !string.isnullorempty(mastername)))

        {

            return new viewengineresult(viewlocationssearched.union(masterlocationssearched));

        }

 

        return new viewengineresult(createview(controllercontext, viewpath, masterpath), this);

    }

}

啪啪啪

 

  getpath方法在寻找【视图页】时,首先将当前请求的controller和action的名称添加到地址格式化器中,这样就有了要寻找的地址(们),之后就来检查格式化后的地址是否真的存在指定的【视图页】。如果是通过手机端来请求,则会对格式化之后的地址进行再进行处理(如:index.cshtml修改为index.mobile.cshtml),之后再检查新地址下是否存在【视图页】。

 

注:默认情况下会先检查是否为手机端访问!