I am developing an application in ASP.NET Core MVC and I have some questions regarding the structure of the controllers and views. In summary, the application has the same structure for two types of users, Company and Investor.
The application detects what kind of user has been logged in and changes the menu links to the Company/[controller]/[action]
or Investor/[controller]/[action]
The directory structure is as follows:
Image structure of directories
The controllers have the following routing label that works well:
[Route("/Company/[controller]/[action]")]
public class DashboardController : Controller
{...
I'm having problems with the views, which have the same directory structure, since it does not detect the corresponding view. I have to put in each Action a return View("Views/Company/Dashboard/Dashboard.cshtml")
with the entire route to the view and that smells bad. The same thing happens with views that have partial renders to other views in the same subdirectory.
Example: Company/Dashboard/Dashboard.cshtml
contains:
<partial name="Users" />
Where Users.cshtml
is a view in the same directory q Dashboard.cshtml
InvalidOperationException: The partial view 'Users' was not found. The following locations were searched:
/Views/Dashboard/Users.cshtml
/Views/Shared/Users.cshtml
/Pages/Shared/Users.cshtml
Is this the best way to structure an application with these characteristics?
Is there any way to tell MVC to use another route for the views?
Thank you.
EDITED:
One solution is to add a class that implements IViewLocationExpander
public class ViewLocationExpander : IViewLocationExpander
{
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
{
string[] locations = new[]
{
"/Views/Company/{1}/{0}.cshtml",
"/Views/Investor/{1}/{0}.cshtml",
"/Views/Shared/{0}.cshtml"
};
return locations.Union(viewLocations);
}
public void PopulateValues(ViewLocationExpanderContext context)
{
context.Values["customviewlocation"] = nameof(ViewLocationExpander);
}
}
And register it with ...
services.Configure<RazorViewEngineOptions>(options =>
{
options.ViewLocationExpanders.Add(new ViewLocationExpander());
});
Now the application detects the view well BUT always selects the first one in case I enter as a Company or as an Investor, and the menu has no way of indicating one or the other Controller
Is there any way to indicate it?
<li><a asp-controller="Dashboard" asp-action="Index">Company Dashboard</a></li>
<li><a asp-controller="Dashboard" asp-action="Index">Investor Dashboard</a></li>