5
votes

I am having some difficulty configuring a default home page in an ASP.NET MVC Core 2 application. I seem to be unable to get the routing to map to the correct home page a the default when no parameters are used, ex. https://localhost:44362

I don't really like the default convention of putting Controllers in a Controllers folder, view in Views, and View Models in Models. I prefer to group by feature.

So I have a structure like this:

Features
   Home
      HomeController.cs
      HomeIndex.cshtml
      HomeViewModel.cs
   Other
      OtherController.cs
      OtherIndex.cshtml
      OtherViewModel.cs

Everything works fine, except I can't seem to get the default page to be /Home/Index when no path is provided. Everything worked when HomeController was in Controllers (and Index in Views/Home), but as soon as I moved it, things broke.

I'm using the default Startup.cs file, so I have a Configure method that looks like this:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();

    app.UseAuthentication();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

I did some searching it and it looks like using this in the ConfigureServices method should work:

services.AddMvc().AddRazorPagesOptions(options =>
{
    options.Conventions.AddPageRoute("", "/Home/Index");
});

That throws a: Value cannot be null or empty (pageName) exception. I also tried "/", "/Home/Index" as parameters. Finally, just for good measure, I also swapped the above parameters just in case I was misunderstanding usage of each parameter.

In every case, no page is displayed. If I enter the full URL /Home/Index, it works. I also tried to attach a [Route("Home")] attribute to the HomeController class and a [Route("Index")] to the action method.

So I'm obviously messed up the routing, but it's not at all clear to me how to fix this. I've read and re-read the docs on Razor Pages which doesn't seem to clear up my understanding.

2
That's because you changed completely the structure of the application, and now there's no /Home/Index, there's a /Features/Home/Home/Index. That's a pretty bad idea, IMO, you should stick to what MVC provides. Use areas if you want to group stuff. Also, AddRazorPagesOptions is for ASP.NET Core Razor Pages which you aren't using so that's not going to do anything useful - Camilo Terevinto
MVC follows a convention over configuration paradigm. The framework expects those Controllers and Views folders. Keeping your views in the Views folder also makes a more efficient deployment -- only the cshtml files need to be copied. You might look into Areas which will give you a way to group controllers. - Jasen

2 Answers

5
votes

@paul-mrozowski, you were almost correct in your solution above. For basic pages you'll have to use the following approach to change the default route, provided you Index page is under /Pages/Home/ directory:

services.AddMvc().AddRazorPagesOptions(options =>
{
    options.Conventions.AddPageRoute("/Home/Index", "");
});

Just in case someone is using Areas, an approach would be similar, provided your Index page is located under /Areas/SomeArea/Pages/ directory:

services.AddMvc().AddRazorPagesOptions(options =>
{
    options.Conventions.AddAreaPageRoute("SomeArea", "/Index", "");
});
4
votes

It looks like all I needed to do was adjust the locations the Razor view engine looks in my Startup.cs

How to specify the view location

and here in this blog post:

Feature Folder Structure in ASP.NET Core

Then I just needed to remove my Route attributes I had added during testing and it started working.