3

現在、C# Asp.Net Core アプリケーション用の OData Api を開発しています。

API の仕様に準拠するには、URL がマルチテナント アーキテクチャに従う必要があります。 https://website.com/api/tenants/{tenantId}/odata/

OData 4.0 には動的ベース URL を実装する方法が指定されていないため、次の回避策を実装しました。ミドルウェアを使用して、HTTP コンテキストの動的テナント ID を静的文字列「tenantId」に置き換えます。ここで、OData メタデータを変更/操作して、応答でこの回避策を元に戻す方法を見つける必要があります。

実装例

Starup.cs:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    private IConfiguration Configuration { get; }


    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDependencies(Configuration);
        services.AddDbContext<DBContext>();
        services.AddOData();
        services.AddODataQueryFilter();
        services.AddAutoMapper();
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }


    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // Custom Workaround Middleware
        app.Use(async (context, next) =>
        {
            // TGis Method parses the tenant id from the Request.Path, replaces it and wries it to the context.Items to maintain the information for later
            (Microsoft.AspNetCore.Http.HttpContext contextwTid, System.Guid tenantGuid) = ODataHelper.ParseTenantIDToContext(context);
            context = contextwTid;
            await next.Invoke();
        });

        app.UseMvc(b =>
        {
            b.Select().Filter().OrderBy().MaxTop(100).Count();
            b.MapODataServiceRoute(
                routeName: "odata",
                routePrefix: "api/tenants/tenantId/odata",
                model: ODataHelper.GetEdmModel());
        });

    }

ODataHelper:

  ...
  public static (Microsoft.AspNetCore.Http.HttpContext, Guid) ParseTenantIDToContext(Microsoft.AspNetCore.Http.HttpContext context)
    {
        System.Guid tenantGuid = System.Guid.Empty;
        if (context.Request.Path.ToString().Split('/').Length > 3 && context.Request.Path.ToString().ToLower().Contains("odata"))
        {
            bool isValidGUID = System.Guid.TryParse(context.Request.Path.ToString().Split('/')[3], result: out tenantGuid);
            if (isValidGUID)
                context.Request.Path = context.Request.Path.Value.Replace(context.Request.Path.ToString().Split('/')[3], "tenantId");
            context.Items["tenantId"] = tenantGuid.ToString();
        }
        return (context, tenantGuid);
    }
  ...

コントローラーの例:

public class ClientsController : ODataController
{
    private readonly DBService<Client> _service;

    public ClientsController(DBService<Client> service)
    {
        _service = service;
    }

    [HttpGet]
    [EnableQuery]
    [ODataRoute("Clients")]
    public async Task<IEnumerable<Client>> Get(
        ODataQueryOptions<Client> options)
    {
        System.Guid tenantId = ODataHelper.GetTenantIDFromContext(this.HttpContext);
        IQueryable res = await _service.Get(
            tenantId, 
            AuthorizationHelper.GetSubjectId(tenantId, User), 
            AuthorizationHelper.GetAllowedUserRoles(RoleType.Reporting), 
            options, 
            null);
        return new List<Client>(res.Cast<Client>());
    }
}

質問:

  1. Asp.Net Core を使用して OData に動的ベース ルーティングを実装するより良い方法はありますか?
  2. リクエストまたは OData メタデータを操作する方法はありますか。詳細には、応答は、"@OData.context" および (今後) OData ページング メタデータに動的な tenantId を含む元の URL を表示する必要があります。

これまでの調査/グーグル:

4

1 に答える 1