Мой 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());
});