diff --git a/zero.Api/ZeroApiControllerModelConvention.cs b/zero.Api/ZeroApiControllerModelConvention.cs index 0cbb7075..5b3d053f 100644 --- a/zero.Api/ZeroApiControllerModelConvention.cs +++ b/zero.Api/ZeroApiControllerModelConvention.cs @@ -50,17 +50,14 @@ public class ZeroApiControllerModelConvention : IControllerModelConvention } - protected AttributeRouteModel BuildRouteModel(string pathSegment, bool appAware = false) + protected virtual AttributeRouteModel BuildRouteModel(string pathSegment, bool appAware = false) { StringBuilder path = new(); path.Append(pathSegment.EnsureSurroundedWith('/')); - if (appAware) - { - path.Append("{zero_app_key}/"); - // TODO add route constraint which only allows registered app-ids - // see https://nemi-chand.github.io/creating-custom-routing-constraint-in-aspnet-core-mvc/ - } + path.Append("{zero_app_key}/"); + // TODO add route constraint which only allows registered app-ids + // see https://nemi-chand.github.io/creating-custom-routing-constraint-in-aspnet-core-mvc/ path.Append("[controller]"); diff --git a/zero.ApiTry/ApiParameterTransformer.cs b/zero.ApiTry/ApiParameterTransformer.cs deleted file mode 100644 index 1d889099..00000000 --- a/zero.ApiTry/ApiParameterTransformer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using zero.Persistence; - -namespace zero.ApiTry; - -public class ApiParameterTransformer : IOutboundParameterTransformer -{ - public string? TransformOutbound(object? value) - { - return value == null ? null : Safenames.Alias(value); - } -} \ No newline at end of file diff --git a/zero.ApiTry/Controllers/Api/AppApiController.cs b/zero.ApiTry/Controllers/Api/AppApiController.cs deleted file mode 100644 index f447b830..00000000 --- a/zero.ApiTry/Controllers/Api/AppApiController.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.ApiTry -{ - [ApiController] - public class AppApiController : ControllerBase - { - } -} diff --git a/zero.ApiTry/Controllers/Api/ByeApiController.cs b/zero.ApiTry/Controllers/Api/ByeApiController.cs deleted file mode 100644 index 06c996eb..00000000 --- a/zero.ApiTry/Controllers/Api/ByeApiController.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.ApiTry -{ - [ZeroSystemApi] - public class ByeController : AppApiController - { - [HttpGet("")] - public ActionResult Get() - { - return new JsonResult(new - { - success = true, - text = "Bye", - url = Url.Action() - }); - } - } -} diff --git a/zero.ApiTry/Controllers/Api/HelloApiController.cs b/zero.ApiTry/Controllers/Api/HelloApiController.cs deleted file mode 100644 index 395db591..00000000 --- a/zero.ApiTry/Controllers/Api/HelloApiController.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.ApiTry -{ - public class HelloController : AppApiController - { - [HttpGet("")] - public ActionResult Get() - { - return new JsonResult(new - { - success = true, - text = "Hello", - url = Url.Action() - }); - } - } -} diff --git a/zero.ApiTry/Controllers/FrontendController.cs b/zero.ApiTry/Controllers/FrontendController.cs deleted file mode 100644 index a7e4f988..00000000 --- a/zero.ApiTry/Controllers/FrontendController.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.ApiTry -{ - public class FrontendController : Controller - { - public ActionResult Index() - { - return new ContentResult() - { - Content = "This is our frontend
url:" + Request.Path, - ContentType = "text/html", - StatusCode = 200 - }; - } - } -} \ No newline at end of file diff --git a/zero.ApiTry/Controllers/OutController.cs b/zero.ApiTry/Controllers/OutController.cs deleted file mode 100644 index aed5709c..00000000 --- a/zero.ApiTry/Controllers/OutController.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace zero.ApiTry -{ - [ApiController] - public class OutController : ControllerBase - { - [HttpGet("get")] - public ActionResult Get() - { - return new JsonResult(new - { - success = true, - text = "Out", - url = Url.Action() - }); - } - } -} \ No newline at end of file diff --git a/zero.ApiTry/DisableBrowserCacheFilter.cs b/zero.ApiTry/DisableBrowserCacheFilter.cs deleted file mode 100644 index 4414434c..00000000 --- a/zero.ApiTry/DisableBrowserCacheFilter.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.Net.Http.Headers; - -namespace zero.ApiTry; - -/// -/// Ensures that the request is not cached by the browser -/// -public class DisableBrowserCacheFilterAttribute : ActionFilterAttribute -{ - public override void OnResultExecuting(ResultExecutingContext context) - { - base.OnResultExecuting(context); - - var httpResponse = context.HttpContext.Response; - - if (httpResponse.StatusCode != 200) return; - - httpResponse.GetTypedHeaders().CacheControl = - new CacheControlHeaderValue() - { - NoCache = true, - MaxAge = TimeSpan.Zero, - MustRevalidate = true, - NoStore = true - }; - - httpResponse.Headers[HeaderNames.LastModified] = DateTime.Now.ToString("R"); // Format RFC1123 - httpResponse.Headers[HeaderNames.Pragma] = "no-cache"; - httpResponse.Headers[HeaderNames.Expires] = new DateTime(1990, 1, 1, 0, 0, 0).ToString("R"); - } -} \ No newline at end of file diff --git a/zero.ApiTry/Program.cs b/zero.ApiTry/Program.cs deleted file mode 100644 index 46a45c70..00000000 --- a/zero.ApiTry/Program.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using zero.ApiTry; - -var builder = WebApplication.CreateBuilder(args); - -builder.Services.AddSingleton(); -builder.Services.AddControllers(opts => -{ - opts.Conventions.Add(new ZeroApiControllerModelConvention("/zero/api")); -}); - -var app = builder.Build(); - -app.UseRouting(); -app.MapControllers(); -app.MapDynamicControllerRoute("{**path}"); - -//app.Use(async (context, next) => -//{ -// Console.WriteLine("middleware B"); -// await next(context); -//}); - -app.Run(); \ No newline at end of file diff --git a/zero.ApiTry/Properties/launchSettings.json b/zero.ApiTry/Properties/launchSettings.json deleted file mode 100644 index f76cc41a..00000000 --- a/zero.ApiTry/Properties/launchSettings.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:20861", - "sslPort": 0 - } - }, - "profiles": { - "zero.ApiTry": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": false, - "launchUrl": "weatherforecast", - "applicationUrl": "http://localhost:5092", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": false, - "launchUrl": "weatherforecast", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/zero.ApiTry/ZeroApiControllerModelConvention.cs b/zero.ApiTry/ZeroApiControllerModelConvention.cs deleted file mode 100644 index b1365abb..00000000 --- a/zero.ApiTry/ZeroApiControllerModelConvention.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.ApplicationModels; -using System.Text; -using zero.Extensions; - -namespace zero.ApiTry; - -public class ZeroApiControllerModelConvention : IControllerModelConvention -{ - readonly AttributeRouteModel AppAwareRouteModel; - - readonly AttributeRouteModel AppUnawareRouteModel; - - readonly Type BaseClass = typeof(AppApiController); - - readonly Type SystemApiType = typeof(ZeroSystemApiAttribute); - - readonly ApiParameterTransformer Transformer = new(); - - - public ZeroApiControllerModelConvention(string apiPath = "/zero/api") - { - AppAwareRouteModel = BuildRouteModel(apiPath, true); - AppUnawareRouteModel = BuildRouteModel(apiPath, false); - } - - - /// - /// Configure routing model for all backoffice controllers - /// - public virtual void Apply(ControllerModel controller) - { - bool hasAttributeRouteModels = controller.Selectors.Any(selector => selector.AttributeRouteModel != null); - - if (controller.ControllerType.IsSubclassOf(BaseClass)) - { - bool isSystemApi = controller.Attributes.Any(x => x.GetType() == SystemApiType); - controller.Selectors[0].AttributeRouteModel = isSystemApi ? AppUnawareRouteModel : AppAwareRouteModel; - controller.Filters.Add(new DisableBrowserCacheFilterAttribute()); - - foreach (var action in controller.Actions) - { - action.RouteParameterTransformer = Transformer; - } - } - } - - - protected AttributeRouteModel BuildRouteModel(string apiPath, bool appAware = false) - { - StringBuilder path = new(); - path.Append(apiPath.EnsureSurroundedWith('/')); - - if (appAware) - { - path.Append("{zero_app_slug}/"); - } - - path.Append("[controller]"); - - return new AttributeRouteModel(new RouteAttribute(path.ToString())); - } -} \ No newline at end of file diff --git a/zero.ApiTry/ZeroRoutesTransformer.cs b/zero.ApiTry/ZeroRoutesTransformer.cs deleted file mode 100644 index da000fd3..00000000 --- a/zero.ApiTry/ZeroRoutesTransformer.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.Routing; -using Microsoft.AspNetCore.Routing; - -namespace zero.ApiTry; - -public class ZeroRoutesTransformer : DynamicRouteValueTransformer -{ - public override async ValueTask TransformAsync(HttpContext httpContext, RouteValueDictionary values) - { - if (httpContext.Request.Path.StartsWithSegments("/zero")) - { - return values; - } - - values["controller"] = "Frontend"; - values["action"] = "Index"; - return values; - } - - - public override ValueTask> FilterAsync(HttpContext httpContext, RouteValueDictionary values, IReadOnlyList endpoints) - { - return base.FilterAsync(httpContext, values, endpoints); - } -} \ No newline at end of file diff --git a/zero.ApiTry/ZeroSystemApiAttribute.cs b/zero.ApiTry/ZeroSystemApiAttribute.cs deleted file mode 100644 index 6a0bc910..00000000 --- a/zero.ApiTry/ZeroSystemApiAttribute.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace zero.ApiTry; - -[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] -public class ZeroSystemApiAttribute : Attribute { } \ No newline at end of file diff --git a/zero.ApiTry/appsettings.Development.json b/zero.ApiTry/appsettings.Development.json deleted file mode 100644 index 0c208ae9..00000000 --- a/zero.ApiTry/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/zero.ApiTry/appsettings.json b/zero.ApiTry/appsettings.json deleted file mode 100644 index 10f68b8c..00000000 --- a/zero.ApiTry/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/zero.ApiTry/zero.ApiTry.csproj b/zero.ApiTry/zero.ApiTry.csproj deleted file mode 100644 index 9fa431c5..00000000 --- a/zero.ApiTry/zero.ApiTry.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - net6.0 - enable - enable - - - - - - - diff --git a/zero.Backoffice.UI/app/axios.config.ts b/zero.Backoffice.UI/app/axios.config.ts index 15b2aa1f..9169758a 100644 --- a/zero.Backoffice.UI/app/axios.config.ts +++ b/zero.Backoffice.UI/app/axios.config.ts @@ -7,7 +7,7 @@ import Qs from 'qs'; // throw Exception('window.zero and zero.apiPath (= base path to the backoffice API) have to be configured'); //} -Axios.defaults.baseURL = '/zero/api/'; +//Axios.defaults.baseURL = '/zero/api/'; Axios.defaults.withCredentials = true; Axios.defaults.paramsSerializer = (params) => diff --git a/zero.Backoffice.UI/app/options.ts b/zero.Backoffice.UI/app/options.ts new file mode 100644 index 00000000..7fe6ba78 --- /dev/null +++ b/zero.Backoffice.UI/app/options.ts @@ -0,0 +1,6 @@ + +export const paths = { + root: '/zero', + api: '/zero/api/{app}', + backofficeApi: '/zero/api/{app}/backoffice' +}; \ No newline at end of file diff --git a/zero.Backoffice.UI/app/services/request.ts b/zero.Backoffice.UI/app/services/request.ts index 11eba027..c7dcc800 100644 --- a/zero.Backoffice.UI/app/services/request.ts +++ b/zero.Backoffice.UI/app/services/request.ts @@ -1,9 +1,11 @@  import axios from 'axios'; import { AxiosRequestConfig } from 'axios'; +import { paths } from '../options'; export interface ZeroRequestConfig extends AxiosRequestConfig { + raw?: boolean; scope?: string; } @@ -31,11 +33,27 @@ export interface ZeroRequestQuery function getConfig(config?: ZeroRequestConfig): ZeroRequestConfig { config = config || {}; + if (config.scope) { config.params = config.params || {}; config.params.scope = config.scope; } + + if (!config.raw) + { + config.baseURL = paths.api; + + if (config.url != null && config.url.indexOf('{app}') > -1) + { + config.url = config.url.replace('{app}', 'hofbauer'); + } + if (config.baseURL != null && config.baseURL.indexOf('{app}') > -1) + { + config.baseURL = config.baseURL.replace('{app}', 'hofbauer'); + } + } + return config; }; diff --git a/zero.Backoffice/ZeroBackofficeControllerModelConvention.cs b/zero.Backoffice/ZeroBackofficeControllerModelConvention.cs index ea8f8658..4d3352fe 100644 --- a/zero.Backoffice/ZeroBackofficeControllerModelConvention.cs +++ b/zero.Backoffice/ZeroBackofficeControllerModelConvention.cs @@ -1,4 +1,7 @@ -using zero.Api.Controllers; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ApplicationModels; +using System.Text; +using zero.Api.Controllers; namespace zero.Backoffice; @@ -8,4 +11,19 @@ public class ZeroBackofficeControllerModelConvention : ZeroApiControllerModelCon { BaseClassType = typeof(ZeroBackofficeController); } + + + protected override AttributeRouteModel BuildRouteModel(string pathSegment, bool appAware = false) + { + StringBuilder path = new(); + path.Append(pathSegment.EnsureSurroundedWith('/')); + + path.Append("{zero_app_key}/"); + // TODO add route constraint which only allows registered app-ids + // see https://nemi-chand.github.io/creating-custom-routing-constraint-in-aspnet-core-mvc/ + + path.Append("backoffice/[controller]"); + + return new AttributeRouteModel(new RouteAttribute(path.ToString())); + } } \ No newline at end of file diff --git a/zero.Backoffice/ZeroBackofficeMvcOptions.cs b/zero.Backoffice/ZeroBackofficeMvcOptions.cs index c4a2f70a..449cd166 100644 --- a/zero.Backoffice/ZeroBackofficeMvcOptions.cs +++ b/zero.Backoffice/ZeroBackofficeMvcOptions.cs @@ -15,6 +15,6 @@ internal class ZeroBackofficeMvcOptions : IConfigureOptions public void Configure(MvcOptions options) { - options.Conventions.Add(new ZeroBackofficeControllerModelConvention(Options.ZeroPath + "/backoffice", Options.Applications.Count > 1)); + options.Conventions.Add(new ZeroBackofficeControllerModelConvention(Options.ZeroPath + "/api", Options.Applications.Count > 1)); } } \ No newline at end of file diff --git a/zero.Backoffice/ZeroEnpointRouteBuilderExtensions.cs b/zero.Backoffice/ZeroEnpointRouteBuilderExtensions.cs index 71f55ec8..2e4a440e 100644 --- a/zero.Backoffice/ZeroEnpointRouteBuilderExtensions.cs +++ b/zero.Backoffice/ZeroEnpointRouteBuilderExtensions.cs @@ -7,7 +7,7 @@ public static class ZeroEndpointRouteBuilderExtensions public static void MapZeroBackoffice(this IZeroEndpointRouteBuilder endpoints, string path = "/zero") { endpoints.MapFallbackToController(path.EnsureEndsWith('/') + "{**path}", "Index", "ZeroIndex"); - endpoints.MapFallbackToController(path.EnsureEndsWith('/') + "backoffice/{**path}", "Index", "NotFoundZeroApi"); + //endpoints.MapFallbackToController(path.EnsureEndsWith('/') + "backoffice/{**path}", "Index", "NotFoundZeroApi"); //app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments(path + "/api"), app1 => //{ // app1.UseEndpoints(endpoints => diff --git a/zero.sln b/zero.sln index 95669180..e8fcad10 100644 --- a/zero.sln +++ b/zero.sln @@ -49,8 +49,6 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "zero.Backoffice.UI", "zero. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "zero.Demo", "zero.Demo\zero.Demo.csproj", "{8AD56129-2104-4DF5-A08E-1A94A8EC205B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "zero.ApiTry", "zero.ApiTry\zero.ApiTry.csproj", "{F49F6297-FECF-4355-8A8B-72AB29B794B2}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -93,10 +91,6 @@ Global {8AD56129-2104-4DF5-A08E-1A94A8EC205B}.Debug|Any CPU.Build.0 = Debug|Any CPU {8AD56129-2104-4DF5-A08E-1A94A8EC205B}.Release|Any CPU.ActiveCfg = Release|Any CPU {8AD56129-2104-4DF5-A08E-1A94A8EC205B}.Release|Any CPU.Build.0 = Release|Any CPU - {F49F6297-FECF-4355-8A8B-72AB29B794B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F49F6297-FECF-4355-8A8B-72AB29B794B2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F49F6297-FECF-4355-8A8B-72AB29B794B2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F49F6297-FECF-4355-8A8B-72AB29B794B2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE