private static string TransformPageRoute(PageRouteModel model, SelectorModel selectorModel) { // Transformer not set on page route if (model.RouteParameterTransformer == null) { return(selectorModel.AttributeRouteModel.Template); } var pageRouteMetadata = selectorModel.EndpointMetadata.OfType <PageRouteMetadata>().SingleOrDefault(); if (pageRouteMetadata == null) { // Selector does not have expected metadata // This selector was likely configured by AddPageRouteModelConvention // Use the existing explicitly configured template return(selectorModel.AttributeRouteModel.Template); } var segments = pageRouteMetadata.PageRoute.Split('/'); for (var i = 0; i < segments.Length; i++) { segments[i] = model.RouteParameterTransformer.TransformOutbound(segments[i]); } var transformedPageRoute = string.Join("/", segments); // Combine transformed page route with template return(AttributeRouteModel.CombineTemplates(transformedPageRoute, pageRouteMetadata.RouteTemplate)); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddDbContext <TenantDbContext>(); services.AddDbContext <ApplicationDbContext>(builder => builder.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"))); services.AddDefaultIdentity <IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores <TenantDbContext>(); services.AddControllersWithViews(); services.AddRazorPages(options => { options.Conventions.AddAreaFolderRouteModelConvention("Identity", "/Account", model => { foreach (var selector in model.Selectors) { selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{__tenant__}", selector.AttributeRouteModel.Template); } }); }); services.DecorateService <LinkGenerator, AmbientValueLinkGenerator>(new List <string> { "__tenant__" }); services.AddMultiTenant <SaasTenantInfo>().WithRouteStrategy() .WithEFCoreStore <ApplicationDbContext, SaasTenantInfo>().WithPerTenantAuthentication(); }
public void ConfigureServices(IServiceCollection services) { // Register the db context, but do not specify a provider/connection // string since these vary by tenant. services.AddDbContext <ApplicationDbContext>(); services.AddDefaultIdentity <IdentityUser>() .AddEntityFrameworkStores <ApplicationDbContext>(); services.AddControllersWithViews().AddRazorRuntimeCompilation(); services.AddRazorPages(options => { // Since we are using the route multitenant strategy we must add the // route parameter to the Pages conventions used by Identity. options.Conventions.AddAreaFolderRouteModelConvention("Identity", "/Account", model => { foreach (var selector in model.Selectors) { selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{__tenant__}", selector.AttributeRouteModel.Template); } }); }); services.DecorateService <LinkGenerator, AmbientValueLinkGenerator>(new List <string> { "__tenant__" }); services.AddMultiTenant <SampleTenantInfo>() .WithRouteStrategy() .WithConfigurationStore() .WithPerTenantAuthentication(); }
private static string TransformPageRoute(PageRouteModel model, SelectorModel selectorModel) { model.Properties.TryGetValue(typeof(IOutboundParameterTransformer), out var transformer); var pageRouteTransformer = transformer as IOutboundParameterTransformer; // Transformer not set on page route if (pageRouteTransformer == null) { return(selectorModel.AttributeRouteModel.Template); } var pageRouteMetadata = selectorModel.EndpointMetadata.OfType <PageRouteMetadata>().SingleOrDefault(); if (pageRouteMetadata == null) { // Selector does not have expected metadata. Should never reach here throw new InvalidOperationException("Page selector did not have page route metadata."); } var segments = pageRouteMetadata.PageRoute.Split('/'); for (var i = 0; i < segments.Length; i++) { segments[i] = pageRouteTransformer.TransformOutbound(segments[i]); } var transformedPageRoute = string.Join("/", segments); // Combine transformed page route with template return(AttributeRouteModel.CombineTemplates(transformedPageRoute, pageRouteMetadata.RouteTemplate)); }
public void Apply(PageRouteModel model) { foreach (var selector in model.Selectors) { selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates($"{{{PrefixLocalizationOptions.LocaleRouteParameterName}:{PrefixLocalizationOptions.LocaleRouteConstraintKey}}}/", selector.AttributeRouteModel.Template); } }
public void ConfigureServices(IServiceCollection services) { // Register the db context, but do not specify a provider/connection // string since these vary by tenant. services.AddDbContext <ApplicationDbContext>(); services.AddIdentity <MultiTenantIdentityUser, MultiTenantIdentityRole>() .AddDefaultTokenProviders() .AddDefaultUI(UIFramework.Bootstrap4) .AddEntityFrameworkStores <ApplicationDbContext>(); services.AddAuthentication() .AddGoogle("Google", options => { // These configuration settings should be set via user-secrets or environment variables! options.ClientId = Configuration.GetValue <string>("GoogleClientId"); options.ClientSecret = Configuration.GetValue <string>("GoogleClientSecret"); options.AuthorizationEndpoint = string.Concat(options.AuthorizationEndpoint, "?prompt=consent"); }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .AddMvcOptions(options => options.EnableEndpointRouting = false) .AddRazorPagesOptions(options => { // Since we are using the route multitenant strategy we must add the // route parameter to the Pages conventions used by Identity. options.Conventions.AddAreaFolderRouteModelConvention("Identity", "/Account", model => { foreach (var selector in model.Selectors) { selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{__tenant__}", selector.AttributeRouteModel.Template); } }); }); services.AddMultiTenant() .WithRouteStrategy(ConfigRoutes) .WithInMemoryStore(Configuration.GetSection("Finbuckle:MultiTenant:InMemoryStore")) .WithRemoteAuthentication() .WithPerTenantOptions <CookieAuthenticationOptions>((options, tenantInfo) => { // Since we are using the route strategy configure each tenant // to have a different cookie name and adjust the paths. options.Cookie.Name = $"{tenantInfo.Id}_{options.Cookie.Name}"; // See below for why this is commented out. //options.LoginPath = $"/{tenantInfo.Identifier}/Home/Login"; //options.LogoutPath = $"/{tenantInfo.Identifier}"; options.Cookie.Path = $"/{tenantInfo.Identifier}"; }); // Required due to a bug in ASP.NET Core Identity (https://github.com/aspnet/Identity/issues/2019) services.PostConfigure <CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme, options => { // This will result in a path of /_tenant_/Identity/Account/Login options.LoginPath = $"{options.Cookie.Path}{options.LoginPath}"; options.LogoutPath = $"{options.Cookie.Path}{options.LogoutPath}"; }); }
public void Combine_EmptyTemplates(string left, string right, string expected) { // Arrange & Act var combined = AttributeRouteModel.CombineTemplates(left, right); // Assert Assert.Equal(expected, combined); }
private static SelectorModel CreateSelectorModel(string prefix, string template) { return(new SelectorModel { AttributeRouteModel = new AttributeRouteModel { Template = AttributeRouteModel.CombineTemplates(prefix, template), } }); }
private static SelectorModel CreateSelectorModel(string prefix, string routeTemplate) { return(new SelectorModel { AttributeRouteModel = new AttributeRouteModel { Template = AttributeRouteModel.CombineTemplates(prefix, routeTemplate) }, EndpointMetadata = { new PageRouteMetadata(prefix, routeTemplate) } }); }
private static void RewriteTenantPageRoute(PageRouteModel model) { var selectorCount = model.Selectors.Count; for (var i = 0; i < selectorCount; i++) { var selector = model.Selectors[i]; var template = selector.AttributeRouteModel.Template; var tenantTemplates = AttributeRouteModel.CombineTemplates("{tenant}", template); selector.AttributeRouteModel.Template = tenantTemplates; } }
public void ConfigureServices(IServiceCollection services) { // Register the db context, but do not specify a provider/connection // string since these vary by tenant. services.AddDbContext <ApplicationDbContext>(); services.AddIdentity <ApplicationUser, ApplicationRole>() .AddEntityFrameworkStores <ApplicationDbContext>() .AddDefaultTokenProviders(); services.Configure <DataProtectionTokenProviderOptions>(options => { options.TokenLifespan = TimeSpan.FromDays(1.0); }); services.Configure <IdentityOptions>(options => { // Default Password settings. options.Password.RequireDigit = false; options.Password.RequireLowercase = false; options.Password.RequireNonAlphanumeric = false; options.Password.RequireUppercase = false; options.Password.RequiredLength = 6; options.Password.RequiredUniqueChars = 1; }); //services.AddControllersWithViews().AddRazorRuntimeCompilation(); services.AddRazorPages(options => { // Since we are using the route multitenant strategy we must add the // route parameter to the Pages conventions used by Identity. options.Conventions.AddAreaFolderRouteModelConvention("Identity", "/Account", model => { foreach (var selector in model.Selectors) { selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{__tenant__}", selector.AttributeRouteModel.Template); } }); }); services.DecorateService <LinkGenerator, AmbientValueLinkGenerator>(new List <string> { "__tenant__" }); services.AddMultiTenant <ApplicationTenantInfo>() .WithRouteStrategy() .WithConfigurationStore() .WithPerTenantAuthentication(); }
public void Combine_RightOverridesReflectedAttributeRouteModel( AttributeRouteModel left, AttributeRouteModel right) { // Arrange var expectedTemplate = AttributeRouteModel.CombineTemplates(null, right.Template); // Act var combined = AttributeRouteModel.CombineAttributeRouteModel(left, right); // Assert Assert.NotNull(combined); Assert.Equal(expectedTemplate, combined.Template); Assert.Equal(combined.Order, right.Order); }
public void Apply(PageRouteModel model) { (from SelectorModel in model.Selectors select new SelectorModel { AttributeRouteModel = new AttributeRouteModel { Order = -1, Template = AttributeRouteModel.CombineTemplates("/{culture:required}", SelectorModel.AttributeRouteModel.Template) } }) .ToList() .ForEach(s => model.Selectors.Add(s)); }
public void ConfigureServices(IServiceCollection services) { // Register the db context, but do not specify a provider/connection // string since these vary by tenant. services.AddDbContext <ApplicationDbContext>(); services.AddIdentity <IdentityUser, IdentityRole>() .AddDefaultTokenProviders() .AddDefaultUI() .AddEntityFrameworkStores <ApplicationDbContext>(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1) .AddRazorPagesOptions(options => { // Since we are using the route multitenant strategy we must add the // route parameter to the Pages conventions used by Identity. options.Conventions.AddAreaFolderRouteModelConvention("Identity", "/Account", model => { foreach (var selector in model.Selectors) { selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{__tenant__}", selector.AttributeRouteModel.Template); } }); }); services.AddMultiTenant() .WithRouteStrategy(ConfigRoutes) .WithConfigurationStore() .WithPerTenantOptions <CookieAuthenticationOptions>((options, tenantInfo) => { // Since we are using the route strategy configure each tenant // to have a different cookie name and adjust the paths. options.Cookie.Name = $"{tenantInfo.Id}_{options.Cookie.Name}"; // See below for why this is commented out. //options.LoginPath = $"/{tenantInfo.Identifier}/Home/Login"; //options.LogoutPath = $"/{tenantInfo.Identifier}"; options.Cookie.Path = $"/{tenantInfo.Identifier}"; }); // Required due to a bug in ASP.NET Core Identity (https://github.com/aspnet/Identity/issues/2019) services.PostConfigure <CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme, options => { // This will result in a path of /_tenant_/Identity/Account/Login options.LoginPath = $"{options.Cookie.Path}{options.LoginPath}"; options.LogoutPath = $"{options.Cookie.Path}{options.LogoutPath}"; }); }
public void Apply(PageRouteModel model) { var selectorCount = model.Selectors.Count; for (var i = 0; i < selectorCount; i++) { var selector = model.Selectors[i]; model.Selectors.Add(new SelectorModel { AttributeRouteModel = new AttributeRouteModel { Order = -1, Template = AttributeRouteModel.CombineTemplates("{culture?}", selector.AttributeRouteModel.Template), } }); } }
private static void AppendTenantPageRoute(PageRouteModel model) { var selectorCount = model.Selectors.Count; for (var i = 0; i < selectorCount; i++) { var selector = model.Selectors[i]; var appended = new SelectorModel(selector); var template = appended.AttributeRouteModel.Template; var tenantTemplates = AttributeRouteModel.CombineTemplates("{tenant}", template); appended.AttributeRouteModel.Template = tenantTemplates; model.Selectors.Add(appended); } }
public static IPageRouteModelConvention AddFolderRouteParameter( this PageConventionCollection conventions, string folder, string routeParameter) { return(conventions.AddFolderRouteModelConvention(folder, model => { foreach (var s in model.Selectors) { var templateWithId = AttributeRouteModel .CombineTemplates(s.AttributeRouteModel.Template, routeParameter); s.AttributeRouteModel.Template = templateWithId; } })); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); // Register the ToDo db context, but do not specify a provider/connection string since // these vary by tenant. services.AddDbContext <ToDoDbContext>(); // Configure Identity services.AddRazorPages(options => { // Since we are using the route multitenant strategy we must add the // route parameter to the Pages conventions used by Identity. options.Conventions.AddAreaFolderRouteModelConvention("Identity", "/Account", model => { foreach (var selector in model.Selectors) { selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{__tenant__}", selector.AttributeRouteModel.Template); } }); }); // Preserve the tenant route param when new links are generated. services.DecorateService <LinkGenerator, AmbientValueLinkGenerator>(new List <string> { "__tenant__" }); services.AddDbContext <FinbuckleSqlServerToDoIdentityDbContext>(options => options.UseSqlite(Configuration.GetConnectionString("FinbuckleSqlServerToDoIdentityDbContextConnection"))); services.AddDefaultIdentity <IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores <FinbuckleSqlServerToDoIdentityDbContext>(); // Register the tenant store db context. services.AddDbContext <TenantStoreDbContext>(options => { options.UseSqlServer(Configuration.GetConnectionString("TenantStoreConnectionString")); }); // Configure Finbuckle, the store db context does not need to be // added separately. // Also note this must come after Identity configuration. services.AddMultiTenant <TenantInfo>() .WithEFCoreStore <TenantStoreDbContext, TenantInfo>() .WithRouteStrategy() .WithPerTenantAuthentication(); }
public void ConfigureServices(IServiceCollection services) { // Register the db context, but do not specify a provider/connection // string since these vary by tenant. services.AddDbContext <ApplicationDbContext>(); services.AddDefaultIdentity <MultiTenantIdentityUser>() .AddEntityFrameworkStores <ApplicationDbContext>(); services.AddAuthentication() .AddGoogle("Google", options => { // These configuration settings should be set via user-secrets or environment variables! options.ClientId = Configuration.GetValue <string>("GoogleClientId"); options.ClientSecret = Configuration.GetValue <string>("GoogleClientSecret"); options.AuthorizationEndpoint = string.Concat(options.AuthorizationEndpoint, "?prompt=consent"); }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1) .AddRazorPagesOptions(options => { // Since we are using the route multitenant strategy we must add the // route parameter to the Pages conventions used by Identity. options.Conventions.AddAreaFolderRouteModelConvention("Identity", "/Account", model => { foreach (var selector in model.Selectors) { selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{__tenant__}", selector.AttributeRouteModel.Template); } }); }); services.AddMultiTenant() .WithRouteStrategy(ConfigRoutes) .WithInMemoryStore(Configuration.GetSection("Finbuckle:MultiTenant:InMemoryStore")) .WithPerTenantOptions <CookieAuthenticationOptions>((options, tenantInfo) => { // Since we are using the route strategy configure each tenant // to have a different cookie name and adjust the paths. options.Cookie.Name = $"{tenantInfo.Id}_{options.Cookie.Name}"; options.LoginPath = $"/{tenantInfo.Identifier}/Home/Login"; options.LogoutPath = $"/{tenantInfo.Identifier}"; options.Cookie.Path = $"/{tenantInfo.Identifier}"; }); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddApplication(); services.AddInfrastructure(Configuration); services.AddScoped <ICurrentUserService, CurrentUserService>(); services.AddAutoMapper(Assembly.GetExecutingAssembly()); services.AddHttpContextAccessor(); services.AddSingleton <IFileProvider>( new PhysicalFileProvider( Path.Combine(Directory.GetCurrentDirectory(), @"wwwroot"))); services.AddControllersWithViews(o => { // o.Filters.Add<RequireTenantContextFilter>(); }) .AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver()) .AddRazorRuntimeCompilation(); services.AddRazorPages(options => { // Since we are using the route multitenant strategy we must add the // route parameter to the Pages conventions used by Identity. options.Conventions.AddAreaFolderRouteModelConvention("Identity", "/Account", model => { foreach (var selector in model.Selectors) { selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates($"{{{Domain.Constants.RouteTenantParameterName}}}", selector.AttributeRouteModel.Template); } }); }); services.DecorateService <LinkGenerator, AmbientValueLinkGenerator>(new List <string> { $"{Domain.Constants.RouteTenantParameterName}" }); services.AddTransient <Microsoft.AspNetCore.Identity.UI.Services.IEmailSender, EmailSender>(); }
public void Apply(PageRouteModel model) { var route = model.Selectors.FirstOrDefault()?.AttributeRouteModel; if (route == null) { return; } if (!route.Template.StartsWith(model.AreaName)) { return; } if (route.Template.Contains("/Admin/") || model.Properties.ContainsKey("Admin")) { route.Template = AttributeRouteModel.CombineTemplates(_adminUrlPrefixTemplate, route.Template); } }
///<summary> ///运用到所有页面路由模型中,制定页面路由模板,比如访问index页。 ///路由模板可以是/index 也可以是/index/{可选参数} ///</summary> ///<param name="model"></param> public void Apply(PageRouteModel model) { var selectorCount = model.Selectors.Count; for (var i = 0; i < selectorCount; i++) { var selector = model.Selectors[i]; model.Selectors.Add(new SelectorModel { AttributeRouteModel = new AttributeRouteModel { //执行路由顺序 Order = 1, //页面路由模板 Template = AttributeRouteModel.CombineTemplates(selector.AttributeRouteModel.Template, "{globalTemplate?}") } }); } }
public void Apply(PageRouteModel model) { var selectorCount = model.Selectors.Count; for (var i = 0; i < selectorCount; i++) { var selector = model.Selectors[i]; if (selector.AttributeRouteModel.Template != "Index" && !selector.AttributeRouteModel.Template.EndsWith("/Index")) { model.Selectors.Add(new SelectorModel { AttributeRouteModel = new AttributeRouteModel { Order = -1, Template = AttributeRouteModel.CombineTemplates($"{{{CultureTemplateParameter}?}}", selector.AttributeRouteModel.Template), } }); } } }
// https://github.com/dotnet/aspnetcore/issues/16960 public void Apply(PageRouteModel model) { var selectorCount = model.Selectors.Count; for (var i = 0; i < selectorCount; i++) { var selector = model.Selectors[i]; model.Selectors.Add(new SelectorModel { AttributeRouteModel = new AttributeRouteModel { Order = -1, Template = AttributeRouteModel.CombineTemplates("{culture}", selector.AttributeRouteModel.Template), // Ref above github issue - culture changed to required }, }); // Ref above github issue - original routes suppressed so URLs can't be made using its non-prefixed template selector.AttributeRouteModel.SuppressLinkGeneration = true; } }
public void ConfigureServices(IServiceCollection services) { // Register the db context, but do not specify a provider/connection // string since these vary by tenant. services.AddDbContext <ApplicationDbContext>(); services.AddDefaultIdentity <IdentityUser>() .AddEntityFrameworkStores <ApplicationDbContext>(); services.AddControllersWithViews().AddRazorRuntimeCompilation(); services.AddRazorPages(options => { // Since we are using the route multitenant strategy we must add the // route parameter to the Pages conventions used by Identity. options.Conventions.AddAreaFolderRouteModelConvention("Identity", "/Account", model => { foreach (var selector in model.Selectors) { selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{__tenant__}", selector.AttributeRouteModel.Template); } }); }); services.DecorateService <LinkGenerator, AmbientValueLinkGenerator>(new List <string> { "__tenant__" }); services.AddMultiTenant() .WithRouteStrategy() .WithConfigurationStore() .WithPerTenantOptions <CookieAuthenticationOptions>((options, tenantInfo) => { // Since we are using the route strategy configure each tenant // to have a different cookie name and adjust the paths. options.Cookie.Path = $"/{tenantInfo.Identifier}"; options.Cookie.Name = $"{tenantInfo.Id}_authentication"; options.LoginPath = $"{options.Cookie.Path}{options.LoginPath}"; options.LogoutPath = $"{options.Cookie.Path}{options.LogoutPath}"; }); }
public void Apply(PageRouteModel model) { var isIndexPage = model.ViewEnginePath.EndsWith("/Index", StringComparison.OrdinalIgnoreCase); foreach (var selector in model.Selectors.ToList()) { var template = selector.AttributeRouteModel.Template; if (isIndexPage) { var isIndexRoute = template.EndsWith("Index", StringComparison.OrdinalIgnoreCase); if (isIndexRoute) { model.Selectors.Remove(selector); continue; } } selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates(template, "{handler?}/{id?}"); } }
private static SelectorModel MakeLocalizedSelector( SelectorModel controllerSelector, SelectorModel actionSelector, bool withCultureToken) { var routeModel = controllerSelector != null ? AttributeRouteModel.CombineAttributeRouteModel(controllerSelector.AttributeRouteModel, actionSelector.AttributeRouteModel) : new AttributeRouteModel(actionSelector.AttributeRouteModel); var selector = new SelectorModel(actionSelector) { AttributeRouteModel = routeModel }; if (withCultureToken) { routeModel.Template = AttributeRouteModel.CombineTemplates("{culture:culture}", routeModel.Template.TrimStart('~', '/')); routeModel.Order = -2; selector.AttributeRouteModel = routeModel; } else { routeModel.Order = -1; if (routeModel.Name.HasValue()) { routeModel.Name += "__noculture"; } } if (!routeModel.IsAbsoluteTemplate) { // Absolutize pattern routeModel.Template = '/' + routeModel.Template; } selector.EndpointMetadata.Insert(0, new LocalizedRouteMetadata(selector.AttributeRouteModel, !withCultureToken)); return(selector); }
public void Apply(PageRouteModel model) { StringBuilder log = new StringBuilder(); log.AppendLine("=================================="); log.AppendLine($"Count:{model.Selectors.Count} ViewEnginePath:{model.ViewEnginePath} RelativePath:{model.RelativePath}"); var selectorCount = model.Selectors.Count; for (var i = 0; i < selectorCount; i++) { var selector = model.Selectors[i]; log.AppendLine("未添加前"); log.AppendLine($"Order:{selector.AttributeRouteModel.Order} , Template:{selector.AttributeRouteModel.Template}"); //在现有的基础上添加新的路由模板 model.Selectors.Add(new SelectorModel { AttributeRouteModel = new AttributeRouteModel { Order = 1, //有当前的模板和自定义模板合并为一个新的模板 Template = AttributeRouteModel.CombineTemplates( //获取当前的模板 selector.AttributeRouteModel.Template, "{globalTemplate?}"), } }); log.AppendLine($"添加完之后,Count:{model.Selectors.Count}"); foreach (var s in model.Selectors) { log.AppendLine($"Order:{s.AttributeRouteModel.Order} , Template:{s.AttributeRouteModel.Template}"); } _logger.LogDebug(log.ToString()); } }
/// <summary> /// Aplica a convenção que será aplicada durante a rota e construção das PageModel(s) /// </summary> /// <param name="model">Recebe a PageModel por injeção de dependência? ou metodo extendido?</param> public void Apply(PageRouteModel model) { var selectorCount = model.Selectors.Count; for (int i = 0; i < selectorCount; i++) { var selector = model.Selectors[i]; model.Selectors.Add(new SelectorModel { AttributeRouteModel = new AttributeRouteModel { // A ordem das PageModel geralmente iniciam com Order = 1. // Deixando esta convenção com Order = 0 informa que esta convenção deverá ser priorizada. Order = 0, // Combina o template da PageModel com o novo template abaixo: Template = AttributeRouteModel.CombineTemplates( selector.AttributeRouteModel.Template, "{globalTemplate?}" ) } }); } }
private void ProcessSelectors(IList <SelectorModel> selectors) { List <SelectorModel> matchedSelectors = selectors.Where(x => x.AttributeRouteModel != null).ToList(); if (matchedSelectors.Any()) { foreach (SelectorModel selectorModel in matchedSelectors) { selectorModel.AttributeRouteModel.Template = "/" + AttributeRouteModel.CombineTemplates(centralPrefix_.Template, selectorModel.AttributeRouteModel.Template); } } List <SelectorModel> unmatchedSelectors = selectors.Where(x => x.AttributeRouteModel == null).ToList(); if (unmatchedSelectors.Any()) { foreach (SelectorModel selectorModel in unmatchedSelectors) { selectorModel.AttributeRouteModel = centralPrefix_; } } }