MVC में डिफ़ॉल्ट रूट (एक क्षेत्र में) कैसे सेट करें


122

ठीक है यह पहले पूछा गया है, लेकिन वहाँ कोई ठोस समाधान नहीं है। तो अपने और दूसरों के उद्देश्य से जो इस उपयोगी को पा सकते हैं।

MVC2 (ASP.NET) में मैं ऐसा चाहता हूं जब कोई वेबसाइट पर नेविगेट करता है, तो एक डिफ़ॉल्ट क्षेत्र निर्दिष्ट होता है। इसलिए मेरी साइट पर नेविगेट करके आपको एरियाज़ में कंट्रोलर एक्शनवाई को भेजना चाहिए।

Global.asax में निम्न मार्ग का उपयोग करना

routes.MapRoute(
                "Area",
                "",
                new { area = "AreaZ", controller = "ControllerX ", action = "ActionY " }
            );

अब यह काम करता है क्योंकि यह सही पृष्ठ पर काम करने की कोशिश करता है। हालाँकि MVC साइट के रूट में व्यू को देखने के लिए आगे बढ़ता है न कि एरिया फोल्डर में।

क्या इसका समाधान करने का कोई तरीका है?

संपादित करें

एक 'सॉल्यूशन' है और यह कंट्रोलरएक्स में है, एक्शनवाई व्यू का पूरा रास्ता देता है। एक हैक के बिट, लेकिन यह काम करता है। हालांकि मैं उम्मीद कर रहा हूं कि बेहतर समाधान है।

         public ActionResult ActionY()
        {
            return View("~/Areas/AreaZ/views/ActionY.aspx");
        }

संपादित करें:

पृष्ठ का HTML ActionLink होने पर यह भी एक समस्या बन जाती है। यदि क्षेत्र सेट नहीं है, तो एक्शन लिंक आउटपुट रिक्त है।

यह सब डिजाइन या दोष से है?

जवाबों:


98

यह एक मेरी दिलचस्पी थी, और मुझे आखिरकार इस पर गौर करने का मौका मिला। अन्य लोगों को स्पष्ट रूप से समझ में नहीं आया है कि यह देखने के साथ एक मुद्दा है , न कि रूटिंग के साथ एक मुद्दा है - और शायद यही कारण है कि आपका प्रश्न शीर्षक इंगित करता है कि यह रूटिंग के बारे में है।

किसी भी मामले में, क्योंकि यह एक दृश्य-संबंधित मुद्दा है, जो आप चाहते हैं उसे प्राप्त करने का एकमात्र तरीका डिफ़ॉल्ट दृश्य इंजन को ओवरराइड करना है । आम तौर पर, जब आप ऐसा करते हैं, तो यह आपके दृश्य इंजन (यानी स्पार्क, एनएचएएमएल, आदि) को स्विच करने के सरल उद्देश्य के लिए है। इस मामले में, यह दृश्य-निर्माण तर्क नहीं है जिसे हमें ओवरराइड करने की आवश्यकता है, लेकिन कक्षा में FindPartialViewऔर FindViewविधियां VirtualPathProviderViewEngine

आप अपने भाग्यशाली सितारों को धन्यवाद दे सकते हैं कि ये विधियां वास्तव में आभासी हैं, क्योंकि बाकी सब कुछ VirtualPathProviderViewEngineभी सुलभ नहीं है - यह निजी है, और यह खोज तर्क को ओवरराइड करने के लिए बहुत परेशान करता है क्योंकि आपको मूल रूप से पहले से मौजूद कोड के आधे को फिर से लिखना होगा। यदि आप इसे स्थान कैश और स्थान स्वरूपों के साथ अच्छा खेलना चाहते हैं तो लिखा गया है। रिफ्लेक्टर में कुछ खुदाई के बाद मैं आखिरकार एक काम करने वाले समाधान के साथ आने में कामयाब रहा।

मैंने यहां जो कुछ किया है वह पहले एक अमूर्त बनाना है जो इसके बजाय AreaAwareViewEngineसीधे से प्राप्त होता VirtualPathProviderViewEngineहै WebFormViewEngine। मैंने ऐसा इसलिए किया ताकि यदि आप (या जो भी हो) स्पार्क विचार बनाना चाहते हैं, तब भी आप इस वर्ग को आधार प्रकार के रूप में उपयोग कर सकते हैं।

नीचे दिया गया कोड बहुत लंबा-घुमावदार है, इसलिए आपको यह वास्तव में क्या करता है इसका एक त्वरित सारांश देने के लिए: यह आपको {2}स्थान प्रारूप में डाल देता है , जो क्षेत्र के नाम से {1}मेल खाता है , उसी तरह नियंत्रक नाम से मेल खाता है। बस! यही कारण है कि हमें यह सब कोड लिखना पड़ा है:

BaseAreaAwareViewEngine.cs

public abstract class BaseAreaAwareViewEngine : VirtualPathProviderViewEngine
{
    private static readonly string[] EmptyLocations = { };

    public override ViewEngineResult FindView(
        ControllerContext controllerContext, string viewName,
        string masterName, bool useCache)
    {
        if (controllerContext == null)
        {
            throw new ArgumentNullException("controllerContext");
        }
        if (string.IsNullOrEmpty(viewName))
        {
            throw new ArgumentNullException(viewName,
                "Value cannot be null or empty.");
        }

        string area = getArea(controllerContext);
        return FindAreaView(controllerContext, area, viewName,
            masterName, useCache);
    }

    public override ViewEngineResult FindPartialView(
        ControllerContext controllerContext, string partialViewName,
        bool useCache)
    {
        if (controllerContext == null)
        {
            throw new ArgumentNullException("controllerContext");
        }
        if (string.IsNullOrEmpty(partialViewName))
        {
            throw new ArgumentNullException(partialViewName,
                "Value cannot be null or empty.");
        }

        string area = getArea(controllerContext);
        return FindAreaPartialView(controllerContext, area,
            partialViewName, useCache);
    }

    protected virtual ViewEngineResult FindAreaView(
        ControllerContext controllerContext, string areaName, string viewName,
        string masterName, bool useCache)
    {
        string controllerName =
            controllerContext.RouteData.GetRequiredString("controller");
        string[] searchedViewPaths;
        string viewPath = GetPath(controllerContext, ViewLocationFormats,
            "ViewLocationFormats", viewName, controllerName, areaName, "View",
            useCache, out searchedViewPaths);
        string[] searchedMasterPaths;
        string masterPath = GetPath(controllerContext, MasterLocationFormats,
            "MasterLocationFormats", masterName, controllerName, areaName,
            "Master", useCache, out searchedMasterPaths);
        if (!string.IsNullOrEmpty(viewPath) &&
            (!string.IsNullOrEmpty(masterPath) || 
              string.IsNullOrEmpty(masterName)))
        {
            return new ViewEngineResult(CreateView(controllerContext, viewPath,
                masterPath), this);
        }
        return new ViewEngineResult(
            searchedViewPaths.Union<string>(searchedMasterPaths));
    }

    protected virtual ViewEngineResult FindAreaPartialView(
        ControllerContext controllerContext, string areaName,
        string viewName, bool useCache)
    {
        string controllerName =
            controllerContext.RouteData.GetRequiredString("controller");
        string[] searchedViewPaths;
        string partialViewPath = GetPath(controllerContext,
            ViewLocationFormats, "PartialViewLocationFormats", viewName,
            controllerName, areaName, "Partial", useCache,
            out searchedViewPaths);
        if (!string.IsNullOrEmpty(partialViewPath))
        {
            return new ViewEngineResult(CreatePartialView(controllerContext,
                partialViewPath), this);
        }
        return new ViewEngineResult(searchedViewPaths);
    }

    protected string CreateCacheKey(string prefix, string name,
        string controller, string area)
    {
        return string.Format(CultureInfo.InvariantCulture,
            ":ViewCacheEntry:{0}:{1}:{2}:{3}:{4}:",
            base.GetType().AssemblyQualifiedName,
            prefix, name, controller, area);
    }

    protected string GetPath(ControllerContext controllerContext,
        string[] locations, string locationsPropertyName, string name,
        string controllerName, string areaName, string cacheKeyPrefix,
        bool useCache, out string[] searchedLocations)
    {
        searchedLocations = EmptyLocations;
        if (string.IsNullOrEmpty(name))
        {
            return string.Empty;
        }
        if ((locations == null) || (locations.Length == 0))
        {
            throw new InvalidOperationException(string.Format("The property " +
                "'{0}' cannot be null or empty.", locationsPropertyName));
        }
        bool isSpecificPath = IsSpecificPath(name);
        string key = CreateCacheKey(cacheKeyPrefix, name,
            isSpecificPath ? string.Empty : controllerName,
            isSpecificPath ? string.Empty : areaName);
        if (useCache)
        {
            string viewLocation = ViewLocationCache.GetViewLocation(
                controllerContext.HttpContext, key);
            if (viewLocation != null)
            {
                return viewLocation;
            }
        }
        if (!isSpecificPath)
        {
            return GetPathFromGeneralName(controllerContext, locations, name,
                controllerName, areaName, key, ref searchedLocations);
        }
        return GetPathFromSpecificName(controllerContext, name, key,
            ref searchedLocations);
    }

    protected string GetPathFromGeneralName(ControllerContext controllerContext,
        string[] locations, string name, string controllerName,
        string areaName, string cacheKey, ref string[] searchedLocations)
    {
        string virtualPath = string.Empty;
        searchedLocations = new string[locations.Length];
        for (int i = 0; i < locations.Length; i++)
        {
            if (string.IsNullOrEmpty(areaName) && locations[i].Contains("{2}"))
            {
                continue;
            }
            string testPath = string.Format(CultureInfo.InvariantCulture,
                locations[i], name, controllerName, areaName);
            if (FileExists(controllerContext, testPath))
            {
                searchedLocations = EmptyLocations;
                virtualPath = testPath;
                ViewLocationCache.InsertViewLocation(
                    controllerContext.HttpContext, cacheKey, virtualPath);
                return virtualPath;
            }
            searchedLocations[i] = testPath;
        }
        return virtualPath;
    }

    protected string GetPathFromSpecificName(
        ControllerContext controllerContext, string name, string cacheKey,
        ref string[] searchedLocations)
    {
        string virtualPath = name;
        if (!FileExists(controllerContext, name))
        {
            virtualPath = string.Empty;
            searchedLocations = new string[] { name };
        }
        ViewLocationCache.InsertViewLocation(controllerContext.HttpContext,
            cacheKey, virtualPath);
        return virtualPath;
    }


    protected string getArea(ControllerContext controllerContext)
    {
        // First try to get area from a RouteValue override, like one specified in the Defaults arg to a Route.
        object areaO;
        controllerContext.RouteData.Values.TryGetValue("area", out areaO);

        // If not specified, try to get it from the Controller's namespace
        if (areaO != null)
            return (string)areaO;

        string namespa = controllerContext.Controller.GetType().Namespace;
        int areaStart = namespa.IndexOf("Areas.");
        if (areaStart == -1)
            return null;

        areaStart += 6;
        int areaEnd = namespa.IndexOf('.', areaStart + 1);
        string area = namespa.Substring(areaStart, areaEnd - areaStart);
        return area;
    }

    protected static bool IsSpecificPath(string name)
    {
        char ch = name[0];
        if (ch != '~')
        {
            return (ch == '/');
        }
        return true;
    }
}

अब जैसा कि कहा गया है, यह एक ठोस इंजन नहीं है, इसलिए आपको इसे भी बनाना होगा। यह हिस्सा, सौभाग्य से, है बहुत आसान है, हमें बस इतना करना है कि डिफ़ॉल्ट प्रारूप सेट करें और वास्तव में विचार बनाएं:

AreaAwareViewEngine.cs

public class AreaAwareViewEngine : BaseAreaAwareViewEngine
{
    public AreaAwareViewEngine()
    {
        MasterLocationFormats = new string[]
        {
            "~/Areas/{2}/Views/{1}/{0}.master",
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.master",
            "~/Areas/{2}/Views/Shared/{0}.cshtml",
            "~/Views/{1}/{0}.master",
            "~/Views/{1}/{0}.cshtml",
            "~/Views/Shared/{0}.master"
            "~/Views/Shared/{0}.cshtml"
        };
        ViewLocationFormats = new string[]
        {
            "~/Areas/{2}/Views/{1}/{0}.aspx",
            "~/Areas/{2}/Views/{1}/{0}.ascx",
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.aspx",
            "~/Areas/{2}/Views/Shared/{0}.ascx",
            "~/Areas/{2}/Views/Shared/{0}.cshtml",
            "~/Views/{1}/{0}.aspx",
            "~/Views/{1}/{0}.ascx",
            "~/Views/{1}/{0}.cshtml",
            "~/Views/Shared/{0}.aspx"
            "~/Views/Shared/{0}.ascx"
            "~/Views/Shared/{0}.cshtml"
        };
        PartialViewLocationFormats = ViewLocationFormats;
    }

    protected override IView CreatePartialView(
        ControllerContext controllerContext, string partialPath)
    {
        if (partialPath.EndsWith(".cshtml"))
            return new System.Web.Mvc.RazorView(controllerContext, partialPath, null, false, null);
        else
            return new WebFormView(controllerContext, partialPath);
    }

    protected override IView CreateView(ControllerContext controllerContext,
        string viewPath, string masterPath)
    {
        if (viewPath.EndsWith(".cshtml"))
            return new RazorView(controllerContext, viewPath, masterPath, false, null);
        else
            return new WebFormView(controllerContext, viewPath, masterPath);
    }
}

ध्यान दें कि हमने कुछ प्रविष्टियाँ मानक में जोड़ दी हैं ViewLocationFormats। ये नई {2}प्रविष्टियां हैं, जहां हम डाल में {2}मैप किए जाएंगेareaRouteData । मैंने MasterLocationFormatsअकेला छोड़ दिया है , लेकिन जाहिर है कि आप चाहें तो बदल सकते हैं।

अब अपने को संशोधित करें global.asax इस दृश्य इंजन को पंजीकृत को :

Global.asax.cs

protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new AreaAwareViewEngine());
}

... और डिफ़ॉल्ट मार्ग पंजीकृत करें:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapRoute(
        "Area",
        "",
        new { area = "AreaZ", controller = "Default", action = "ActionY" }
    );
    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = "" }
    );
}

अब बनाएँ AreaController हम सिर्फ संदर्भित :

DefaultController.cs (~ / नियंत्रक / में)

public class DefaultController : Controller
{
    public ActionResult ActionY()
    {
        return View("TestView");
    }
}

जाहिर है कि हमें निर्देशिका संरचना और उसके साथ जाने के लिए देखने की आवश्यकता है - हम इसे सुपर सरल रखेंगे:

TestView.aspx (~ में / क्षेत्रों / क्षेत्र / दृश्य / डिफ़ॉल्ट / या ~ / क्षेत्र / क्षेत्र / दृश्य / साझा /)

<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<h2>TestView</h2>
This is a test view in AreaZ.

और बस। अंत में, हम कर रहे हैं

अधिकांश भाग के लिए, आप बस लेने के लिए सक्षम होना चाहिए BaseAreaAwareViewEngineऔर AreaAwareViewEngineऔर किसी भी MVC परियोजना में छोड़ने, तो भले ही यह कोड का एक बहुत ले लिया इस किया पाने के लिए, आप केवल एक बार लिखने के लिए की है। उसके बाद, यह केवल कुछ लाइनों को संपादित करने global.asax.csऔर आपकी साइट संरचना बनाने की बात है ।


यह सबसे अच्छा वर्तमान समाधान है लेकिन आदर्श से बहुत दूर है। जैसे ही आप एक्शनलिंक जोड़ते हैं या ऐसी ही समस्या आती है।
लियाम

1
@Pino: मुझे लगता है कि आपको "डिफ़ॉल्ट" रूट मैपिंग में ActionLinkसमान जोड़कर समस्या को हल करने में सक्षम होना चाहिए । मैं हालांकि सकारात्मक नहीं हूँ; कोशिश करो और देखो। area = "AreaZ"global.asax.cs
Aaronaught

MVC4 में "डिफ़ॉल्ट" मार्ग घोषणापत्र Global.asax से ~ / App_Start / RouteConfig.cs / RegisterRoutes () तक चला गया
एंड्री एफ।

3
मुझे नीच से नफरत है, लेकिन मैं वास्तव में नीचे दिए गए उत्तर पर विश्वास नहीं कर सकता @ क्रिस एल्डरसन ने अधिक वोट प्राप्त नहीं किए हैं। यह इस की तुलना में बहुत सरल समाधान है और किनारे के मामलों (एक्शनलिंक, आदि) को हल करने के लिए लगता है।
jdmcnair

ऐसा प्रतीत होता है कि यहां एक बग है। उदाहरण के लिए "Re" नामक क्षेत्र का दृश्य ~ / क्षेत्र / Re / Views / Ctrlr / blah.aspx में होगा, लेकिन यहां कोड ~ / {2} / {1} / {0} का उपयोग होता है जो ~ होगा /Re/Ctrl/blah.aspx, पथ में महत्वपूर्ण क्षेत्र निर्देशिका को याद कर रहा है। यह "~ / क्षेत्र / {2} / दृश्य / {1} / {0} .aspx" होना चाहिए
क्रिस मोशचिनी

100

मैंने इस तरह से इसे किया। मुझे नहीं पता कि MapRoute () आपको क्षेत्र सेट करने की अनुमति क्यों नहीं देता है, लेकिन यह रूट ऑब्जेक्ट को वापस करता है ताकि आप जो भी अतिरिक्त परिवर्तन करना चाहते हैं वह जारी रख सकें। मैं इसका उपयोग करता हूं क्योंकि मेरे पास एक मॉड्यूलर MVC साइट है जो उद्यम ग्राहकों को बेची जाती है और उन्हें नए मॉड्यूल को जोड़ने के लिए बिन फ़ोल्डर में dll को छोड़ने में सक्षम होने की आवश्यकता होती है। मैं उन्हें AppSettings कॉन्फ़िगरेशन में "होमएयर" बदलने की अनुमति देता हूं।

var route = routes.MapRoute(
                "Home_Default", 
                "", 
                new {controller = "Home", action = "index" },
                new[] { "IPC.Web.Core.Controllers" }
               );
route.DataTokens["area"] = area;

संपादित करें: आप इस क्षेत्र में अपने क्षेत्ररैग्रिगेशन में प्रयास कर सकते हैं। मैंने इसका परीक्षण नहीं किया है, लेकिन AreaRegistrationContext.MapRoute route.DataTokens["area"] = this.AreaName;आपके लिए सेट करता है ।

context.MapRoute(
                    "Home_Default", 
                    "", 
                    new {controller = "Home", action = "index" },
                    new[] { "IPC.Web.Core.Controllers" }
                   );

यह काम करता हैं। नई web.config फ़ाइल से सावधान रहें, यह आपके पुराने वैश्विक कॉन्फ़िगरेशन को ओवरराइड कर सकती है।
मर्ट अक्काया

56

यहां तक ​​कि यह पहले से ही उत्तर दिया गया था - यह छोटा वाक्यविन्यास है (ASP.net 3, 4, 5):

routes.MapRoute("redirect all other requests", "{*url}",
    new {
        controller = "UnderConstruction",
        action = "Index"
        }).DataTokens = new RouteValueDictionary(new { area = "Shop" });

6
यह मेरे लिए बहुत अच्छा काम करता है। मेरे पास रूट पर कोई नियंत्रक नहीं है और केवल क्षेत्रों का उपयोग करते हैं। एमवीसी 4 के लिए मैंने रूटकॉन्फिग.क्स में डिफ़ॉल्ट को बदल दिया है। धन्यवाद!
मार्क

2
मैं MVC4 का उपयोग कर रहा हूं और यह मेरे लिए सबसे सरल उपाय था। एप्लिकेशन को साइट के 'होम पेज' के रूप में किसी विशेष क्षेत्र में सूचकांक दृश्य का उपयोग करने की अनुमति देता है।
जेट

2
यह समाधान भविष्य में (Asp.Net MVC6 और ऊपर से) काम नहीं करेगा।
पैट्रिक डेसजार्डिंस

@PatrickDesjardins: उपरोक्त समाधान का समर्थन नहीं करने का कोई कारण?
आकाश केसी

@SharmaM आप का उत्तर सदाबहार है। यह अभी भी मददगार है। तुमने मुझे एक रात बचाया।
स्कैपुल

16

आरोन को यह बताने के लिए धन्यवाद कि यह विचारों का पता लगाने के बारे में है, मैंने गलत समझा।

[अद्यतन] मैंने अभी एक परियोजना बनाई है जो उपयोगकर्ता को किसी भी कोड या लुकअप पथ के साथ गड़बड़ किए बिना प्रति डिफ़ॉल्ट एक क्षेत्र में भेजती है:

Global.asax में, हमेशा की तरह पंजीकरण करें:

    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,
        );
    }

में Application_Start(), निम्नलिखित आदेश का उपयोग सुनिश्चित करें;

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        RegisterRoutes(RouteTable.Routes);
    }

आप में क्षेत्र पंजीकरण, का उपयोग करें

    public override void RegisterArea(AreaRegistrationContext context)
    {
        context.MapRoute(
            "ShopArea_default",
            "{controller}/{action}/{id}",
            new { action = "Index", id = "", controller = "MyRoute" },
            new { controller = "MyRoute" }
        );
    }

एक उदाहरण पर पाया जा सकता है http://www.emphess.net/2010/01/31/areas-routes-and-defaults-in-mvc-2-rc/

मुझे वास्तव में उम्मीद है कि यह वही है जो आप के लिए पूछ रहे थे ...

////

मुझे नहीं लगता कि छद्म लिखना ViewEngineइस मामले में सबसे अच्छा समाधान है। (प्रतिष्ठा में कमी, मैं टिप्पणी नहीं कर सकता)। यह WebFormsViewEngineक्षेत्र जागरूक है और इसमें AreaViewLocationFormatsडिफ़ॉल्ट रूप से परिभाषित किया गया है

AreaViewLocationFormats = new[] {
        "~/Areas/{2}/Views/{1}/{0}.aspx",
        "~/Areas/{2}/Views/{1}/{0}.ascx",
        "~/Areas/{2}/Views/Shared/{0}.aspx",
        "~/Areas/{2}/Views/Shared/{0}.ascx",
    };

मेरा मानना ​​है कि आप इस सम्मेलन का पालन नहीं करते हैं। आपने पोस्ट किया

public ActionResult ActionY() 
{ 
    return View("~/Areas/AreaZ/views/ActionY.aspx"); 
} 

एक हैकिंग के रूप में, लेकिन यह होना चाहिए

   return View("~/Areas/AreaZ/views/ControllerX/ActionY.aspx"); 

यदि आप अधिवेशन का पालन नहीं करना चाहते हैं, तो, आप WebFormViewEngine( या MvcContrib में, उदाहरण के लिए किया जाता है) से व्युत्पन्न करके एक छोटा रास्ता लेना चाहते हैं , जहाँ आप कंस्ट्रक्टर, या -a में लुकअप पथ सेट कर सकते हैं थोड़ा hacky- इस तरह अपने सम्मेलन को निर्दिष्ट करके Application_Start:

((VirtualPathProviderViewEngine)ViewEngines.Engines[0]).AreaViewLocationFormats = ...;

यह थोड़ा और देखभाल के साथ किया जाना चाहिए, ज़ाहिर है, लेकिन मुझे लगता है कि यह विचार दिखाता है। ये क्षेत्र हैं publicमें VirtualPathProviderViewEngineMVC 2 आर सी में।


यह ध्यान देने योग्य है कि यह केवल MVC 2 RC में लागू होता है - MVC 1 VirtualPathProviderViewEngineमें यह गुण नहीं है और यह क्षेत्र-जागरूक नहीं है। और जबकि यह प्रश्न वास्तव में MVC 2 के बारे में कहा गया था, बहुत से लोग अभी भी इसका उपयोग नहीं कर रहे हैं (और कुछ समय के लिए नहीं होगा)। तो, विशिष्ट प्रश्न के लिए आपका उत्तर आसान है, लेकिन मेरा एकमात्र ऐसा है जो MVC1 उपयोगकर्ताओं के लिए काम करेगा जो इस प्रश्न पर ठोकर खाते हैं। मुझे ऐसे उत्तर प्रदान करना पसंद है जो पूर्व-रिलीज़ कार्यक्षमता पर निर्भर नहीं करते हैं जो संभवतः परिवर्तन के अधीन है।
Aaronaught

इसके अलावा यह "छद्म दृश्य इंजन" नहीं है - दृश्य इंजन वर्गों को जानबूझकर एक्स्टेंसिबल बनाया गया था ताकि विभिन्न प्रकार के विचारों का उपयोग किया जा सके।
Aaronaught

इसका मतलब आपको अपमान करना नहीं था, मुझे खेद है। यह 'छद्म' है कि यह दृश्य को संभालने के तरीके को महत्वपूर्ण रूप से नहीं बदलता है, लेकिन केवल कुछ मूल्यों को बदल देता है।
ममनोसिन

मैं नाराज नहीं था, मैं सिर्फ इस तथ्य को स्पष्ट करना चाहता था कि यह कस्टम दृश्य इंजन को प्राप्त करने के लिए एक विशेष रूप से असामान्य कारण नहीं है, क्योंकि इस तथ्य से स्पष्ट है कि संबंधित तरीके अतिश्योक्तिपूर्ण हैं।
Aaronaught

2
RegisterAreasपहले जाने के बारे में शानदार टिप RegisterRoutes। सोच रहा था कि मेरे कोड ने अचानक काम करना क्यों बंद कर दिया और उस
रिफ्लेक्टर पर

6

मुझे लगता है कि आप चाहते हैं कि उपयोगकर्ता ~/AreaZएक बार URL पर पुनर्निर्देशित हो जाए, उसने ~/URL का दौरा किया है । मैं आपकी रूट के भीतर निम्नलिखित कोड के माध्यम से हासिल करूंगा HomeController

public class HomeController
{
    public ActionResult Index()
    {
        return RedirectToAction("ActionY", "ControllerX", new { Area = "AreaZ" });
    }
}

और में निम्नलिखित मार्ग Global.asax

routes.MapRoute(
    "Redirection to AreaZ",
    String.Empty,
    new { controller = "Home ", action = "Index" }
);

यह काम करता है, लेकिन यह उपयोगकर्ताओं के ब्राउज़र पर URL में बदल जाता है। वास्तव में आदर्श नहीं।
५:४२ पर लियाम

2

सबसे पहले, आप MVC2 के किस संस्करण का उपयोग कर रहे हैं? पूर्वावलोकन 2 से RC में महत्वपूर्ण बदलाव हुए हैं।

मान लें कि आप RC का उपयोग करते हैं, मुझे लगता है कि आपको रूट-मैपिंग को अलग तरह से देखना चाहिए। में AreaRegistration.csअपने क्षेत्र में, आप डिफ़ॉल्ट मार्ग, जैसे किसी तरह का पंजीकरण कर सकते हैं

        context.MapRoute(
            "ShopArea_default",
            "{controller}/{action}/{id}",
            new { action = "Index", id = "", controller="MyRoute" }
        );

उपरोक्त कोड उपयोगकर्ता को MyRouteControllerहमारे ShopAreaडिफ़ॉल्ट रूप में भेजेगा ।

एक दूसरे पैरामीटर के रूप में एक खाली स्ट्रिंग का उपयोग करके एक अपवाद फेंकना चाहिए, क्योंकि एक नियंत्रक निर्दिष्ट किया जाना चाहिए।

बेशक आपको डिफ़ॉल्ट मार्ग बदलना होगा, Global.asaxइसलिए यह मुख्य मार्ग के लिए उपसर्ग का उपयोग करके इस डिफ़ॉल्ट मार्ग में हस्तक्षेप नहीं करता है।

इस थ्रेड और हैक के उत्तर को भी देखें: एमवीसी 2 एरियाग्रैजुएट रूट्स ऑर्डर

उम्मीद है की यह मदद करेगा।


धन्यवाद, लेकिन यकीन नहीं है कि यह सवाल में समझाया गया मुद्दा हल करता है। और इसका MVC RC
LiamB

2

निम्नलिखित को मेरे Application_Start में जोड़ना मेरे लिए काम करता है, हालाँकि मुझे यकीन नहीं है कि यदि आपके पास RC में यह सेटिंग है:

var engine = (WebFormViewEngine)ViewEngines.Engines.First();

// These additions allow me to route default requests for "/" to the home area
engine.ViewLocationFormats = new string[] { 
    "~/Views/{1}/{0}.aspx",
    "~/Views/{1}/{0}.ascx",
    "~/Areas/{1}/Views/{1}/{0}.aspx", // new
    "~/Areas/{1}/Views/{1}/{0}.ascx", // new
    "~/Areas/{1}/Views/{0}.aspx", // new
    "~/Areas/{1}/Views/{0}.ascx", // new
    "~/Views/{1}/{0}.ascx",
    "~/Views/Shared/{0}.aspx",
    "~/Views/Shared/{0}.ascx"
};

1

इस काम को करने के लिए मैंने जो किया वह निम्न है:

  1. मैंने रूट / कंट्रोलर फ़ोल्डर में एक डिफ़ॉल्ट नियंत्रक बनाया। मैंने अपने कंट्रोलर का नाम DefaultController रखा।
  2. नियंत्रक में मैंने निम्नलिखित कोड जोड़ा:

    namespace MyNameSpace.Controllers {
    public class DefaultController : Controller {
        // GET: Default
        public ActionResult Index() {
            return RedirectToAction("Index", "ControllerName", new {area = "FolderName"});
        }
    } }
  3. मेरे RouterConfig.cs में मैंने निम्नलिखित जोड़े:

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

इस सब के पीछे ट्रिक यह है कि मैंने एक डिफॉल्ट कंस्ट्रक्टर बनाया है जो मेरे ऐप के शुरू होने पर हर बार स्टार्टअप कंट्रोलर रहेगा। जब यह उस डिफ़ॉल्ट नियंत्रक को हिट करता है तो यह डिफ़ॉल्ट सूचकांक क्रिया में मेरे द्वारा निर्दिष्ट किसी भी नियंत्रक पर पुनर्निर्देशित हो जाएगा। जो मेरे मामले में है

www.myurl.com/FolderName/ControllerName


0
routes.MapRoute(
                "Area",
                "{area}/",
                new { area = "AreaZ", controller = "ControlerX ", action = "ActionY " }
            );

क्या आपने कोशिश की है?


हां, समस्या इस तथ्य से कम है कि अब साइट रूट में विचारों की तलाश करती है। 'एक्शन' या इसके मास्टर का दृश्य नहीं मिला। निम्नलिखित स्थानों को खोजा गया: ~ / Views / ActionY / ActionY.aspx ~ / Views / ActionY / ActionY.ascx ~ / Views / साझा / ActionY.aspx ~ / दृश्य / साझा / ActionY.ascx
LXB

2
मै समझता हुँ। मैं एक समाधान खोजने की कोशिश करने जा रहा हूं। प्रश्न के लिए +1
बारब्रोस अल्प

0

विभिन्न बिल्डिंग ब्लॉक्स का पता लगाने का अनुरोध जीवन चक्र में किया जाता है। ASP.NET MVC अनुरोध जीवन चक्र के पहले चरणों में से एक अनुरोधित URL को सही नियंत्रक क्रिया विधि में मैप करना है। इस प्रक्रिया को रूटिंग कहा जाता है। एक डिफ़ॉल्ट मार्ग Global.asax फ़ाइल में आरंभीकृत किया गया है और ASP.NET MVC फ्रेमवर्क का वर्णन करता है कि अनुरोध कैसे संभालना है। MvcApplication1 प्रोजेक्ट में Global.asax फ़ाइल पर डबल-क्लिक करना निम्न कोड प्रदर्शित करेगा:

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing;

namespace MvcApplication1 {

   public class GlobalApplication : System.Web.HttpApplication
   {
       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);
       }
   }

}

Application_Start () ईवेंट हैंडलर में, जिसे जब भी अनुप्रयोग संकलित किया जाता है या वेब सर्वर को पुनरारंभ किया जाता है, एक रूट टेबल पंजीकृत होता है। डिफ़ॉल्ट मार्ग को डिफ़ॉल्ट नाम दिया गया है, और http://www.example.com/ के रूप में URL पर प्रतिक्रिया देता है {नियंत्रक} / {क्रिया} / {id} । {और} के बीच के चरों को अनुरोध URL से वास्तविक मानों के साथ या डिफ़ॉल्ट मानों के साथ आबाद किया जाता है यदि URL में कोई ओवरराइड मौजूद नहीं है। डिफ़ॉल्ट मार्ग पैरामीटर के अनुसार यह डिफ़ॉल्ट मार्ग होम कंट्रोलर और इंडेक्स एक्शन विधि में मैप करेगा। इस रूटिंग मैप के साथ हमारे पास कोई अन्य कार्रवाई नहीं होगी।

डिफ़ॉल्ट रूप से, इस डिफ़ॉल्ट मार्ग के माध्यम से सभी संभव URL मैप किए जा सकते हैं। हमारे अपने मार्ग बनाना भी संभव है। उदाहरण के लिए, आइए URL को मैप करें http://www.example.com/Employee/Maarten से एम्प्लॉई कंट्रोलर, शो एक्शन और फर्स्टनाम पैरामीटर को । निम्नलिखित कोड स्निपेट Global.asax फ़ाइल में डाला जा सकता है जिसे हमने अभी खोला है। क्योंकि ASP.NET MVC फ्रेमवर्क पहले मिलान मार्ग का उपयोग करता है, इस कोड स्निपेट को डिफ़ॉल्ट मार्ग के ऊपर डाला जाना चाहिए; अन्यथा मार्ग का उपयोग कभी नहीं किया जाएगा।

routes.MapRoute(

   "EmployeeShow",                    // Route name
   "Employee/{firstname}",            // URL with parameters
    new {                             // Parameter defaults
       controller = "Employee",
       action = "Show", 
       firstname = "" 
   }  

);

अब, आइए इस मार्ग के लिए आवश्यक घटक जोड़ें। सबसे पहले, कंट्रोलर फ़ोल्डर में EmployeeController नामक एक क्लास बनाएं। आप इस परियोजना में एक नया आइटम जोड़कर और वेब के तहत स्थित एमवीसी कंट्रोलर क्लास टेम्पलेट का चयन कर सकते हैं MVC श्रेणी। इंडेक्स एक्शन विधि को निकालें, और इसे शो नामक विधि या एक्शन से बदलें। यह विधि एक firstname पैरामीटर स्वीकार करती है और डेटा को ViewData शब्दकोश में पास करती है। इस शब्दकोश का उपयोग डेटा प्रदर्शित करने के लिए किया जाएगा।

EmployeeController वर्ग एक कर्मचारी वस्तु को देखने के लिए पारित करेगा। यह कर्मचारी वर्ग मॉडल फ़ोल्डर में जोड़ा जाना चाहिए (इस फ़ोल्डर पर राइट-क्लिक करें और फिर संदर्भ मेनू से Add | Class का चयन करें)। यहाँ कर्मचारी वर्ग के लिए कोड है:

namespace MvcApplication1.Models {

   public class Employee
   {
       public string FirstName { get; set; }
       public string LastName { get; set; }
       public string Email { get; set; }
   }

} 

1
धन्यवाद, मुझे पूरा यकीन नहीं है कि यह कैसे एक डिफ़ॉल्ट क्षेत्र की स्थापना से संबंधित है। : - /
LiamB

0

खैर, एक कस्टम व्यू इंजन बनाते समय इसके लिए काम कर सकते हैं, फिर भी आपके पास एक विकल्प हो सकता है:

  • तय करें कि आपको डिफ़ॉल्ट रूप से क्या दिखाना है।
  • कुछ है कि नियंत्रक और कार्रवाई (और क्षेत्र), सही है?
  • उस क्षेत्र पंजीकरण को खोलें और इस तरह से कुछ जोड़ें:
public override void RegisterArea(AreaRegistrationContext context)
{
    //this makes it work for the empty url (just domain) to act as current Area.
    context.MapRoute(
        "Area_empty",
        "",
        new { controller = "Home", action = "Index", id = UrlParameter.Optional },
        namespaces: new string[] { "Area controller namespace" }
    );
        //other routes of the area
}

चीयर्स!


माना। हालाँकि मुझे लगता है कि इस मार्ग की परिभाषा के लिए अधिक उपयुक्त स्थान Global.asax फ़ाइल में है।
nuhusky2003

ऐसे मामले में आपकी वैश्विक.सैक्स परिभाषाएँ एक क्षेत्र नियंत्रक नाम स्थान अस्तित्व के बारे में जानती हैं, जो मुझे लगता है कि सही नहीं है। क्षेत्र एक अतिरिक्त कार्यक्षमता है, जिसका अर्थ है कि आपको वैश्विक.सैक्स परिभाषाओं को छूने के बिना एक को जोड़ने / हटाने में सक्षम होना चाहिए। प्रश्न के लिए मेरे दृष्टिकोण में, मैं अनुरोध करने के लिए "वैश्विक" वेबसाइट के बजाय "हाथ से ओवर" अनुरोध को "टेक-ओवर" करना पसंद करता हूं।
टेंगिज

0

इस प्रश्न का स्वीकृत समाधान है, जबकि कस्टम व्यू इंजन बनाने के लिए संक्षेप में सही है, प्रश्न का सही उत्तर नहीं देता है। यहाँ मुद्दा यह है कि पिनो गलत तरीके से अपने डिफ़ॉल्ट मार्ग को निर्दिष्ट कर रहा है । विशेष रूप से उसकी "क्षेत्र" परिभाषा गलत है। "क्षेत्र" की जाँच डेटाटैंकेंस संग्रह के माध्यम से की जाती है और इसे इस तरह जोड़ा जाना चाहिए:

var defaultRoute = new Route("",new RouteValueDictionary(){{"controller","Default"},{"action","Index"}},null/*constraints*/,new RouteValueDictionary(){{"area","Admin"}},new MvcRouteHandler());
defaultRoute.DataTokens.Add("Namespaces","MyProject.Web.Admin.Controller"); 
routes.Add(defaultRoute);

डिफॉल्ट्स ऑब्जेक्ट में निर्दिष्ट "क्षेत्र" को अनदेखा किया जाएगा । ऊपर कोड एक डिफ़ॉल्ट मार्ग बनाता है, जो आपकी साइट के रूट के अनुरोध पर पकड़ता है और फिर डिफ़ॉल्ट नियंत्रक, व्यवस्थापक क्षेत्र में सूचकांक कार्रवाई को कॉल करता है। कृपया यह भी ध्यान दें कि "नामस्थान" कुंजी को डेटाटैक्स में जोड़ा जा रहा है, यह केवल तभी आवश्यक है जब आपके पास एक ही नाम के साथ कई नियंत्रक हों। यह समाधान Mvc2 और Mvc3 .NET 3.5 / 4.0 के साथ सत्यापित है


-1

ummm, मुझे नहीं पता कि यह सब प्रोग्रामिंग क्यों, मुझे लगता है कि इस डिफ़ॉल्ट मार्ग को निर्दिष्ट करके मूल समस्या को आसानी से हल किया गया है ...

routes.MapRoute("Default", "{*id}", 
                 new { controller = "Home"
                     , action = "Index"
                     , id = UrlParameter.Optional 
                     }
              );
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.