क्या मैं ASP.NET MVC में "विचारों की खोज" करने के लिए एक कस्टम स्थान निर्दिष्ट कर सकता हूं?


105

मेरे पास मेरी mvc प्रोजेक्ट के लिए निम्नलिखित लेआउट है:

  • / नियंत्रकों
    • / डेमो
    • / डेमो / DemoArea1Controller
    • / डेमो / DemoArea2Controller
    • आदि...
  • / दृश्य
    • / डेमो
    • /Demo/DemoArea1/Index.aspx
    • /Demo/DemoArea2/Index.aspx

हालाँकि, जब मेरे पास इसके लिए है DemoArea1Controller:

public class DemoArea1Controller : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

मुझे सामान्य दृश्य स्थानों के साथ "दृश्य 'सूचकांक मिलता है या इसके स्वामी को" त्रुटि नहीं मिली "।

मैं "डेमो" नामस्थान में खोजकर्ताओं को "डेमो" दृश्य सबफ़ोल्डर में कैसे निर्दिष्ट कर सकता हूं?


रोब कॉनरी के एमवीसी कॉमर्स ऐप से एक साधारण ViewEngine का एक और नमूना है : ViewEngine सेट करने के लिए इंजन कोड और Global.asax.cs कोड देखें: Global.asax.cs आशा है कि यह मदद करता है।
रॉबर्ट डीन

जवाबों:


121

आप उन सभी स्थानों को निर्दिष्ट करने के लिए आसानी से WebFormViewEngine का विस्तार कर सकते हैं जिन्हें आप देखना चाहते हैं:

public class CustomViewEngine : WebFormViewEngine
{
    public CustomViewEngine()
    {
        var viewLocations =  new[] {  
            "~/Views/{1}/{0}.aspx",  
            "~/Views/{1}/{0}.ascx",  
            "~/Views/Shared/{0}.aspx",  
            "~/Views/Shared/{0}.ascx",  
            "~/AnotherPath/Views/{0}.ascx"
            // etc
        };

        this.PartialViewLocationFormats = viewLocations;
        this.ViewLocationFormats = viewLocations;
    }
}

सुनिश्चित करें कि आप अपने Global.asax.cs में Application_Start पद्धति को संशोधित करके दृश्य इंजन पंजीकृत करना याद रखें

protected void Application_Start()
{
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new CustomViewEngine());
}

आप नेस्टेड मास्टर पेज से मास्टर पेज के मार्ग का उपयोग कैसे कर सकते हैं? CustomViewEngine के रास्तों के भीतर खोज करने के लिए नेस्टेड मास्टर पेज लेआउट सेट करने के रूप में
Drahcir

6
क्या यह बेहतर नहीं है अगर हम पहले से पंजीकृत इंजनों को साफ़ करना छोड़ दें और सिर्फ नया जोड़ दें और दृश्य केवल नए ही होंगे?
प्रसन्न

3
ViewEngines.Engines.Clear के बिना कार्यान्वयन (); सभी ठीक काम करते हैं। यदि आप * .cshtml का उपयोग करना चाहते हैं, तो आपको RazorViewEngine से विरासत में प्राप्त करना होगा
KregHEk

क्या कोई तरीका है जिससे हम "ऐड व्यू" को लिंक कर सकें और कंट्रोलर्स से नए व्यू लोकेशन्स पर "व्यूज़" देखने जा सकें? मैं दृश्य स्टूडियो 2012 का उपयोग कर रहा हूं
नेविल नाजरीन

जैसा कि @Prasanna द्वारा उल्लेख किया गया है, नए स्थानों को जोड़ने के लिए मौजूदा इंजनों को खाली करने की आवश्यकता नहीं है, अधिक विवरण के लिए इस उत्तर को देखें।
होमन बहरीन

45

अब MVC 6 में आप IViewLocationExpanderदृश्य इंजनों के साथ खिलवाड़ किए बिना इंटरफ़ेस को लागू कर सकते हैं :

public class MyViewLocationExpander : IViewLocationExpander
{
    public void PopulateValues(ViewLocationExpanderContext context) {}

    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        return new[]
        {
            "/AnotherPath/Views/{1}/{0}.cshtml",
            "/AnotherPath/Views/Shared/{0}.cshtml"
        }; // add `.Union(viewLocations)` to add default locations
    }
}

जहाँ {0}लक्ष्य नाम, {1}- नियंत्रक नाम और {2}- क्षेत्र का नाम है।

आप स्थानों की अपनी सूची वापस कर सकते हैं, इसे डिफ़ॉल्ट रूप से मर्ज कर सकते हैं viewLocations( .Union(viewLocations)) या बस उन्हें बदल सकते हैं ( viewLocations.Select(path => "/AnotherPath" + path))।

MVC में अपने कस्टम दृश्य स्थान विस्तारक को पंजीकृत करने के लिए, फ़ाइल ConfigureServicesमें विधि के लिए अगली पंक्तियाँ जोड़ें Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<RazorViewEngineOptions>(options =>
    {
        options.ViewLocationExpanders.Add(new MyViewLocationExpander());
    });
}

3
मेरी इच्छा है कि मैं इसे 10 वोट दे सकूं। क्या वास्तव में Asp.net 5 / MVC 6. सुंदर में आवश्यक है। मेरे मामले में (और अन्य) बहुत उपयोगी है जब आप बड़े क्षेत्रों या तार्किक समूहों के लिए सुपर क्षेत्रों में समूह बनाना चाहते हैं।
drewid

Startup.cs हिस्सा होना चाहिए: services .Configure <RazorViewEngineOptions> यह इस पद्धति में जाता है: सार्वजनिक शून्य कॉन्फिगरेशन सर्विसेस (IServiceCollection services)
OrangeKing89

42

आपके कंस्ट्रक्टर में पथों को हार्डकोड करने की तुलना में वास्तव में बहुत आसान विधि है। नीचे नए रास्तों को जोड़ने के लिए रेजर इंजन का विस्तार करने का एक उदाहरण है। एक बात मैं इस बारे में पूरी तरह सुनिश्चित नहीं हूं कि क्या आपके द्वारा यहां जोड़े गए रास्ते बंद होंगे:

public class ExtendedRazorViewEngine : RazorViewEngine
{
    public void AddViewLocationFormat(string paths)
    {
        List<string> existingPaths = new List<string>(ViewLocationFormats);
        existingPaths.Add(paths);

        ViewLocationFormats = existingPaths.ToArray();
    }

    public void AddPartialViewLocationFormat(string paths)
    {
        List<string> existingPaths = new List<string>(PartialViewLocationFormats);
        existingPaths.Add(paths);

        PartialViewLocationFormats = existingPaths.ToArray();
    }
}

और आपका Global.asax.cs

protected void Application_Start()
{
    ViewEngines.Engines.Clear();

    ExtendedRazorViewEngine engine = new ExtendedRazorViewEngine();
    engine.AddViewLocationFormat("~/MyThemes/{1}/{0}.cshtml");
    engine.AddViewLocationFormat("~/MyThemes/{1}/{0}.vbhtml");

    // Add a shared location too, as the lines above are controller specific
    engine.AddPartialViewLocationFormat("~/MyThemes/{0}.cshtml");
    engine.AddPartialViewLocationFormat("~/MyThemes/{0}.vbhtml");

    ViewEngines.Engines.Add(engine);

    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
}

एक बात ध्यान दें: आपके कस्टम स्थान को इसके रूट में ViewStart.cshtml फ़ाइल की आवश्यकता होगी।


23

यदि आप नया पथ जोड़ना चाहते हैं, तो आप डिफ़ॉल्ट दृश्य इंजनों में जोड़ सकते हैं और कोड की कुछ पंक्तियों को छोड़ सकते हैं:

ViewEngines.Engines.Clear();
var razorEngine = new RazorViewEngine();
razorEngine.MasterLocationFormats = razorEngine.MasterLocationFormats
      .Concat(new[] { 
          "~/custom/path/{0}.cshtml" 
      }).ToArray();

razorEngine.PartialViewLocationFormats = razorEngine.PartialViewLocationFormats
      .Concat(new[] { 
          "~/custom/path/{1}/{0}.cshtml",   // {1} = controller name
          "~/custom/path/Shared/{0}.cshtml" 
      }).ToArray();

ViewEngines.Engines.Add(razorEngine);

वही लागू होता है WebFormEngine


2
दृश्य के लिए: razorEngine.ViewLocationFormats का उपयोग करें।
एल्डेन्तेव

13

RazorViewEngine को उप-वर्गित करने के बजाय, या इसे एकमुश्त बदलने के बजाय, आप मौजूदा RazorViewEngine के PartialViewLocationFormats गुण को बदल सकते हैं। यह कोड Application_Start में जाता है:

System.Web.Mvc.RazorViewEngine rve = (RazorViewEngine)ViewEngines.Engines
  .Where(e=>e.GetType()==typeof(RazorViewEngine))
  .FirstOrDefault();

string[] additionalPartialViewLocations = new[] { 
  "~/Views/[YourCustomPathHere]"
};

if(rve!=null)
{
  rve.PartialViewLocationFormats = rve.PartialViewLocationFormats
    .Union( additionalPartialViewLocations )
    .ToArray();
}

2
यह मेरे लिए काम करता है, इस अपवाद के साथ कि रेजर इंजन का प्रकार 'रेज़र व्यूइंगाइन' के बजाय 'फिक्स्डराज़ व्यूइंगाइन' था। इसके अलावा मैं एक अपवाद भी फेंकता हूं अगर इंजन नहीं मिला क्योंकि यह मेरे आवेदन को सफलतापूर्वक आरंभ करने से रोकता है।
रॉब

3

पिछली बार मैंने जाँच की थी, इसके लिए आपको अपना खुद का ViewEngine बनाना होगा। मुझे नहीं पता कि क्या उन्होंने आरसी 1 में इसे आसान बनाया है।

पहले आरसी से पहले मैंने जो मूल दृष्टिकोण का उपयोग किया था, वह मेरे अपने व्यूइंगाइन में, नियंत्रक के नाम स्थान को विभाजित करने और उन फ़ोल्डरों की तलाश करने के लिए था जो भागों से मेल खाते थे।

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

वापस गया और कोड पाया। यहाँ सामान्य विचार है।

public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName)
{
    string ns = controllerContext.Controller.GetType().Namespace;
    string controller = controllerContext.Controller.GetType().Name.Replace("Controller", "");

    //try to find the view
    string rel = "~/Views/" +
        (
            ns == baseControllerNamespace ? "" :
            ns.Substring(baseControllerNamespace.Length + 1).Replace(".", "/") + "/"
        )
        + controller;
    string[] pathsToSearch = new string[]{
        rel+"/"+viewName+".aspx",
        rel+"/"+viewName+".ascx"
    };

    string viewPath = null;
    foreach (var path in pathsToSearch)
    {
        if (this.VirtualPathProvider.FileExists(path))
        {
            viewPath = path;
            break;
        }
    }

    if (viewPath != null)
    {
        string masterPath = null;

        //try find the master
        if (!string.IsNullOrEmpty(masterName))
        {

            string[] masterPathsToSearch = new string[]{
                rel+"/"+masterName+".master",
                "~/Views/"+ controller +"/"+ masterName+".master",
                "~/Views/Shared/"+ masterName+".master"
            };


            foreach (var path in masterPathsToSearch)
            {
                if (this.VirtualPathProvider.FileExists(path))
                {
                    masterPath = path;
                    break;
                }
            }
        }

        if (string.IsNullOrEmpty(masterName) || masterPath != null)
        {
            return new ViewEngineResult(
                this.CreateView(controllerContext, viewPath, masterPath), this);
        }
    }

    //try default implementation
    var result = base.FindView(controllerContext, viewName, masterName);
    if (result.View == null)
    {
        //add the location searched
        return new ViewEngineResult(pathsToSearch);
    }
    return result;
}

1
यह वास्तव में बहुत आसान है। उपवर्ग WebFormsViewEngine और फिर पथ के सरणी में इसे जोड़ें जो पहले से ही आपके निर्माता में खोज करता है।
क्रेग स्टंट्ट

जानकार अच्छा लगा। पिछली बार मुझे उस संग्रह को संशोधित करने की आवश्यकता थी, यह उस तरीके से संभव नहीं था।
जोएल

वर्थ उल्लेख करते हुए कि आपको अपने बेस कंट्रोलर नेमस्पेस (जैसे "प्रोजेक्ट.कंट्रोलर") को "बेसकंट्रोलरनामेसस्पेस" वैरिएबल सेट करने की आवश्यकता है, लेकिन अन्यथा मुझे वही चाहिए जो पोस्ट किए जाने के 7 साल बाद हो।
प्रोटोटाइप 14

3

कुछ इस तरह की कोशिश करो:

private static void RegisterViewEngines(ICollection<IViewEngine> engines)
{
    engines.Add(new WebFormViewEngine
    {
        MasterLocationFormats = new[] {"~/App/Views/Admin/{0}.master"},
        PartialViewLocationFormats = new[] {"~/App/Views/Admin//{1}/{0}.ascx"},
        ViewLocationFormats = new[] {"~/App/Views/Admin//{1}/{0}.aspx"}
    });
}

protected void Application_Start()
{
    RegisterViewEngines(ViewEngines.Engines);
}

3

नोट: ASP.NET MVC 2 के लिए उनके पास अतिरिक्त स्थान पथ हैं जिन्हें आपको 'क्षेत्रों' में विचारों के लिए सेट करना होगा।

 AreaViewLocationFormats
 AreaPartialViewLocationFormats
 AreaMasterLocationFormats

एक क्षेत्र के लिए एक दृश्य इंजन बनाना फिल के ब्लॉग पर वर्णित है

नोट: यह पूर्वावलोकन रिलीज़ 1 के लिए है इसलिए परिवर्तन के अधीन है।


1

यहां अधिकांश उत्तर, कॉल करके मौजूदा स्थानों को साफ़ करते हैंViewEngines.Engines.Clear() और फिर उन्हें फिर से जोड़ते हैं ... ऐसा करने की कोई आवश्यकता नहीं है।

हम मौजूदा स्थानों में नए स्थान जोड़ सकते हैं, जैसा कि नीचे दिखाया गया है:

// note that the base class is RazorViewEngine, NOT WebFormViewEngine
public class ExpandedViewEngine : RazorViewEngine
{
    public ExpandedViewEngine()
    {
        var customViewSubfolders = new[] 
        {
            // {1} is conroller name, {0} is action name
            "~/Areas/AreaName/Views/Subfolder1/{1}/{0}.cshtml",
            "~/Areas/AreaName/Views/Subfolder1/Shared/{0}.cshtml"
        };

        var customPartialViewSubfolders = new[] 
        {
            "~/Areas/MyAreaName/Views/Subfolder1/{1}/Partials/{0}.cshtml",
            "~/Areas/MyAreaName/Views/Subfolder1/Shared/Partials/{0}.cshtml"
        };

        ViewLocationFormats = ViewLocationFormats.Union(customViewSubfolders).ToArray();
        PartialViewLocationFormats = PartialViewLocationFormats.Union(customPartialViewSubfolders).ToArray();

        // use the following if you want to extend the master locations
        // MasterLocationFormats = MasterLocationFormats.Union(new[] { "new master location" }).ToArray();   
    }
}

अब आप RazorViewEngineGlobal.asax में उपरोक्त का उपयोग करने के लिए अपनी परियोजना को कॉन्फ़िगर कर सकते हैं :

protected void Application_Start()
{
    ViewEngines.Engines.Add(new ExpandedViewEngine());
    // more configurations
}

अधिक जानकारी के लिए इस ट्यूटर को देखें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.