Implement Server.Transfer () similar functionality in an ASP. NET MVC Application

Source: Internet
Author: User

In an ASP. NET MVC application, if you use the Server.Transfer () method to forward a request to a different path or an HTTP handler for processing, a "error occurred while performing a child request for XXX" will be thrown The HttpException exception. And inside the method that finally implements the Server.Transfer () operation, I see a few lines of code.

is Page) {        new HttpException (string. Empty);}   

Obviously, within a method, all IHttpHandler are treated as page types. Throws an exception if the incoming handler is not of the page type! Even if your incoming URL or IHttpHandler corresponds to a physical ashx file, it is no exception. And this approach has not changed under the framework of. NET 4.5.

We know that in the ASP. All HTTP requests are processed from the IHttpHandler ProcessRequest () method In addition to WebService, and in MVC mode This gives us the conditions that are similar to Server.Transfer () in our own implementation. We just have to get an instance of the IHttpHandler that is used to process the new request and make the appropriate changes to the context of the request so that we can call ProcessRequest to force the processing of the request to be executed in the new IHttpHandler.

In an ASP. NET MVC program, the IHttpHandler of processing the request is obtained from the Iroutehandler Gethttphandler () method, so in order to get a new handler from this method, we must create a new routing request context information " RequestContext ".

  First step: Get the route instance where the target request handler is located and create a new routing data (Routedata):

There are two ways to get a routed instance, one from the routing table based on the route name, and one to create a new route instance based on the URL, and the route handler. In both of these ways, you must give explicit values for the route parameters that are used to determine the destination URL for the route.

First approach: Generate route data based on route name and value

 Public voidToroute (stringRouteName,Objectvalues) {            //Get the routing instance            varRoute =Routetable.routes[routename]; if(Route = =NULL)                Throw NewException (string. Format ("a route named \ ' {0}\ ' does not exist in the routing table", RouteName)); //Creating routing Data            varRoutedata =NewRoutedata (Route,NewMvcroutehandler ()); //Add route parameter/value            foreach(varPairinch NewRouteValueDictionary (values)) {Routedata.values[pair. Key]=pair.            Value;        } Route (Routedata); }

The second way: Generate route data based on the given URL and value. ( in an ASP. NET MVC application, the implementation of Iroutehandler is System.Web.Mvc.MvcRouteHandler)

 Public voidTourl (stringUrlObjectvalues) {            //To create a route handler instance            varRoutehandler =NewMvcroutehandler (); //Creating routing Data            varRoutedata =NewRoutedata (NewRoute (URL, routehandler), Routehandler); //Add route parameter/value            foreach(varPairinch NewRouteValueDictionary (values)) {Routedata.values[pair. Key]=pair.            Value;        } Route (Routedata); }

Step Two: Create a new routing request context information (RequestContext), override the internal path, get the IHttpHandler, and call its ProcessRequest method

voidRoute (Routedata routedata) {varRequestContext =NewRequestContext (Context, routedata); //overriding the internal request path            varNewPath = RouteData.Route.GetVirtualPath (RequestContext,NULL).            virtualpath;            RequestContext.HttpContext.RewritePath (NewPath); //get handlers, process requestsIHttpHandler handler =RouteData.RouteHandler.GetHttpHandler (RequestContext); if(Handler = =NULL)                Throw NewException ("failed to get IHttpHandler from the specified route"); Handler.        ProcessRequest (HttpContext.Current); }

The complete implementation code:

usingSYSTEM.WEB.MVC; usingSystem.Web.Routing;  Public classRequestrouter {ReadOnlyhttpcontextbase _context;  Publichttpcontextbase Context {Get{return  This. _context;} }         PublicRequestrouter (httpcontextbase context) { This. _context =context; }        voidRoute (Routedata routedata) {varRequestContext =NewRequestContext (Context, routedata); //overriding the internal request path            varNewPath = RouteData.Route.GetVirtualPath (RequestContext,NULL).            virtualpath;            RequestContext.HttpContext.RewritePath (NewPath); //get handlers, process requestsIHttpHandler handler =RouteData.RouteHandler.GetHttpHandler (RequestContext); if(Handler = =NULL)                Throw NewException ("failed to get IHttpHandler from the specified route"); Handler.        ProcessRequest (HttpContext.Current); }         Public voidToroute (stringRouteName,Objectvalues) {            //Get the routing instance            varRoute =Routetable.routes[routename]; if(Route = =NULL)                Throw NewException (string. Format ("a route named \ ' {0}\ ' does not exist in the routing table", RouteName)); //Creating routing Data            varRoutedata =NewRoutedata (Route,NewMvcroutehandler ()); //Add route parameter/value            foreach(varPairinch NewRouteValueDictionary (values)) {Routedata.values[pair. Key]=pair.            Value;        } Route (Routedata); }         Public voidTourl (stringUrlObjectvalues) {            //To create a route handler instance            varRoutehandler =NewMvcroutehandler (); //Creating routing Data            varRoutedata =NewRoutedata (NewRoute (URL, routehandler), Routehandler); //Add route parameter/value            foreach(varPairinch NewRouteValueDictionary (values)) {Routedata.values[pair. Key]=pair.            Value;        } Route (Routedata); }    }

Step three: Forward the request in the action of the Controller

 public   ActionResult Index () { var  routerequest =  Requestrouter (    HttpContext); Routerequest.toroute (  default  , new  {controller =  " home  " , action =  " about  "   return  new   Emptyresult ();}  

In this way, after requesting the index action method in the controller above, the request is forwarded to the Home controller's about operation method, and all request-related data (forms,querystrings) is preserved. However, changes made to ViewData and viewbag in the action that forwarded the request cannot be persisted because a new controller instance is being executed.

Implement Server.Transfer () similar functionality in an ASP. NET MVC Application

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.