How to Specify a Custom Location to "Search For Views" in ASP.NET MVC

Can I specify a custom location to search for views in ASP.NET MVC?

You can easily extend the WebFormViewEngine to specify all the locations you want to look in:

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

Make sure you remember to register the view engine by modifying the Application_Start method in your Global.asax.cs

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

Search for view files in a custom location only for Specified Area in MVC 5

Try this: in RouteConfig.cs where you are setting up the route which links to a controller which you want to find the custom view location, add this:

var route = routes.MapRoute(<route params here>);
route.DataTokens["area"] = "AreaName";

This will tell MVC that when you follow this route, you are going into area 'AreaName'. Then it will subsequently look for views in that area. Your custom ViewEngine will only affect view locations when MVC is looking for them in some area. Otherwise it won't have any effect, as the location format lists for areas are the only ones it overrides.

How to specify the view location in asp.net core mvc when using custom locations?

You can expand the locations where the view engine looks for views by implementing a view location expander. Here is some sample code to demonstrate the approach:

public class ViewLocationExpander: IViewLocationExpander {

/// <summary>
/// Used to specify the locations that the view engine should search to
/// locate views.
/// </summary>
/// <param name="context"></param>
/// <param name="viewLocations"></param>
/// <returns></returns>
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations) {
//{2} is area, {1} is controller,{0} is the action
string[] locations = new string[] { "/Views/{2}/{1}/{0}.cshtml"};
return locations.Union(viewLocations); //Add mvc default locations after ours
}


public void PopulateValues(ViewLocationExpanderContext context) {
context.Values["customviewlocation"] = nameof(ViewLocationExpander);
}
}

Then in the ConfigureServices(IServiceCollection services) method in the startup.cs file add the following code to register it with the IoC container. Do this right after services.AddMvc();

services.Configure<RazorViewEngineOptions>(options => {
options.ViewLocationExpanders.Add(new ViewLocationExpander());
});

Now you have a way to add any custom directory structure you want to the list of places the view engine looks for views, and partial views. Just add it to the locations string[]. Also, you can place a _ViewImports.cshtml file in the same directory or any parent directory and it will be found and merged with your views located in this new directory structure.

Update:

One nice thing about this approach is that it provides more flexibility then the approach later introduced in ASP.NET Core 2 (Thanks @BrianMacKay for documenting the new approach). So for example this ViewLocationExpander approach allows for not only specifying a hierarchy of paths to search for views and areas but also for layouts and view components. Also you have access to the full ActionContext to determine what an appropriate route might be. This provides alot of flexibility and power. So for example if you wanted to determine the appropriate view location by evaluating the path of the current request, you can get access to the path of the current request via context.ActionContext.HttpContext.Request.Path.

mvc6: specify custom location for views of viewComponents

You can do that but you have to do following steps for that.

  1. Create New View engine based on RazorViewEngine. Also by default it need Components directory so just use Views as root folder.

    namespace WebApplication10
    {
    public class MyViewEngine : RazorViewEngine
    {
    public MyViewEngine(IRazorPageFactory pageFactory, IViewLocationExpanderProvider viewLocationExpanderProvider, IViewLocationCache viewLocationCache) : base(pageFactory,viewLocationExpanderProvider,viewLocationCache)
    {

    }
    public override IEnumerable<string> ViewLocationFormats
    {
    get
    {
    List<string> existing = base.ViewLocationFormats.ToList();
    existing.Add("/Views/{0}.cshtml");
    return existing;
    }
    }

    }

    }

  2. Add ViewEngine in MVC in Startup.cs

    services.AddMvc().Configure<MvcOptions>(options =>
    {
    options.ViewEngines.Add(Type.GetType("WebApplication10.MyViewEngine"));

    });
  3. Now I have placed My Component at following location. For example my component name is MyFirst.cshtml. So I can place Views/Components/MyFirst/Default.cshtml.

Is is possible to specify searchable location formats for an MVC Razor Layout?

Recently I was struggling on a similar issue where, in a themed application that uses a custom ViewEngine to search theme's location first for views, I was trying to override some master files. One way to force the location of the layout to go through the ViewEngine's FindView is to specify the name of the master view in a controller action when returning:

return View("myView", "myViewMaster");

However, if "myViewMaster" also has a layout (nested layouts), this method doesn't work for the nested layout. My best solution so far is to call the view engine directly in the view:

@{
Layout = (ViewEngines.Engines.FindView(this.ViewContext.Controller.ControllerContext, "myViewMaster", "").View as RazorView).ViewPath;
}

This works but could certainly be encapsulated in a extension method to avoid repetition and abstract the code.

Hope it helps!

how to change order of search viewLocation in asp.net mvc?

you can create custom class inherits RazorViewEngine

usin System.Web.Mvc
namespace Views.Infrastructure{
public class CustomrazorViewEngine : RazorViewEngin{
public CustomrazorViewEngine(){
ViewLocationFormats=new string[]{
"~/Views/{1}/{0}.cshtml",
"~/Views/Common/{0}.cshtml"
};
}
}
}

and in Global.asax

proteced void Application_Start()
{
AreaRegisteration.registerAllArea();
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomrazorViewEngine());
RoutConfig.registerRoutes(RouteTable.Routes);
}

I suggest doing this to prevent the Confilict of other introduced Viewengines :

ViewEngines.Engines.Clear();

How do I tell Resharper to look in a custom location for Partial views?

I have Resharper 8.2 installed. I would register custom ViewEngine in global.asax and it works fine.

protected void Application_Start()
{
//register custom ViewEngine
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new MyCustonViewEngine());

AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}

and here is code snip for MyCustonViewEngine:

public class MyCustonViewEngine : RazorViewEngine
{
public MyCustonViewEngine()
{
ViewLocationFormats = new[]
{
"~/UI/MVC/Razor/{1}/{0}.cshtml",
"~/UI/MVC/Razor/Shared/{1}/{0}.cshtml"
};
MasterLocationFormats = ViewLocationFormats;
PartialViewLocationFormats = ViewLocationFormats;
}
}


Related Topics



Leave a reply



Submit