1

라이브러리 AttributeRouting을 사용하여을 기반으로 기본 경로 제약 조건을 으로 지정하여 특성 라우팅을 구성 할 수있었습니다.매개 변수 이름을 기반으로 글로벌 경로 제약 조건 추가

예를 들어, 로 끝나는 모든 경로 매개 변수에 대한 RegexRouteConstraint을 추가 : 나는 약 custom route constraints in MVC5에 대해 알고

routes.MapAttributeRoutes(cfg => 
    { 
     cfg.AddDefaultRouteConstraint(@"year$", 
      new RegexRouteConstraint(@"^([1-2]\d{3})$")); 
    } 
); 

,하지만 난 정말하여 일부 제약 조건을 추가 할 수 있도록하고 싶습니다 단순히 매개 변수 이름에 기반한 규칙.

MVC5.1의 속성 라우팅 기능을 사용하여 동일한 작업을 수행 할 수 있습니까?

답변

1

필자는 철저히 테스트하지는 않았지만 동일한 필요성을 갖고 해결책을 찾았습니다. 내 시나리오는 경로가 모두 "api/{tenant}/..."로 시작하는 멀티 테넌트 API입니다. 테넌트는 web.config에서 가져 오므로 내 사용자 지정 리졸버가 싱글 톤이어야한다는 추가 복잡성이 있습니다. 아래의 솔루션은 웹 API 용이지만 몇 가지 네임 스페이스 조정을 통해 MVC에서 작동 할 것으로 기대합니다.

IHttpRouteConstraint의 구현을 만듭니다. 이것은 내 것입니다 :

public class TenantRouteConstraint : IHttpRouteConstraint 
{ 
    public const string TenantKey = "tenant"; 

    private readonly ISet<string> _tenants; 

    public TenantRouteConstraint() 
    { 
     _tenants = new HashSet<string>(); 
     foreach (ConnectionStringSettings connectionString in ConfigurationManager.ConnectionStrings) 
     { 
      _tenants.Add(connectionString.Name.ToLowerInvariant()); 
     } 
    } 

    private static string GetTenant(IDictionary<string, object> values) 
    { 
     object tenant; 
     if (values.TryGetValue(TenantKey, out tenant)) 
     { 
      return tenant.ToString().ToLowerInvariant(); 
     } 
     return null; 
    } 

    public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection) 
    { 
     var tenant = GetTenant(values); 
     return tenant != null && _tenants.Contains(tenant); 
    } 
} 

그 부분은 쉬웠고, 그때 까다로워졌습니다. 경로는 일반적으로 WebApiConfig.Register에서 초기화되며, Global.asax에서 GlobalConfiguration.Configure에 위임 된 것으로 전달됩니다. 그러나 특성 기반 경로는 Register 메서드 끝에 Routes 컬렉션에 채워지지 않습니다. 이 문제를 해결하기 위해 Register를 호출 한 WebApiConfig에 RegisterRouteConstraints 메서드를 추가했습니다.

RegisterRouteConstraints 메서드는 Routes 컬렉션을 반복하고 "{tenant}"가 경로 템플릿에 있으면 제약 조건을 추가합니다. Routes 컬렉션에는 세 가지 유형의 경로가 포함됩니다. RouteCollectionRoute, HostedHttpRoute 및 LinkGeneratioRoute입니다. 특성 기반 경로는 RouteCollectionRoute에 있지만 이러한 클래스는 내부이므로 직접 해당 유형을 테스트 할 수 없습니다. 다행히도 IEnumerable<IHttpRoute>을 구현하므로이를 확인합니다.

public static void RegisterRouteConstraints(HttpConfiguration config) 
{ 
    var tenantConstraint = new TenantRouteConstraint(); 
    AddConstraint(config.Routes, "tenant", tenantConstraint); 
} 

private static void AddConstraint(IEnumerable<IHttpRoute> routes, string key, IHttpRouteConstraint constraint) 
{ 
    foreach (var route in routes) 
    { 
     if (route.RouteTemplate.Contains("{" + key + "}") && !route.Constraints.ContainsKey(key)) 
     { 
      route.Constraints.Add(key, constraint); 
     } 

     var routeCollection = route as IEnumerable<IHttpRoute>; 
     if (routeCollection != null) 
     { 
      AddConstraint(routeCollection, key, constraint); 
     } 
    } 
} 

은 Global.asax에 위해 Application_Start에서 호출됩니다

// ... 
GlobalConfiguration.Configure(WebApiConfig.Register); 
GlobalConfiguration.Configure(WebApiConfig.RegisterRouteConstraints); 
// ... 
관련 문제