ASP.net Web API 2 блокирует маршрут в области в корне - PullRequest
0 голосов
/ 30 июня 2018

У меня определен маршрут в области, настроена конфигурация, и маршруты запускаются, как и ожидалось, однако я также могу использовать маршруты области в корневом профиле.

Есть ли способ заблокировать корневой профиль от просмотра маршрутов моей области (определенных только в области), что-то вроде этого:

/area/api/awesomeservice -> only this one should be allowed
/api/awesomeservice -> should not be allowed

RouteConfig.cs:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapMvcAttributeRoutes();

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            namespaces: new[] { "TestBed.Controllers" }
        );
    }
}

WebApiConfig.cs:

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services

    // Web API routes
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

Сервисный контроллер в разделе / ​​Области / Услуги

ServiceController.cs

namespace TestBed.Areas.Services.Controllers
{
    public class HotFuzzController : ApiController
    {
        [HttpGet]
        public string Get()
        {
            return "Hello World";
        }
    }
}

Конфигурация зоны для Районов / Сервисов

ServicesAreaRegistration.cs

namespace TestBed.Areas.Services
{
    public class ServicesAreaRegistration : AreaRegistration 
    {
        public override string AreaName 
        {
            get 
            {
                return "Services";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context) 
        {
            context.Routes.MapHttpRoute(
                name: "ServicesApiAction",
                routeTemplate: "services/api/{controller}/{action}");

            context.Routes.MapHttpRoute(
                name: "ServicesApi",
                routeTemplate: "services/api/{controller}");

            context.MapRoute(
                "Services_default",
                "Services/{controller}/{action}/{id}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new[] { "TestBed.Areas.Services.Controllers" }
            );
        }
    }
}

Global.asax.cs

namespace TestBed
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}

1 Ответ

0 голосов
/ 02 июля 2018

Проблема возникает из-за маршрута по умолчанию, который соответствует контроллерам областей. К сожалению, в рамках нет способа (который я знаю) сделать маршрут только для контроллеров, которые не находятся в области.

Но вы можете создать собственную RouteContraint и применить свои собственные правила соответствия. Вот пример ограничения маршрута, в котором отражение используется для сопоставления только контроллеров исполняемой сборки, которые находятся в пространствах имен:

public class NamespaceFilterConstraint : System.Web.Http.Routing.IHttpRouteConstraint
{
    private Type[] types;
    public string[] AllowedNamespaces { get; }
    public NamespaceFilterConstraint(string[] ns)
    {
        AllowedNamespaces = ns;
        types = Assembly.GetExecutingAssembly().GetTypes();
    }
    public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection)
    {
        var controllerName = values["controller"] + "Controller";
        //This assumes no controllers with the same name in different namespaces
        Type controllerType = types.FirstOrDefault(t => t.Name == controllerName);
        return AllowedNamespaces.Contains(controllerType.Namespace);
    }
}

Вы можете использовать его в WebApiConfig:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional },
    constraints: new { controller = new NamespaceFilterConstraint(new string[] { "MyApp.Controllers" }) }
);
...