1

ライブラリAttributeRoutingを使用して、パラメーター name に基づくデフォルトのルート制約を使用するように属性ルーティングを構成できました。

たとえば、 year で終わるすべてのルート パラメーターに RegexRouteConstraint を追加するには、のようにします

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

私は MVC5 のカスタム ルート制約について知っていますが、単にパラメーター名に基づいて、規則によっていくつかの制約を追加できるようにしたいと考えています。

MVC5.1 の属性ルーティング機能で同じことを行うことは可能ですか?

4

1 に答える 1

1

完全にテストしていませんが、同じニーズがあり、解決策を見つけました。私のシナリオは、ルートがすべて「api/{tenant}/...」で始まるマルチテナント API です。テナントは web.config から取得されるため、カスタム リゾルバーをシングルトンにする必要があるという複雑さが増します。以下のソリューションは Web 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 コレクションに取り込まれません。これを回避するために、登録後に呼び出される RegisterRouteConstraints メソッドを WebApiConfig に追加しました。

RegisterRouteConstraints メソッドは Routes コレクションをループし、ルート テンプレートに "{tenant}" が存在する場合、制約を追加します。Routes コレクションには、RouteCollectionRoute、HostedHttpRoute、LinkGenerationRoute の 3 種類のルートが含まれています。属性ベースのルートは 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);
// ...
于 2014-04-22T14:25:53.490 に答える