ASP.NET MVC में Server.Transfer का अनुकरण कैसे करें?


124

ASP.NET MVC में आप आसानी से एक पुनर्निर्देशन ActionResult लौटा सकते हैं:

 return RedirectToAction("Index");

 or

 return RedirectToRoute(new { controller = "home", version = Math.Random() * 10 });

यह वास्तव में एक HTTP रीडायरेक्ट देगा, जो सामान्य रूप से ठीक है। हालाँकि, Google विश्लेषिकी का उपयोग करते समय यह बड़े मुद्दों का कारण बनता है क्योंकि मूल रेफ़र खो जाता है इसलिए Google नहीं जानता कि आप कहाँ से आए हैं। यह किसी भी खोज इंजन शब्द जैसी उपयोगी जानकारी खो देता है।

एक साइड नोट के रूप में, इस विधि में किसी भी पैरामीटर को हटाने का लाभ है जो अभियानों से आया हो सकता है लेकिन फिर भी मुझे सर्वर साइड पर कब्जा करने की अनुमति देता है। उन्हें क्वेरी स्ट्रिंग में छोड़ने से लोग बुकमार्क या ट्विटर या ब्लॉग को लिंक करते हैं जो उन्हें नहीं करना चाहिए। मैंने इसे कई बार देखा है जहाँ लोगों ने हमारी साइट के लिंक को अभियान आईडी से लिंक किया है।

वैसे भी, मैं साइट पर आने वाली सभी यात्राओं के लिए एक 'गेटवे' कंट्रोलर लिख रहा हूं, जिसे मैं अलग-अलग जगहों या वैकल्पिक संस्करणों पर रीडायरेक्ट कर सकता हूं।

अभी के लिए मैं Google के लिए अब (आकस्मिक बुकमार्क करने की तुलना में) अधिक परवाह करता हूं, और मैं किसी ऐसे व्यक्ति को भेजने में सक्षम होना चाहता हूं जो /उस पृष्ठ पर जाता है /home/7, जो अगर वे गए थे , जो एक होमपेज का संस्करण 7 है।

जैसा कि मैंने पहले कहा था कि अगर मैं ऐसा करता हूं तो मैं संदर्भकर्ता का विश्लेषण करने के लिए Google की क्षमता खो देता हूं:

 return RedirectToAction(new { controller = "home", version = 7 });

मैं वास्तव में क्या चाहता हूँ a

 return ServerTransferAction(new { controller = "home", version = 7 });

जो मुझे एक क्लाइंट साइड पुनर्निर्देशित किए बिना वह दृश्य मिलेगा। मुझे नहीं लगता कि हालांकि ऐसा कुछ मौजूद है।

वर्तमान में सबसे अच्छी बात जो मैं HomeController.Index(..)अपने GatewayController.Indexएक्शन के लिए पूरे कंट्रोलर लॉजिक की नकल कर सकता हूं । इसका मतलब है कि मुझे इसमें 'Views/Home'प्रवेश 'Shared'करना था इसलिए यह सुलभ था। इसके लिए अवश्य ही एक बेहतर तरीका होना चाहिए??..


वास्तव में क्या है ServerTransferActionकि आप दोहराने की कोशिश कर रहे थे? क्या वह वास्तविक चीज है? (इस पर कोई जानकारी नहीं मिली ... सवाल के लिए धन्यवाद, btw, नीचे जवाब शानदार है)
jleach

Server.Transfer (...) देखें। यह मूल रूप से सर्वर साइड पर एक 'रिडायरेक्ट' करने का एक तरीका है जहां क्लाइंट रिडायरेक्ट किए गए पेज को क्लाइंट साइड रीडायरेक्ट के बिना प्राप्त करता है। आमतौर पर आधुनिक रूटिंग के साथ इसकी अनुशंसा नहीं की जाती है।
सिमोन_विवर

1
"ट्रांसफ़रिंग" एक पुरातन ASP.NET सुविधा है जो अब राउटिंग का उपयोग करके सही कंट्रोलर एक्शन में सीधे जाने की क्षमता के कारण MVC में आवश्यक नहीं है । देखें इस उत्तर जानकारी के लिए।
नाइटऑवल

@ NightOwl888 हाँ निश्चित रूप से - लेकिन कभी-कभी व्यावसायिक तर्क के कारण भी यह आवश्यक / आसान है। मैंने यह देखने के लिए वापस देखा कि मैं इसका उपयोग कहां समाप्त करूंगा - (सौभाग्य से यह केवल एक ही स्थान पर था) - जहां मेरे पास एक होमपेज है जिसे मैं कुछ जटिल परिस्थितियों के लिए गतिशील होना चाहता था और इसलिए पर्दे के पीछे यह एक अलग मार्ग दिखाता है। निश्चित रूप से रूटिंग या रूट स्थितियों के पक्ष में जितना संभव हो उतना इसे टालना चाहते हैं - लेकिन कभी-कभी एक सरल ifबयान भी एक समाधान को लुभाने वाला होता है।
सिमोन_विवर

@Simon_Weaver - और उपवर्ग के साथ क्या गलत है RouteBaseताकि आप ifएक नियंत्रक से दूसरे नियंत्रक पर कूदने के लिए सब कुछ झुकने के बजाय अपना बयान वहां रख सकें ?
नाइटऑवल

जवाबों:


130

कैसे एक TransferResult वर्ग के बारे में? ( स्टैंस जवाब के आधार पर )

/// <summary>
/// Transfers execution to the supplied url.
/// </summary>
public class TransferResult : ActionResult
{
    public string Url { get; private set; }

    public TransferResult(string url)
    {
        this.Url = url;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        var httpContext = HttpContext.Current;

        // MVC 3 running on IIS 7+
        if (HttpRuntime.UsingIntegratedPipeline)
        {
            httpContext.Server.TransferRequest(this.Url, true);
        }
        else
        {
            // Pre MVC 3
            httpContext.RewritePath(this.Url, false);

            IHttpHandler httpHandler = new MvcHttpHandler();
            httpHandler.ProcessRequest(httpContext);
        }
    }
}

अपडेट किया गया: अब MVC3 ( साइमन पोस्ट से कोड का उपयोग करके) के साथ काम करता है । यह IIS7 + के एकीकृत पाइपलाइन के भीतर चल रहा है या नहीं, यह देखकर एमवीसी 2 में काम करना चाहिए

पूर्ण पारदर्शिता के लिए; हमारे उत्पादन वातावरण में हमने कभी भी TransferResult का सीधे उपयोग नहीं किया है। हम एक TransferToRouteResult का उपयोग करते हैं, जो बदले में कॉल TransferResult निष्पादित करता है। यहाँ वास्तव में मेरे उत्पादन सर्वर पर चल रहा है।

public class TransferToRouteResult : ActionResult
{
    public string RouteName { get;set; }
    public RouteValueDictionary RouteValues { get; set; }

    public TransferToRouteResult(RouteValueDictionary routeValues)
        : this(null, routeValues)
    {
    }

    public TransferToRouteResult(string routeName, RouteValueDictionary routeValues)
    {
        this.RouteName = routeName ?? string.Empty;
        this.RouteValues = routeValues ?? new RouteValueDictionary();
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        var urlHelper = new UrlHelper(context.RequestContext);
        var url = urlHelper.RouteUrl(this.RouteName, this.RouteValues);

        var actualResult = new TransferResult(url);
        actualResult.ExecuteResult(context);
    }
}

और अगर आप T4MVC का उपयोग कर रहे हैं (यदि नहीं ... तो!) यह एक्सटेंशन काम आ सकता है।

public static class ControllerExtensions
{
    public static TransferToRouteResult TransferToAction(this Controller controller, ActionResult result)
    {
        return new TransferToRouteResult(result.GetRouteValueDictionary());
    }
}

इस छोटे से रत्न का उपयोग आप कर सकते हैं

// in an action method
TransferToAction(MVC.Error.Index());

1
यह बहुत अच्छा काम करता है। एक अनन्त लूप के साथ समाप्त न होने के लिए सावधान रहें - जैसा कि मैंने गलत URL पास करके अपने पहले प्रयास में किया था। मैंने एक छोटे से संशोधन करके मार्ग मूल्य संग्रह को पारित करने की अनुमति दी, जिसमें दूसरों के लिए उपयोगी हो सकता है। ऊपर या नीचे पोस्ट किया गया ...
शमौन_वेर

अद्यतन: यह समाधान अच्छी तरह से काम करने के लिए लगता है, और हालांकि मैं इसे केवल एक बहुत ही सीमित क्षमता में उपयोग कर रहा हूं, अभी तक कोई भी समस्या नहीं मिली है
साइमन_वेअर

एक मुद्दा: POST से GET अनुरोध पर पुनर्निर्देशित नहीं किया जा सकता - लेकिन यह जरूरी नहीं कि एक बुरी चीज हो। हालांकि कुछ सावधान रहना चाहिए
साइमन_वेवर

2
@ ब्रैडलैनी: आप बस 'var urlHelper ...' और 'var url ...' लाइनों को हटा सकते हैं और 'url' को बाकी के लिए 'this.Url' से बदल सकते हैं और यह काम करता है। :)
माइकल उलमन

1
1: युग्मन / यूनिट परीक्षण / भविष्य की अनुकूलता। 2: mvc कोर / mvc नमूने कभी भी इस सिंगलटन का उपयोग नहीं करते हैं। 3: यह सिंगलटन एक थ्रेड (नल) में उपलब्ध नहीं है, या तो एक पूल थ्रेड या एक async प्रतिनिधि को डिफ़ॉल्ट के अलावा किसी अन्य संदर्भ पर कॉल किया जाता है, जैसे कि async एक्शन विधियों का उपयोग करते समय। 4: अनुकूलता प्रयोजनों के लिए, mvc उपयोगकर्ता कोड दर्ज करने से पहले संदर्भ के लिए इस सिंगलटन मान को सेट करता है।
सॉफ्टलिंय

47

संपादित करें: ASP.NET MVC 3 के साथ संगत होने के लिए अद्यतन किया गया

बशर्ते आप IIS7 का उपयोग कर रहे हों, ASP.NET MVC के लिए निम्न संशोधन काम करता है। मूल कोड के काम न करने के लिए @nitin और @andy को धन्यवाद।

4/11/2011 संपादित करें: TempData MVC 3 RTM के रूप में Server.TransferRequest के साथ टूट जाता है

अपवाद को फेंकने के लिए नीचे दिए गए कोड को संशोधित किया - लेकिन इस समय कोई अन्य समाधान नहीं।


यहाँ मेरा संशोधन मार्कस के स्टेन के मूल पद के संशोधित संस्करण पर आधारित है। मैंने रूट वैल्यू डिक्शनरी लेने के लिए एक अतिरिक्त कंस्ट्रक्टर जोड़ा - और इसे भ्रम से बचने के लिए MVCTransferResult का नाम दिया कि यह सिर्फ एक रीडायरेक्ट हो सकता है।

अब मैं निम्नलिखित को पुनर्निर्देशित कर सकता हूं:

return new MVCTransferResult(new {controller = "home", action = "something" });

मेरा संशोधित वर्ग:

public class MVCTransferResult : RedirectResult
{
    public MVCTransferResult(string url)
        : base(url)
    {
    }

    public MVCTransferResult(object routeValues):base(GetRouteURL(routeValues))
    {
    }

    private static string GetRouteURL(object routeValues)
    {
        UrlHelper url = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()), RouteTable.Routes);
        return url.RouteUrl(routeValues);
    }

    public override void ExecuteResult(ControllerContext context)
    {
        var httpContext = HttpContext.Current;

        // ASP.NET MVC 3.0
        if (context.Controller.TempData != null && 
            context.Controller.TempData.Count() > 0)
        {
            throw new ApplicationException("TempData won't work with Server.TransferRequest!");
        }

        httpContext.Server.TransferRequest(Url, true); // change to false to pass query string parameters if you have already processed them

        // ASP.NET MVC 2.0
        //httpContext.RewritePath(Url, false);
        //IHttpHandler httpHandler = new MvcHttpHandler();
        //httpHandler.ProcessRequest(HttpContext.Current);
    }
}

1
ऐसा लगता है कि MVC 3 RC में काम नहीं कर रहा है। HttpHandler.ProcessRequest () पर फेल, कहते हैं: 'HttpContext.SetSessionStateBehavior' को केवल 'HttpApplication.AcquestRequestState' ईवेंट के उठाए जाने से पहले ही लागू किया जा सकता है।
एंडी

मैंने अभी तक MVC3 को देखने के लिए कोई परिवर्तन नहीं किया है। मुझे बताएं कि क्या आपको कोई समाधान मिलता है
सिमोन_विवर

क्या Server.TransferRquest जैसा कि नितिन ने सुझाया है कि ऊपर वाला क्या करने की कोशिश कर रहा है?
पुरानी गीजर

हमें अशक्त और गिनती> 0 के लिए TempData की जांच करने की आवश्यकता क्यों है?
युरर्ट

आप नहीं करते हैं, लेकिन इसकी सिर्फ एक सुरक्षा सुविधा है, इसलिए यदि आप पहले से ही इसका उपयोग कर रहे हैं और इस पर भरोसा कर रहे हैं तो आप गायब होने पर अपने सिर को खरोंचने से बचे नहीं रहेंगे
Simon_Weaver


12

मुझे हाल ही में पता चला कि ASP.NET MVC Server.Transfer () का समर्थन नहीं करता है, इसलिए मैंने एक स्टब विधि (Default.aspx.cs से प्रेरित) बनाई है।

    private void Transfer(string url)
    {
        // Create URI builder
        var uriBuilder = new UriBuilder(Request.Url.Scheme, Request.Url.Host, Request.Url.Port, Request.ApplicationPath);
        // Add destination URI
        uriBuilder.Path += url;
        // Because UriBuilder escapes URI decode before passing as an argument
        string path = Server.UrlDecode(uriBuilder.Uri.PathAndQuery);
        // Rewrite path
        HttpContext.Current.RewritePath(path, false);
        IHttpHandler httpHandler = new MvcHttpHandler();
        // Process request
        httpHandler.ProcessRequest(HttpContext.Current);
    }

9

क्या आप केवल उस नियंत्रक का एक उदाहरण नहीं बना सकते हैं जिसे आप पुनर्निर्देशित करना चाहते हैं, जिस कार्य विधि को आप चाहते हैं, उसे लागू करें और फिर उसी का परिणाम लौटाएं? कुछ इस तरह:

 HomeController controller = new HomeController();
 return controller.Index();

4
नहीं, आपके द्वारा बनाया गया नियंत्रक उस पर अनुरोध और प्रतिक्रिया सेटअप जैसी चीजें ठीक से नहीं करेगा। जिसके चलते परेशानी हो सकती है।
जेफ वॉकर कोड रेंजर

मैं @JeffWalkerCodeRanger से सहमत हूं: संपत्ति सेट करने के बाद भी यही बात हैotherController.ControllerContext = this.ControllerContext;
T-moty

7

मैं एक अन्य नियंत्रक / कार्रवाई के लिए वर्तमान अनुरोध को फिर से रूट करना चाहता था, जबकि निष्पादन पथ को ठीक उसी तरह रखता था जैसे कि दूसरा नियंत्रक / कार्रवाई का अनुरोध किया गया था। मेरे मामले में, Server.Request काम नहीं करेगा क्योंकि मैं अधिक डेटा जोड़ना चाहता था। यह वास्तव में दूसरे HTTP GET / POST को निष्पादित करने वाले वर्तमान हैंडलर के बराबर है, फिर क्लाइंट को परिणाम स्ट्रीमिंग करता है। मुझे यकीन है कि इसे प्राप्त करने के बेहतर तरीके होंगे, लेकिन यहां मेरे लिए क्या काम करता है:

RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Public");
routeData.Values.Add("action", "ErrorInternal");
routeData.Values.Add("Exception", filterContext.Exception);

var context = new HttpContextWrapper(System.Web.HttpContext.Current);
var request = new RequestContext(context, routeData);

IController controller = ControllerBuilder.Current.GetControllerFactory().CreateController(filterContext.RequestContext, "Public");
controller.Execute(request);

आपका अनुमान सही है: मैंने इस कोड को डाला है

public class RedirectOnErrorAttribute : ActionFilterAttribute, IExceptionFilter

और मैं इसे डेवलपर्स को त्रुटियों को प्रदर्शित करने के लिए उपयोग कर रहा हूं, जबकि यह उत्पादन में एक नियमित पुनर्निर्देशन का उपयोग कर रहा होगा। ध्यान दें कि मैं अनुरोधों के बीच अपवाद डेटा पास करने के लिए ASP.NET सत्र, डेटाबेस, या कुछ अन्य तरीकों का उपयोग नहीं करना चाहता था।


7

एक सर्वर स्थानांतरण का अनुकरण करने के बजाय, MVC अभी भी वास्तव में एक Server.TransferRequest करने में सक्षम है :

public ActionResult Whatever()
{
    string url = //...
    Request.RequestContext.HttpContext.Server.TransferRequest(url);
    return Content("success");//Doesn't actually get returned
}

इसे स्पष्ट करने के लिए अपने उत्तर में कुछ पाठ जोड़ने के लिए स्वतंत्र महसूस करें।
व्लादिमीर पलंत

ध्यान दें कि इसके लिए MVCv3 और इसके बाद के संस्करण की आवश्यकता है।
Seph

5

बस अन्य नियंत्रक को उदाहरण दें और इसे निष्पादित करें क्रिया विधि।


इससे एड्रेस बार में वांछित URL नहीं दिखाई देगा
arserbin3

@ arserbin3 - न तो Server.Transfer होगा। यह आवश्यकता संभवतः इसलिए है क्योंकि मूल प्रश्न भी पोस्ट किया गया था।
रिचर्ड सैज़ले

2

आप अन्य नियंत्रक को नया कर सकते हैं और परिणाम को वापस करने की क्रिया विधि लागू कर सकते हैं। हालाँकि आपको अपने दृश्य को साझा किए गए फ़ोल्डर में रखने की आवश्यकता होगी।

मुझे यकीन नहीं है कि यह वही है जो आपको डुप्लिकेट से मतलब है लेकिन:

return new HomeController().Index();

संपादित करें

एक अन्य विकल्प हो सकता है कि आप अपना स्वयं का नियंत्रक निर्माण करें, इस तरह से आप यह निर्धारित कर सकते हैं कि किस नियंत्रक को बनाना है।


यह दृष्टिकोण हो सकता है, लेकिन यह काफी संदर्भ सही है लगता है - भले ही मैं hc.ControllerContext = this.ControllerContext कहता हूं। इसके अलावा यह ~ / दृश्य / गेटवे / 5.aspx के तहत देखने के लिए लगता है और यह नहीं मिलता है।
सिमोन_विवर 19

साथ ही आप सभी एक्शन फिल्टर्स खो देते हैं। आप शायद IController इंटरफ़ेस पर एक्सक्यूट विधि का उपयोग करने का प्रयास करना चाहते हैं जिसे आपके नियंत्रकों को लागू करना होगा। उदाहरण के लिए: ((IController) नया HomeController ())। Execute (...)। इस तरह से आप अभी भी एक्शन इन्वोकर पाइपलाइन में भाग लेते हैं। आपको वास्तव में यह पता लगाना होगा कि परीक्षा में पास होना क्या है ... परावर्तक वहाँ मदद कर सकता है :)
एंड्रयू स्टैंटन-नर्स

हां, मुझे एक नियंत्रक को नया बनाने का विचार पसंद नहीं है, मुझे लगता है कि आपके अपने नियंत्रक कारखाने को परिभाषित करना बेहतर है जो इसके लिए उचित विस्तार बिंदु की तरह लगता है। लेकिन मैं मुश्किल से इस ढांचे की सतह को खरोंच कर दिया है ताकि मैं रास्ता काट सकूं।
जोशबर्कर

1

क्या रूटिंग सिर्फ आपके लिए इस परिदृश्य का ध्यान नहीं रखती है? ऊपर वर्णित परिदृश्य के लिए, आप केवल एक मार्ग हैंडलर बना सकते हैं जिसने इस तर्क को लागू किया है।


इसकी प्रोग्रामेटिक स्थितियों के आधार पर। अर्थात अभियान १०० and देखने के लिए जा सकता है और २०० अभियान etc. देखने के लिए जा सकता है इत्यादि इत्यादि। रूटिंग के लिए बहुत जटिल है
सिमोन_विवर २9'०

4
राउटिंग के लिए यह भी जटिल क्यों है? कस्टम मार्ग बाधाओं के साथ क्या गलत है? stephenwalther.com/blog/archive/2008/08/07/…
इयान मर्सर

1

अभिव्यक्ति-आधारित रूटिंग का उपयोग करने वाले किसी भी व्यक्ति के लिए, ऊपर केवल TransferResult क्लास का उपयोग करके, यहां एक नियंत्रक एक्सटेंशन विधि है जो ट्रिक करती है और TempData को संरक्षित करती है। TransferToRouteResult के लिए कोई ज़रूरत नहीं है।

public static ActionResult TransferRequest<T>(this Controller controller, Expression<Action<T>> action)
    where T : Controller
{
     controller.TempData.Keep();
     controller.TempData.Save(controller.ControllerContext, controller.TempDataProvider);
     var url = LinkBuilder.BuildUrlFromExpression(controller.Request.RequestContext, RouteTable.Routes, action);
     return new TransferResult(url);
}

चेतावनी: यह एक त्रुटि का कारण लगता है 'SessionStateTempDataProvider वर्ग को सत्र स्थिति को सक्षम करने की आवश्यकता होती है' हालांकि यह वास्तव में अभी भी काम करता है। मुझे केवल अपने लॉग में यह त्रुटि दिखाई देती है। मैं त्रुटि लॉगिंग के लिए ELMAH का उपयोग कर रहा हूं और InProc और AppFabric के लिए यह त्रुटि प्राप्त कर रहा हूं
Simon_Weaver

1

Server.TransferRequestहै MVC में पूरी तरह से अनावश्यक । यह एक पुरातन विशेषता है जो केवल ASP.NET में आवश्यक थी क्योंकि अनुरोध सीधे एक पृष्ठ पर आया था और एक अनुरोध को दूसरे पृष्ठ पर स्थानांतरित करने का एक तरीका होने की आवश्यकता थी। ASP.NET (MVC सहित) के आधुनिक संस्करणों में एक रूटिंग इन्फ्रास्ट्रक्चर है जिसे वांछित संसाधन के लिए सीधे रूट के लिए अनुकूलित किया जा सकता है। अनुरोध को केवल एक नियंत्रक तक पहुंचाने के लिए इसे किसी अन्य नियंत्रक को स्थानांतरित करने की अनुमति देने का कोई मतलब नहीं है जब आप अनुरोध को सीधे नियंत्रक और इच्छित कार्रवाई पर जा सकते हैं।

यह अधिक है कि जब से आप मूल अनुरोध का जवाब दे रहे हैं, TempDataतो अनुरोध को सही स्थान पर भेजने के लिए किसी अन्य भंडारण में कुछ भी टिक करने की आवश्यकता नहीं है। इसके बजाय, आप मूल अनुरोध के साथ नियंत्रक कार्रवाई पर पहुंचते हैं। आप इस बात से भी निश्चिंत हो सकते हैं कि Google इस दृष्टिकोण को स्वीकार कर लेगा क्योंकि यह पूरी तरह से सर्वर की तरफ होता है।

जब आप दोनों से काफी कुछ कर सकते हैं IRouteConstraintऔर IRouteHandler, रूटिंग के लिए सबसे शक्तिशाली विस्तार बिंदु RouteBaseउपवर्ग है। इस वर्ग को आने वाले मार्गों और आउटगोइंग URL पीढ़ी दोनों प्रदान करने के लिए बढ़ाया जा सकता है, जो इसे URL के साथ काम करने और URL को निष्पादित करने वाली हर चीज के लिए एक बंद दुकान बनाता है।

तो, अपने दूसरे उदाहरण का पालन करने के लिए, से प्राप्त /करने के लिए /home/7, आपको बस एक मार्ग की आवश्यकता है जो उचित मार्ग मूल्यों को जोड़ता है।

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        // Routes directy to `/home/7`
        routes.MapRoute(
            name: "Home7",
            url: "",
            defaults: new { controller = "Home", action = "Index", version = 7 }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

लेकिन अपने मूल उदाहरण पर वापस जाने से जहां आपके पास एक यादृच्छिक पृष्ठ है, यह अधिक जटिल है क्योंकि मार्ग पैरामीटर रनटाइम पर नहीं बदल सकते हैं। तो, यह RouteBaseनिम्न के साथ एक उपवर्ग के साथ किया जा सकता है ।

public class RandomHomePageRoute : RouteBase
{
    private Random random = new Random();

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        RouteData result = null;

        // Only handle the home page route
        if (httpContext.Request.Path == "/")
        {
            result = new RouteData(this, new MvcRouteHandler());

            result.Values["controller"] = "Home";
            result.Values["action"] = "Index";
            result.Values["version"] = random.Next(10) + 1; // Picks a random number from 1 to 10
        }

        // If this isn't the home page route, this should return null
        // which instructs routing to try the next route in the route table.
        return result;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        var controller = Convert.ToString(values["controller"]);
        var action = Convert.ToString(values["action"]);

        if (controller.Equals("Home", StringComparison.OrdinalIgnoreCase) &&
            action.Equals("Index", StringComparison.OrdinalIgnoreCase))
        {
            // Route to the Home page URL
            return new VirtualPathData(this, "");
        }

        return null;
    }
}

जिसे रूटिंग में पंजीकृत किया जा सकता है जैसे:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        // Routes to /home/{version} where version is randomly from 1-10
        routes.Add(new RandomHomePageRoute());

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

उपरोक्त उदाहरण में ध्यान दें, यह भी समझ में आ सकता है कि उपयोगकर्ता द्वारा होम पेज संस्करण को रिकॉर्ड करते हुए कुकी को स्टोर किया जाए, ताकि जब वे वापस आएं तो उन्हें वही होम पेज संस्करण प्राप्त हो।

ध्यान दें कि इस दृष्टिकोण का उपयोग करके आप क्वेरी स्ट्रिंग मापदंडों को ध्यान में रखने के लिए रूटिंग को अनुकूलित कर सकते हैं (यह पूरी तरह से उन्हें डिफ़ॉल्ट रूप से अनदेखा करता है) और तदनुसार उचित नियंत्रक कार्रवाई के लिए मार्ग।

अतिरिक्त उदाहरण


क्या होगा अगर मैं किसी एक्शन में प्रवेश करने पर तुरंत ट्रांसफर नहीं करना चाहता, बल्कि उस एक्शन को कुछ काम करने दें और फिर सशर्त रूप से किसी अन्य एक्शन में ट्रांसफर कर दें। ट्रांसफर टारगेट पर सीधे जाने के लिए मेरी रूटिंग को बदलने से काम नहीं चलेगा, इसलिए ऐसा लग रहा है कि Server.TransferRequest"एमवीसी में पूरी तरह से अनावश्यक" नहीं है।
प्रोफके

0

प्रति उत्तर नहीं, लेकिन स्पष्ट रूप से आवश्यकता न केवल वास्तविक नेविगेशन के लिए Webforms Server.Transfer () की समतुल्य कार्यक्षमता को "करने" के लिए होगी, बल्कि इस सबके लिए इकाई परीक्षण के भीतर पूरी तरह से समर्थित होने के लिए भी होगी।

इसलिए ServerTransferResult को RedirectToRouteResult की तरह "देखना" चाहिए, और वर्ग पदानुक्रम के संदर्भ में यथासंभव समान होना चाहिए।

मैं रिफ्लेक्टर को देखते हुए ऐसा करने के बारे में सोच रहा हूं, और जो कुछ भी RedirectToRouteResult क्लास कर रहा है, वह भी विभिन्न कंट्रोलर बेस क्लास मेथड्स, और फिर बाद में कंट्रोलर के पास एक्सटेंशन विधियों के माध्यम से "जोड़ना"। हो सकता है कि आसानी से डाउनलोड करने के आलस / आलस्य के लिए ये एक ही कक्षा में स्थिर तरीके हो सकते हैं?

अगर मैं ऐसा करने के लिए चक्कर लगाता हूं तो मैं इसे पोस्ट कर दूंगा, नहीं तो हो सकता है कि कोई दूसरा मुझे हरा दे!


0

मैंने Html.RenderActionएक दृश्य में सहायक का उपयोग करके इसे हासिल किया :

@{
    string action = ViewBag.ActionName;
    string controller = ViewBag.ControllerName;
    object routeValues = ViewBag.RouteValues;
    Html.RenderAction(action, controller, routeValues);
}

और मेरे नियंत्रक में:

public ActionResult MyAction(....)
{
    var routeValues = HttpContext.Request.RequestContext.RouteData.Values;    
    ViewBag.ActionName = "myaction";
    ViewBag.ControllerName = "mycontroller";
    ViewBag.RouteValues = routeValues;    
    return PartialView("_AjaxRedirect");
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.