1

I would like to reorganize structure of MVC Core project so that, instead of horizontal layers (Models, Controllers, Views) I have vertical "slices" : each feature is contained inside one folder which contains everything related to that feature.

Example of this structure might look like this:

/Features/Home/Model.cs
/Features/Home/Controller.cs
/Features/Home/Index.cshtml

In older projects, I achieved this by writing custom controller factory.

Questions:

  1. Is custom controller factory best way to achieve this in ASP.NET MVC Core?

  2. If so, is there an example how to write and inject custom controller factory in ASP.NET MVC Core?

3
  • 1
    This looks like the built-in Areas to me. Commented Apr 2, 2016 at 12:03
  • Yes, a bit... but Areas still have Model, View and Controller folders. I want to create structure that is flat. However my primary concern here, as title of the question states, is to learn how to create and use Custom Controller Factory in MVC Core Commented Apr 2, 2016 at 12:27
  • 1
    You don't need a custom controller factory for this. MVC doesn't care how your Controllers or Models are structured. They are all ultimately compiled into a DLL, and their location with the project folders are irrelevant. Views, on the hand, are filesystem based, and the framework needs to know where to find them, which typically means your own View engine, or as Ciel mentions, a ViewExpander. Of course, tooling won't understand your structure, such as scaffolding, but that's a different problem. Commented Apr 8, 2016 at 21:59

1 Answer 1

2

I think what you want is a ViewExpander, as we discussed in the ASP.NET JabbR channel.

You simply setup the expander and use it to tell the framework how to interpret searches for Views. {0} - Controller Action {1} - Controller Name {2} - Area (if applicable)

using System;
using System.Collections.Generic;
using System.Linq;

namespace Microsoft.AspNet.Mvc.Razor {

    public class ViewExpander : IViewLocationExpander {

        public void PopulateValues(ViewLocationExpanderContext context) {
        }

        public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations) {
            return viewLocations.ToList().Then(n => {
                n.Add("/Layout/{1}/{0}.cshtml");
                n.Add("/Layout/{0}.cshtml");
                n.Add("/web/Views/{1}/{0}.cshtml");
                n.Add("/web/Views/Shared/{0}.cshtml");
            });
        }
    }
}

Then in your Startup.cs, in the ConfigureServices method, you wire it up;

services.Configure<RazorViewEngineOptions>(o => {
    o.ViewLocationExpanders.Add(new ViewExpander());
});

Some of the names of these may have changed in the newest RC2 edge builds/nightly builds, but the functionality is still there.

Controllers can go in any folder, and have any namespace setup you want - so there's not a need to change anything there.

Sign up to request clarification or add additional context in comments.

1 Comment

None of the names changed in RC2, everything works out of the box. For the completeness of this answer I must add that "Then" is an extension method public static T Then<T>(this T entity, Action action) { action(); return entity; }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.