Динамическое определение макета на основе атрибутов AuthorizeFilter и AllowAnonymous в ASP. NET Базовый сайт - PullRequest
0 голосов
/ 28 марта 2020

Мой ASP. NET Сайт Core 3.1 имеет два макета. Один для аутентифицированных пользователей называется «_Layout.Authenticated», а другой для неаутентифицированных пользователей - «_Layout.Unauthenticated». Вместо того чтобы использовать ViewStart.cs html, чтобы указать макет по умолчанию для используемого наиболее часто, а затем указать макет для других представлений на самих представлениях, я хочу, чтобы сайт динамически определял это.

Я делаю У меня есть решение, использующее фильтры действий, и я хотел посмотреть, есть ли лучший подход.

Я создал пользовательский фильтр действий, который будет устанавливать элемент ViewData с именем макета следующим образом:

public class LayoutSelectionActionFilterAttribute : IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        ActionExecutedContext resultContext = await next().ConfigureAwait(false);

        if (resultContext.Result is ViewResult viewResult)
        {
            viewResult.ViewData["LayoutName"] = HasAllowAnonymous(context)
                ? "_Layout.Unauthenticated"
                : "_Layout.Authenticated";
        }
    }

    private static bool HasAllowAnonymous(FilterContext context)
    {
        IList<IFilterMetadata> filters = context.Filters;

        if (filters.OfType<IAllowAnonymousFilter>().Any())
        {
            return true;
        }

        Endpoint endpoint = context.HttpContext.GetEndpoint();

        return endpoint?.Metadata?.GetMetadata<IAllowAnonymous>() != null;
    }
}

Мой ViewStart.cs html выглядит так:

@{
    Layout =  ViewData["LayoutName"] as string;
}

Наконец, я настроил свои фильтры в Startup.cs следующим образом:

services.AddControllersWithViews(options =>
{
     AuthorizationPolicy authorizationPolicyBuilder = new AuthorizationPolicyBuilder()
          .RequireAuthenticatedUser()
          .Build();

     options.Filters.Add(new AuthorizeFilter(authorizationPolicyBuilder));
     options.Filters.Add(new LayoutSelectionActionFilterAttribute());
 });
...