Fallback route for MVC Areas

2019-04-13 07:09发布

问题:

Using asp.net core MVC application here. I have my areas defined and routing works as expected.

One thing i would like to do, is have a fallback route in case the area does not exist.

I have the following structure:

APP
-- Areas
   -- SharedArea
      -- Controllers
         -- LoginController
         -- UserController
         -- AnotherController
         -- AndSoOnController
   -- SomeArea1
      -- Controllers
         -- HomeController
   -- SomeArea2
      -- Controllers
         -- HomeController
         -- LoginController

My ultimate goal, is to have shared controllers that is being used as a fallback in the event that an area does not have the specified controller.

Scenario 1

User currently browse SomeArea1 and clicks on Login. There is no LoginController for SomeArea1 and he gets directed to SharedArea\Login.

Scenario 2

User currently browse SomeArea2 and clicks on Login. There is aLoginController for SomeArea2 and he gets directed to SomeArea2\Login.

How would one go about configuring your routes in the Startup.cs file?

My current route setup in startup.cs:

app.UseMvc(routes =>
        {
            routes.DefaultHandler = areaRouter;
            routes.MapRoute("areaRoute", "{area:exists}/{controller=Home}/{action=Index}/{id?}");
            routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
        });

areaRouter is a custom implimentation for subdomain routing, you can view more here: subdomain routing to areas

回答1:

One thing i would like to do, is have a fallback route in case the area does not exist.

Implement the base controllers for each area. In this way the controllers from those areas will use the HandleAttribute from the base controller. It's only 1 setting (one for each area in fact)

Scenario1: Create a base(shared) Controller in your area:

[Authorize(ActiveAuthenticationSchemes = "sharedarea")]//see solution for next scenario
public class SharedAreaController : Controller
{
    [AllowAnonymous]
    public login()
    {

    }
}

Derive SomeArea1 controllers from this controller:

public class HomeController : SharedAreaController 
{
    // actions for this controller
}

Scenario2: The place where you register you CookieAuthentication middleware, do this:

app.UseCookieAuthentication(o =>
{
    o.LoginPath = "/SomeArea2/login";
    o.AuthenticationScheme = "SomeArea2";
    //TODO: set other interesting properties if you want to
});

then On you controller/action, specify the authentication scheme like:

[Authorize(ActiveAuthenticationSchemes = "SomeArea2")]
public IActionResult PageWhichNeedsArea2Auth()
{
    return Content("sth");
}

I hope to be helpful :)