Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
367 views
in Technique[技术] by (71.8m points)

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

Let's say I have a controller that uses attribute based routing to handle a requested url of /admin/product like so:

[Route("admin/[controller]")]        
public class ProductController: Controller {

    // GET: /admin/product
    [Route("")]
    public IActionResult Index() {

        return View();
    }
}

Now let's say that I'd like to keep my views organized in a folder structure that roughly reflects the url paths they are related to. So I'd like the view for this controller to be located here:

/Views/Admin/Product.cshtml

To go further, if I had a controller like this:

[Route("admin/marketing/[controller]")]        
public class PromoCodeListController: Controller {

    // GET: /admin/marketing/promocodelist
    [Route("")]
    public IActionResult Index() {

        return View();
    }
}

I would like the framework to automatically look for it's view here:

Views/Admin/Marketing/PromoCodeList.cshtml

Ideally the approach for informing the framework of the view location would work in a general fashion based on the attribute based route information regardless of how many url segments are involved (ie. how deeply nested it is).

How can I instruct the the Core MVC framework (I'm currently using RC1) to look for the controller's view in such a location?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Great news... In ASP.NET Core 2 and up, you don't need a custom ViewEngine or even ExpandViewLocations anymore.

Using the OdeToCode.AddFeatureFolders Package

This is the easiest way... K. Scott Allen has a nuget package for you at OdeToCode.AddFeatureFolders that is clean and includes optional support for areas. Github: https://github.com/OdeToCode/AddFeatureFolders

Install the package, and it's as simple as:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc()
                .AddFeatureFolders();

        ...
    }

    ...
}  

DIY

Use this if you need extremely fine control over your folder structure, or if you aren't allowed/don't want to take the dependency for whatever reason. This is also quite easy, although perhaps more cluttery than the nuget package above:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
         ...

         services.Configure<RazorViewEngineOptions>(o =>
         {
             // {2} is area, {1} is controller,{0} is the action    
             o.ViewLocationFormats.Clear(); 
             o.ViewLocationFormats.Add("/Controllers/{1}/Views/{0}" + RazorViewEngine.ViewExtension);
             o.ViewLocationFormats.Add("/Controllers/Shared/Views/{0}" + RazorViewEngine.ViewExtension);

             // Untested. You could remove this if you don't care about areas.
             o.AreaViewLocationFormats.Clear();
             o.AreaViewLocationFormats.Add("/Areas/{2}/Controllers/{1}/Views/{0}" + RazorViewEngine.ViewExtension);
             o.AreaViewLocationFormats.Add("/Areas/{2}/Controllers/Shared/Views/{0}" + RazorViewEngine.ViewExtension);
             o.AreaViewLocationFormats.Add("/Areas/Shared/Views/{0}" + RazorViewEngine.ViewExtension);
        });

        ...         
    }

...
}

And that's it! No special classes required.

Dealing with Resharper/Rider

Bonus tip: if you're using ReSharper, you might notice that in some places ReSharper can't find your views and gives you annoying warnings. To work around that, pull in the Resharper.Annotations package and in your startup.cs (or anywhere else really) add one of these attributes for each of your view locations:

[assembly: AspMvcViewLocationFormat("/Controllers/{1}/Views/{0}.cshtml")]
[assembly: AspMvcViewLocationFormat("/Controllers/Shared/Views/{0}.cshtml")]

[assembly: AspMvcViewLocationFormat("/Areas/{2}/Controllers/{1}/Views/{0}.cshtml")]
[assembly: AspMvcViewLocationFormat("/Controllers/Shared/Views/{0}.cshtml")]

Hopefully this spares some folks the hours of frustration I just lived through. :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...