Asp.net MVC source code analysis-actionresult findview

Source: Internet
Author: User

Next, I will go to Asp.net MVC source code analysis-In actionresult, viewengineresult result = viewenginecollection. findview (context, viewname, mastername) in viewresult. How did I find the view? Let's take a look at the findview method in viewenginecollection.

Return find (E => E. findview (controllercontext, viewname, mastername, true ),
E => E. findview (controllercontext, viewname, mastername, false ));

But there are a lot of things to do. Call an internal find method,

Private viewengineresult find (func <iviewengine, viewengineresult> cachelocator, func <iviewengine, viewengineresult> Locator ){
// First, look up using the cachelocator and do not track the searched paths in non-matching view Engines
// Then, look up using the normal locator and track the searched paths so that an error view engine can be returned
 Return find (cachelocator, tracksearchedpaths: false)
?? Find (locator, tracksearchedpaths: True );
}

Here, cachelocator = E. findview (controllercontext, viewname, mastername, true), locator = E. findview (controllercontext, viewname, mastername, false), it is also calling an internal find method,

Private viewengineresult find (func <iviewengine, viewengineresult> lookup, bool tracksearchedpaths) {// returns // 1st result // or list of searched paths (if tracksearchedpaths = true) // or null viewengineresult result; List <string> searched = NULL; If (tracksearchedpaths) {searched = new list <string> ();} foreach (iviewengine engine in combineditems) {If (engine! = NULL) {result = Lookup (engine); If (result. view! = NULL) {return result;} If (tracksearchedpaths) {searched. addrange (result. searchedlocations) ;}}}if (tracksearchedpaths) {// remove duplicate search paths since multiple view engines cocould have potentially looked at the same path return New viewengineresult (searched. distinct (). tolist ();} else {return NULL ;}}

Tracksearchedpaths indicates whether to record the cable receiving path,FirstCheck whether the view can be found. If the view cannot be found, record the query path here.. By the way, there is a findpartialview method in viewenginecollection that is consistent with the findview method logic..

Combineditems here is actually the engines attribute in viewengines. By default, only the webformviewengine and razorviewengine instances are supported. So it will traverse all iviewengines to find the view. To improve performance,We can remove an iviewengine that we don't need ., For example, when I use razor to develop MVC, I can remove webformviewengine to improve the performance. Add viewengines. Engines. removeat (0) to application_start );

The tracksearchedpaths parameter records the search path. What is the result? If the corresponding view is not found in iviewengine, the search path is recorded.

If (tracksearchedpaths ){
Searched. addrange (result. searchedlocations );
}

If all iviewengine is found, no view is found. If tracksearchedpaths is false, null is directly returned. Otherwise, a viewengineresult with no view is returned.

The results are as follows:

Now let's take a look at the findview method in the virtualpathproviderviewengine class:

Public Virtual viewengineresult findview (controllercontext, string viewname, string mastername, bool usecache) {If (controllercontext = NULL) {Throw new argumentnullexception ("controllercontext");} If. isnullorempty (viewname) {Throw new argumentexception (mvcresources. common_nullorempty, "viewname");} string [] viewlocationssearched; string [] masterlocationssearched; s Tring controllername = controllercontext. routedata. getrequiredstring ("controller"); string viewpath = getpath (controllercontext, viewlocationformats, callback, "viewlocationformats", viewname, controllername, _ cachekeyprefix_view, usecache, out viewlocationssearched ); string masterpath = getpath (controllercontext, masterlocationformats, areamasterlocationformats, "masterlocationform ATS ", mastername, controllername, _ cachekeyprefix_master, usecache, out masterlocationssearched); If (string. isnullorempty (viewpath) | (string. isnullorempty (masterpath )&&! String. Loads (mastername) {return New viewengineresult (viewlocationssearched. Union (masterlocationssearched);} return New viewengineresult (createview (controllercontext, viewpath, masterpath), this );}

A very important string viewpath = getpath (controllercontext, viewlocationformats, areaviewlocationformats, "viewlocationformats", viewname, controllername, _ cachekeyprefix_view, usecache, out viewlocationssearched); getpath is used to find viewpath and masterpath.

Private string getpath (controllercontext, string [] locations, string [] arealocations, string locationspropertyname, string name, string controllername, string cachekeyprefix, bool usecache, out string [] searchedlocations) {searchedlocations = _ emptylocations; If (string. isnullorempty (name) {return string. empty;} string areaname = areahelpers. getareaname (controllercontext. route Data); bool usingareas =! String. isnullorempty (areaname); List <viewlocation> viewlocations = getviewlocations (locations, (usingareas )? Arealocations: NULL); If (viewlocations. count = 0) {Throw new invalidoperationexception (string. format (cultureinfo. currentculture, mvcresources. callback, locationspropertyname);} bool namerepresentspath = isspecificpath (name); string cachekey = createcachekey (cachekeyprefix, name, (namerepresentspath )? String. Empty: controllername, areaname); If (usecache) {return viewlocationcache. getviewlocation (controllercontext. httpcontext, cachekey);} return (namerepresentspath )? Getpathfromspecificname (controllercontext, name, cachekey, ref searchedlocations): getpathfromgeneralname (controllercontext, viewlocations, name, controllername, areaname, cachekey, ref searchedlocations );}

String areaname = areahelpers. getareaname (controllercontext. routedata );
Bool usingareas =! String. isnullorempty (areaname );
Usingareas is false by default. The getviewlocations method returns a set of viewlocations.CodeSimple. For example, reset it in razorviewengine.

Viewlocationformats = new [] {
"~ /Views/{1}/{0}. cshtml ",
"~ /Views/{1}/{0}. vbhtml ",
"~ /Views/shared/{0}. cshtml ",
"~ /Views/shared/{0}. vbhtml"
};

Add the current controller as home and action as index,

Then, the actual search path will be

"~ /Views/home/index. cshtml ",
"~ /Views/home/index. vbhtml ",
"~ /Views/shared/index. cshtml ",
"~ /Views/shared/index. vbhtml"

ActuallyOur general project is either C # Or VB, so viewlocationformats can remove two elements to improve performance..

Bool namerepresentspath = isspecificpath (name) indicates whether our viewname is ~ And.

String cachekey = createcachekey (cachekeyprefix, name, (namerepresentspath )? String. Empty: controllername, areaname); Create a cache key.

If (usecache ){
Return viewlocationcache. getviewlocation (controllercontext. httpcontext, cachekey );
}

Viewpath is returned from the cache. By default, viewlocationcache = new defaultviewlocationcache ()

The main method of defaultviewlocationcache is as follows:

Public String getviewlocation (httpcontextbase httpcontext, string key ){
If (httpcontext = NULL ){
Throw new argumentnullexception ("httpcontext ");
}
Return (string) httpcontext. cache [Key];
}
Public void insertviewlocation (httpcontextbase httpcontext, string key, string virtualpath ){
If (httpcontext = NULL ){
Throw new argumentnullexception ("httpcontext ");
}
Httpcontext. cache. insert (Key, virtualpath, null/* dependencies */, cache. noabsoluteexpiration, timespan );
}

Very simple.

Now let's go back to the getpath method. If you don't need to cache, there will be only the last sentence.

Return (namerepresentspath )?
Getpathfromspecificname (controllercontext, name, cachekey, ref searchedlocations ):
Getpathfromgeneralname (controllercontext, viewlocations, name, controllername, areaname, cachekey, ref searchedlocations );

The two methods are implemented as follows:

Private string getpathfromgeneralname (controllercontext, list <viewlocation> locations, string name, string controllername, string areaname, string cachekey, ref string [] searchedlocations) {string result = string. empty; searchedlocations = new string [locations. count]; for (INT I = 0; I <locations. count; I ++) {viewlocation location = locations [I]; string virtualpath = location. f Ormat (name, controllername, areaname); If (fileexists (controllercontext, virtualpath) {searchedlocations = _ emptylocations; Result = virtualpath; viewlocationcache. insertviewlocation (controllercontext. httpcontext, cachekey, result); break;} searchedlocations [I] = virtualpath;} return result;} private string getpathfromspecificname (controllercontext, string name, String cache Key, ref string [] searchedlocations) {string result = Name; If (! (Filepathissupported (name) & fileexists (controllercontext, name) {result = string. empty; searchedlocations = new [] {name};} viewlocationcache. insertviewlocation (controllercontext. httpcontext, cachekey, result); return result ;}

Both methods call a common method fileexists. fileexists is an inline function that directly calls virtualpathprovider. fileexists (virtualpath). By default, virtualpathprovider = hostingenvironment. virtualpathprovider. But what is actually called isBuildmanager. getobjectfactory (virtualpath, false )! = NULLWe will ignore it here for how it checks the path. Call the filepathissupported method in the getpathfromspecificname method to check the viewname extension.
Here we can complete the search for viewpath.

 

Now let's go back to findview,

If (string. isnullorempty (viewpath) | (string. isnullorempty (masterpath )&&! String. isnullorempty (mastername ))){
Return new viewengineresult (viewlocationssearched. Union (masterlocationssearched ));
}

This sentence is simple. Return new viewengineresult ( createview (controllercontext, viewpath, masterpath), this); this sentence returns a viewengineresult. The viewengineresult constructor is also very simple. Now let's take a look at the createview method. The specific implementation of razorviewengine and webformviewengine is as follows:

Protected override iview createview (controllercontext, string viewpath, string masterpath ){
VaR view = new razorview (controllercontext, viewpath,
Layoutpath: masterpath, runviewstartpages: True, viewstartfileextensions: fileextensions, viewpageactivator: viewpageactivator );
Return view;
}
Protected override iview createview (controllercontext, string viewpath, string masterpath ){
Return new webformview (controllercontext, viewpath, masterpath, viewpageactivator );
}

Now we have successfully found the view.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.