diff --git a/NetSwissTools.Web.sln b/NetSwissTools.Web.sln
index b236a82..0575020 100644
--- a/NetSwissTools.Web.sln
+++ b/NetSwissTools.Web.sln
@@ -1,12 +1,40 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.7.34031.279
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.34031.81
MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{E938E22F-DEA2-42A9-A2DC-F81A555BB1FF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{8C65E219-42F9-41FC-ADFB-4938C1DB2E51}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetSwissTools.Web", "src\NetSwissTools.Web\NetSwissTools.Web.csproj", "{58742414-637E-4AAA-8FC4-A8C7C93FAE49}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{A82929A9-88AB-4C42-A160-4AC238D4528F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Clients.API", "samples\Clients.API\Clients.API.csproj", "{117B883A-1C2C-46AE-880B-403B2609EC0B}"
+EndProject
Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {58742414-637E-4AAA-8FC4-A8C7C93FAE49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {58742414-637E-4AAA-8FC4-A8C7C93FAE49}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {58742414-637E-4AAA-8FC4-A8C7C93FAE49}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {58742414-637E-4AAA-8FC4-A8C7C93FAE49}.Release|Any CPU.Build.0 = Release|Any CPU
+ {117B883A-1C2C-46AE-880B-403B2609EC0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {117B883A-1C2C-46AE-880B-403B2609EC0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {117B883A-1C2C-46AE-880B-403B2609EC0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {117B883A-1C2C-46AE-880B-403B2609EC0B}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {58742414-637E-4AAA-8FC4-A8C7C93FAE49} = {8C65E219-42F9-41FC-ADFB-4938C1DB2E51}
+ {117B883A-1C2C-46AE-880B-403B2609EC0B} = {A82929A9-88AB-4C42-A160-4AC238D4528F}
+ EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9BB015AE-CDF3-415F-94FF-B957B290C771}
EndGlobalSection
diff --git a/samples/Clients.API/Client.cs b/samples/Clients.API/Client.cs
new file mode 100644
index 0000000..6702f8b
--- /dev/null
+++ b/samples/Clients.API/Client.cs
@@ -0,0 +1,10 @@
+namespace Clients.API
+{
+ public class Client
+ {
+ public Guid Id { get; set; }
+ public string Name { get; set; }
+ public int Age { get; set; }
+ public string Email { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/samples/Clients.API/Clients.API.csproj b/samples/Clients.API/Clients.API.csproj
new file mode 100644
index 0000000..34ef7cb
--- /dev/null
+++ b/samples/Clients.API/Clients.API.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/Clients.API/Controllers/ClientsController.cs b/samples/Clients.API/Controllers/ClientsController.cs
new file mode 100644
index 0000000..5445654
--- /dev/null
+++ b/samples/Clients.API/Controllers/ClientsController.cs
@@ -0,0 +1,81 @@
+using Microsoft.AspNetCore.Mvc;
+using NetSwissTools.Web.Mvc;
+using NetSwissTools.Web.Mvc.Results;
+using System;
+using System.Net;
+using System.Runtime.CompilerServices;
+
+namespace Clients.API.Controllers
+{
+ [ApiController]
+ [Route("[controller]")]
+ [ApiVersion("1")]
+ public class ClientsController : SwissControllerApi
+ {
+ public ClientsController(ILogger logger)
+ {
+ }
+
+ [HttpPost]
+ public async Task Post(Client client)
+ {
+ lock (MemoryStore.Clients)
+ {
+ client.Id = Guid.NewGuid();
+
+ MemoryStore.Clients.Add(client);
+ }
+ await Task.Delay(1000);
+ return base.Created(client.Id.ToString(), client);
+ }
+
+ [HttpPost("Pending")]
+ public async Task PostCreate(Client client)
+ {
+ lock (MemoryStore.ClientsPending)
+ {
+ client.Id = Guid.NewGuid();
+
+ MemoryStore.ClientsPending.Add(client);
+ }
+ await Task.Delay(1000);
+ return Created(client.Id.ToString(), client);
+ }
+
+ [HttpPost("Simulate/{id}")]
+ public async Task PostSimulate(Guid id)
+ {
+ await Task.Delay(1000);
+ lock (MemoryStore.ClientsPending)
+ {
+ var client = MemoryStore.ClientsPending.FirstOrDefault(x => x.Id == id);
+
+ if (client == null)
+ return MovedPermanently(id.ToString());
+
+ MemoryStore.Clients.Add(client);
+ MemoryStore.ClientsPending.Remove(client);
+
+ return Created(client.Id.ToString(), client);
+ }
+ }
+
+ [HttpGet]
+ public ActionResult Get()
+ {
+ lock (MemoryStore.Clients)
+ {
+ return RequestOK(MemoryStore.Clients);
+ }
+ }
+
+ [HttpGet("{id}")]
+ public ActionResult GetById(Guid id)
+ {
+ lock (MemoryStore.Clients)
+ {
+ return RequestOK(MemoryStore.Clients.Find(x => x.Id == id));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/Clients.API/MemoryStore.cs b/samples/Clients.API/MemoryStore.cs
new file mode 100644
index 0000000..74f89cb
--- /dev/null
+++ b/samples/Clients.API/MemoryStore.cs
@@ -0,0 +1,8 @@
+namespace Clients.API
+{
+ public static class MemoryStore
+ {
+ public static List Clients = new();
+ public static List ClientsPending = new();
+ }
+}
diff --git a/samples/Clients.API/Program.cs b/samples/Clients.API/Program.cs
new file mode 100644
index 0000000..48863a6
--- /dev/null
+++ b/samples/Clients.API/Program.cs
@@ -0,0 +1,25 @@
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+
+builder.Services.AddControllers();
+// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
+builder.Services.AddEndpointsApiExplorer();
+builder.Services.AddSwaggerGen();
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+ app.UseSwagger();
+ app.UseSwaggerUI();
+}
+
+app.UseHttpsRedirection();
+
+app.UseAuthorization();
+
+app.MapControllers();
+
+app.Run();
diff --git a/samples/Clients.API/Properties/launchSettings.json b/samples/Clients.API/Properties/launchSettings.json
new file mode 100644
index 0000000..a09a15c
--- /dev/null
+++ b/samples/Clients.API/Properties/launchSettings.json
@@ -0,0 +1,31 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:38011",
+ "sslPort": 44392
+ }
+ },
+ "profiles": {
+ "Clients.API": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "applicationUrl": "https://localhost:7038;http://localhost:5031",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "launchUrl": "swagger",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/samples/Clients.API/appsettings.Development.json b/samples/Clients.API/appsettings.Development.json
new file mode 100644
index 0000000..0c208ae
--- /dev/null
+++ b/samples/Clients.API/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/samples/Clients.API/appsettings.json b/samples/Clients.API/appsettings.json
new file mode 100644
index 0000000..10f68b8
--- /dev/null
+++ b/samples/Clients.API/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/NetSwissTools.Web/Enums/EExceptionErrorCodes.cs b/src/NetSwissTools.Web/Enums/EExceptionErrorCodes.cs
new file mode 100644
index 0000000..6b99e1b
--- /dev/null
+++ b/src/NetSwissTools.Web/Enums/EExceptionErrorCodes.cs
@@ -0,0 +1,18 @@
+namespace NetSwissTools.Web.Enums
+{
+ public enum EExceptionErrorCodes
+ {
+ UnhandledException = 900,
+ InvalidRequest = 997,
+ UnauthorizedRequest = 998,
+ InvalidEstablishmentKey = 999,
+ ValidationError = -10000,
+ RegisterNotFound = -15000,
+ RegisterChild = -16000,
+ InsertSQLError = -20001,
+ UpdateSQLError = -20002,
+ DeleteSQLError = -20003,
+ SaveSQLError = -20004,
+ SQLCommandError = -20005
+ }
+}
\ No newline at end of file
diff --git a/src/NetSwissTools.Web/Mvc/Helpers/ResultStatusHelper.cs b/src/NetSwissTools.Web/Mvc/Helpers/ResultStatusHelper.cs
new file mode 100644
index 0000000..64ca504
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Helpers/ResultStatusHelper.cs
@@ -0,0 +1,32 @@
+using System.Net;
+
+namespace NetSwissTools.Web.Mvc.Helpers
+{
+ public static class ResultStatusHelper
+ {
+ public static bool IsClientError(HttpStatusCode code) =>
+ (int)code >= 400 && (int)code <= 499;
+
+ public static bool IsInformational(HttpStatusCode code) =>
+ (int)code >= 100 && (int)code <= 199;
+
+ public static bool IsRedirect(HttpStatusCode code) =>
+ (int)code >= 300 && (int)code <= 399;
+
+ public static bool IsServerError(HttpStatusCode code) =>
+ (int)code >= 500 && (int)code <= 599;
+
+ public static bool IsSuccess(HttpStatusCode code) =>
+ (int)code >= 200 && (int)code <= 299;
+
+ public static bool IsSuccessReponse(HttpStatusCode code)
+ {
+ if (IsInformational(code) || IsSuccess(code) || IsRedirect(code))
+ return true;
+ else if (IsClientError(code) || IsServerError(code))
+ return false;
+
+ return false;
+ }
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Interfaces/IErrorService.cs b/src/NetSwissTools.Web/Mvc/Interfaces/IErrorService.cs
new file mode 100644
index 0000000..a5224f9
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Interfaces/IErrorService.cs
@@ -0,0 +1,9 @@
+using NetSwissTools.Exceptions;
+
+namespace NetSwissTools.Web.Mvc.Interfaces
+{
+ public interface IErrorService
+ {
+ List Errors { get; set; }
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Interfaces/IErrorsController.cs b/src/NetSwissTools.Web/Mvc/Interfaces/IErrorsController.cs
new file mode 100644
index 0000000..b0a2c53
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Interfaces/IErrorsController.cs
@@ -0,0 +1,20 @@
+using NetSwissTools.Exceptions;
+
+namespace NetSwissTools.Web.Mvc.Interfaces
+{
+ public interface IErrorsController
+ {
+ void AddError(string message);
+ void AddError(string field, string exception);
+ void AddError(string field, string exception, string value);
+ void AddError(int code, string field, string exception, string value);
+ void AddError(ModelException exception);
+ void AddError(ModelException[] exceptions);
+ void AddError(Exception exception);
+ void ClearErrors();
+ ModelException[] GetErrors();
+ bool HasAnyErrors();
+ bool IsOperationValid();
+ bool ValidateModelState(TEntity pModel) where TEntity : class;
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Interfaces/IResultStatusController.cs b/src/NetSwissTools.Web/Mvc/Interfaces/IResultStatusController.cs
new file mode 100644
index 0000000..bc78ae8
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Interfaces/IResultStatusController.cs
@@ -0,0 +1,15 @@
+using System.Net;
+
+namespace NetSwissTools.Web.Mvc.Interfaces
+{
+ public interface IResultStatusController
+ {
+ bool IsInformational(HttpStatusCode code);
+ bool IsSuccess(HttpStatusCode code);
+ bool IsRedirect(HttpStatusCode code);
+ bool IsClientError(HttpStatusCode code);
+ bool IsServerError(HttpStatusCode code);
+ bool IsSuccessReponse(HttpStatusCode code);
+
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Interfaces/IUrlInfoController.cs b/src/NetSwissTools.Web/Mvc/Interfaces/IUrlInfoController.cs
new file mode 100644
index 0000000..4c9ba25
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Interfaces/IUrlInfoController.cs
@@ -0,0 +1,13 @@
+namespace NetSwissTools.Web.Mvc.Interfaces
+{
+ public interface IUrlInfoController
+ {
+ IQueryCollection QueryString { get; }
+ int GetPageNumber();
+ int GetPageSize();
+ string GetSort();
+ string GetFilter();
+ string GetQueryColumn();
+ DateTime? GetDateTime(string pDate);
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Results/SwissBadRequestResult.cs b/src/NetSwissTools.Web/Mvc/Results/SwissBadRequestResult.cs
new file mode 100644
index 0000000..7bd3bf8
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Results/SwissBadRequestResult.cs
@@ -0,0 +1,98 @@
+using Microsoft.AspNetCore.Mvc;
+using NetSwissTools.Exceptions;
+using NetSwissTools.Web.Mvc.Helpers;
+using System.Diagnostics;
+using System.Net;
+
+namespace NetSwissTools.Web.Mvc.Results
+{
+ public class SwissBadRequestResult : BadRequestResult
+ {
+ private readonly ModelException[] ErrorList;
+ private readonly int ResponseCode = StatusCodes.Status400BadRequest;
+ private readonly object Data;
+
+ public SwissBadRequestResult(ModelException[] errors)
+ {
+ ErrorList = errors;
+ Data = null;
+ }
+
+ public SwissBadRequestResult(HttpStatusCode statusCode, ModelException[] errors)
+ {
+ ResponseCode = (int)statusCode;
+ ErrorList = errors;
+ Data = null;
+ }
+
+ public SwissBadRequestResult(ModelException errors)
+ {
+ ErrorList = new[] { errors };
+ Data = null;
+ }
+
+ public SwissBadRequestResult(HttpStatusCode statusCode, ModelException errors)
+ {
+ ResponseCode = (int)statusCode;
+ ErrorList = new[] { errors };
+ Data = null;
+ }
+
+ public SwissBadRequestResult(object data, ModelException[] errors)
+ {
+ ErrorList = errors;
+ Data = data;
+ }
+
+ public SwissBadRequestResult(HttpStatusCode statusCode, object data, ModelException[] errors)
+ {
+ ResponseCode = (int)statusCode;
+ ErrorList = errors;
+ Data = data;
+ }
+
+ public SwissBadRequestResult(object data, ModelException errors)
+ {
+ ErrorList = new[] { errors };
+ Data = data;
+ }
+
+ public SwissBadRequestResult(HttpStatusCode statusCode, object data, ModelException errors)
+ {
+ ResponseCode = (int)statusCode;
+ ErrorList = new[] { errors };
+ Data = data;
+ }
+
+ public override void ExecuteResult(ActionContext context)
+ {
+ context.HttpContext.Response.StatusCode = ResponseCode;
+
+ ObjectResult objResult = new(new SwissResult(
+ ResponseCode,
+ Data,
+ ErrorList != null ? ErrorList.ToList() : new List())
+ )
+ {
+ StatusCode = ResponseCode
+ };
+
+ objResult.ExecuteResult(context);
+ }
+
+ public async override Task ExecuteResultAsync(ActionContext context)
+ {
+ context.HttpContext.Response.StatusCode = ResponseCode;
+
+ ObjectResult objResult = new(new SwissResult(
+ ResponseCode,
+ Data,
+ ErrorList != null ? ErrorList.ToList() : new List())
+ )
+ {
+ StatusCode = ResponseCode
+ };
+ await objResult.ExecuteResultAsync(context).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Results/SwissCreatedResult.cs b/src/NetSwissTools.Web/Mvc/Results/SwissCreatedResult.cs
new file mode 100644
index 0000000..d2d9f66
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Results/SwissCreatedResult.cs
@@ -0,0 +1,52 @@
+using Microsoft.AspNetCore.Http.Extensions;
+using Microsoft.AspNetCore.Mvc;
+using NetSwissTools.Exceptions;
+using NetSwissTools.Utils;
+using System.Net;
+
+namespace NetSwissTools.Web.Mvc.Results
+{
+ public class SwissCreatedResult : ObjectResult
+ {
+ public virtual T Entity { get; }
+ public virtual string Id { get; }
+ public virtual string ResourceUrl { get; }
+
+ public SwissCreatedResult(string id, T entity)
+ : base(entity)
+ {
+ Entity = entity;
+ Id = id;
+ ResourceUrl = "";
+ }
+
+ public SwissCreatedResult(string resourceUrl, string id, T entity)
+ : base(entity)
+ {
+ Entity = entity;
+ Id = id;
+ ResourceUrl = resourceUrl;
+ }
+
+ public async override Task ExecuteResultAsync(ActionContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ HttpRequest request = context.HttpContext.Request;
+ HttpResponse response = context.HttpContext.Response;
+ IActionResult result = SwissResultHelpers.GenerateActionResult(Entity);
+ Uri location = SwissResultHelpers.GenerateLocationHeader(request, ResourceUrl, Id);
+
+ response.Headers["Location"] = location.AbsoluteUri;
+ await result.ExecuteResultAsync(context).ConfigureAwait(false);
+ SwissResultHelpers.AddEntityId(response, Id);
+ }
+
+
+
+
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Results/SwissMovedPermanently.cs b/src/NetSwissTools.Web/Mvc/Results/SwissMovedPermanently.cs
new file mode 100644
index 0000000..e33530c
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Results/SwissMovedPermanently.cs
@@ -0,0 +1,86 @@
+using Microsoft.AspNetCore.Mvc;
+using NetSwissTools.Exceptions;
+using NetSwissTools.Web.Enums;
+
+namespace NetSwissTools.Web.Mvc.Results
+{
+ public class SwissMovedPermanently : ObjectResult
+ {
+ private readonly int ResponseCode = StatusCodes.Status301MovedPermanently;
+ private readonly ModelException[] ErrorList;
+ public virtual string Id { get; }
+ public virtual string ResourceUrl { get; }
+
+ public SwissMovedPermanently(string id) :
+ base (null)
+ {
+ Id = id;
+ ResourceUrl = "";
+ ErrorList = new List()
+ {
+ new ModelException
+ {
+ ErrorCode = (int)EExceptionErrorCodes.RegisterNotFound,
+ Field = "",
+ Value = "",
+ Messages = new [] { "Moved Permanently" }
+ }
+ }.ToArray();
+ }
+
+ public SwissMovedPermanently(string id, ModelException errors) :
+ base(null)
+ {
+ Id = id;
+ ResourceUrl = "";
+ ErrorList = new[] { errors };
+ }
+
+ public SwissMovedPermanently(string resourceUrl, string id) :
+ base(null)
+ {
+ Id = id;
+ ResourceUrl = resourceUrl;
+ ErrorList = new List()
+ {
+ new ModelException
+ {
+ ErrorCode = (int)EExceptionErrorCodes.RegisterNotFound,
+ Field = "",
+ Value = "",
+ Messages = new [] { "Moved Permanently" }
+ }
+ }.ToArray();
+ }
+
+ public SwissMovedPermanently(string resourceUrl, string id, ModelException errors) :
+ base(null)
+ {
+ Id = id;
+ ResourceUrl = resourceUrl;
+ ErrorList = new[] { errors };
+ }
+
+ public async override Task ExecuteResultAsync(ActionContext context)
+ {
+ context.HttpContext.Response.StatusCode = ResponseCode;
+
+ ObjectResult objResult = new(new SwissResult(
+ ResponseCode,
+ ErrorList.ToList()))
+ {
+ StatusCode = ResponseCode
+ };
+
+ HttpRequest request = context.HttpContext.Request;
+ HttpResponse response = context.HttpContext.Response;
+ Uri location = SwissResultHelpers.GenerateLocationHeader(request, ResourceUrl, Id);
+
+ var ss = location.AbsoluteUri;
+
+ response.Headers["Location"] = location.AbsoluteUri;
+ await objResult.ExecuteResultAsync(context).ConfigureAwait(false);
+ // SwissResultHelpers.AddEntityId(response, Id);
+ }
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Results/SwissNotFoundResult.cs b/src/NetSwissTools.Web/Mvc/Results/SwissNotFoundResult.cs
new file mode 100644
index 0000000..c70e19f
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Results/SwissNotFoundResult.cs
@@ -0,0 +1,58 @@
+using Microsoft.AspNetCore.Mvc;
+using NetSwissTools.Exceptions;
+using NetSwissTools.Web.Enums;
+
+namespace NetSwissTools.Web.Mvc.Results
+{
+ public class SwissNotFoundResult : NotFoundResult
+ {
+ private readonly int ResponseCode = StatusCodes.Status404NotFound;
+ private readonly ModelException[] ErrorList;
+
+ public SwissNotFoundResult()
+ {
+ ErrorList = new List()
+ {
+ new ModelException
+ {
+ ErrorCode = (int)EExceptionErrorCodes.RegisterNotFound,
+ Field = "",
+ Value = "",
+ Messages = new [] { "Not Found" }
+ }
+ }.ToArray();
+ }
+
+ public SwissNotFoundResult(ModelException errors)
+ {
+ ErrorList = new[] { errors };
+ }
+
+ public override void ExecuteResult(ActionContext context)
+ {
+ context.HttpContext.Response.StatusCode = ResponseCode;
+
+ ObjectResult objResult = new(new SwissResult(
+ ResponseCode,
+ ErrorList.ToList()))
+ {
+ StatusCode = ResponseCode
+ };
+
+ objResult.ExecuteResult(context);
+ }
+
+ public async override Task ExecuteResultAsync(ActionContext context)
+ {
+ context.HttpContext.Response.StatusCode = ResponseCode;
+
+ ObjectResult objResult = new(new SwissResult(
+ ResponseCode,
+ ErrorList.ToList()))
+ {
+ StatusCode = ResponseCode
+ };
+ await objResult.ExecuteResultAsync(context).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Results/SwissOkResult.cs b/src/NetSwissTools.Web/Mvc/Results/SwissOkResult.cs
new file mode 100644
index 0000000..9d454ed
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Results/SwissOkResult.cs
@@ -0,0 +1,54 @@
+using Microsoft.AspNetCore.Mvc;
+using NetSwissTools.Exceptions;
+using System.Net;
+
+namespace NetSwissTools.Web.Mvc.Results
+{
+ public class SwissOkResult: OkResult
+ {
+ private readonly int ResponseCode = StatusCodes.Status200OK;
+ private readonly object Data;
+
+ public SwissOkResult(object data)
+ {
+ Data = data;
+ }
+
+ public SwissOkResult(HttpStatusCode statusCode, object data)
+ {
+ ResponseCode = (int)statusCode;
+ Data = data;
+ }
+
+ public override void ExecuteResult(ActionContext context)
+ {
+ context.HttpContext.Response.StatusCode = ResponseCode;
+
+ ObjectResult objResult = new(new SwissResult(
+ ResponseCode,
+ Data,
+ new List())
+ )
+ {
+ StatusCode = ResponseCode
+ };
+
+ objResult.ExecuteResult(context);
+ }
+
+ public async override Task ExecuteResultAsync(ActionContext context)
+ {
+ context.HttpContext.Response.StatusCode = ResponseCode;
+
+ ObjectResult objResult = new(new SwissResult(
+ ResponseCode,
+ Data,
+ new List())
+ )
+ {
+ StatusCode = ResponseCode
+ };
+ await objResult.ExecuteResultAsync(context).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Results/SwissResult.cs b/src/NetSwissTools.Web/Mvc/Results/SwissResult.cs
new file mode 100644
index 0000000..95dc9f9
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Results/SwissResult.cs
@@ -0,0 +1,35 @@
+using NetSwissTools.Exceptions;
+using NetSwissTools.Web.Mvc.Helpers;
+using System.Net;
+
+namespace NetSwissTools.Web.Mvc.Results
+{
+ public class SwissResult
+ {
+ public SwissResult(
+ int status,
+ List error)
+ {
+ this.status = status;
+ this.success = ResultStatusHelper.IsSuccessReponse((HttpStatusCode)status);
+ this.data = null;
+ this.error = error;
+ }
+
+ public SwissResult(
+ int status, object data,
+ List error)
+ {
+ this.status = status;
+ this.success = ResultStatusHelper.IsSuccessReponse((HttpStatusCode)status);
+ this.data = data;
+ this.error = error;
+ }
+
+ public int status { get; private set; }
+ public bool success { get; private set; }
+ public object data { get; private set; }
+ public List error { get; private set; }
+
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Results/SwissResultHelpers.cs b/src/NetSwissTools.Web/Mvc/Results/SwissResultHelpers.cs
new file mode 100644
index 0000000..2a795f4
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Results/SwissResultHelpers.cs
@@ -0,0 +1,61 @@
+using Microsoft.AspNetCore.Mvc;
+using NetSwissTools.Exceptions;
+using NetSwissTools.Utils;
+using System.Net;
+
+namespace NetSwissTools.Web.Mvc.Results
+{
+ public static class SwissResultHelpers
+ {
+ static string IdHeaderName = "Id";
+
+ internal static void AddEntityId(HttpResponse response, string entityId)
+ {
+ if (response.StatusCode == (int)HttpStatusCode.NoContent ||
+ response.StatusCode == (int)HttpStatusCode.MovedPermanently)
+ {
+ response.Headers.Add(IdHeaderName, entityId);
+ }
+ }
+
+ internal static Uri GenerateLocationHeader(HttpRequest request, string resourceUrl, string id)
+ {
+ if (!resourceUrl.IsEmpty())
+ return new Uri(resourceUrl);
+
+ var controller = request.RouteValues.FirstOrDefault(x => x.Key.Equals("controller", StringComparison.OrdinalIgnoreCase)).Value ??
+ (request.Path.Value ?? "/")[1..];
+
+ var url = $"{request.Scheme}://{request.Host}/{controller}";
+
+ if (!id.IsEmpty())
+ url += $"/{id}";
+
+ return new Uri(url);
+ }
+
+ internal static IActionResult GenerateActionResult(T entity)
+ {
+ if (entity == null)
+ return new StatusCodeResult((int)HttpStatusCode.NoContent);
+
+ return new ObjectResult(new SwissResult(
+ (int)HttpStatusCode.Created,
+ entity,
+ new List()))
+ {
+ StatusCode = (int)HttpStatusCode.Created
+ };
+ }
+
+ public static string GetBaseUrl(this HttpContext context)
+ {
+ var request = context.Request;
+
+ var controller = request.RouteValues.FirstOrDefault(x => x.Key.Equals("controller", StringComparison.OrdinalIgnoreCase)).Value ??
+ (request.Path.Value ?? "/")[1..];
+
+ return $"{request.Scheme}://{request.Host}/{controller}";
+ }
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Results/SwissUnauthorizedResult.cs b/src/NetSwissTools.Web/Mvc/Results/SwissUnauthorizedResult.cs
new file mode 100644
index 0000000..f96a04c
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Results/SwissUnauthorizedResult.cs
@@ -0,0 +1,58 @@
+using Microsoft.AspNetCore.Mvc;
+using NetSwissTools.Exceptions;
+using NetSwissTools.Web.Enums;
+
+namespace NetSwissTools.Web.Mvc.Results
+{
+ public class SwissUnauthorizedResult : UnauthorizedResult
+ {
+ private readonly int ResponseCode = StatusCodes.Status404NotFound;
+ private readonly ModelException[] ErrorList;
+
+ public SwissUnauthorizedResult()
+ {
+ ErrorList = new List()
+ {
+ new ModelException
+ {
+ ErrorCode = (int)EExceptionErrorCodes.RegisterNotFound,
+ Field = "",
+ Value = "",
+ Messages = new [] { "Not Authorized" }
+ }
+ }.ToArray();
+ }
+
+ public SwissUnauthorizedResult(ModelException errors)
+ {
+ ErrorList = new[] { errors };
+ }
+
+ public override void ExecuteResult(ActionContext context)
+ {
+ context.HttpContext.Response.StatusCode = ResponseCode;
+
+ ObjectResult objResult = new(new SwissResult(
+ ResponseCode,
+ ErrorList.ToList()))
+ {
+ StatusCode = ResponseCode
+ };
+
+ objResult.ExecuteResult(context);
+ }
+
+ public async override Task ExecuteResultAsync(ActionContext context)
+ {
+ context.HttpContext.Response.StatusCode = ResponseCode;
+
+ ObjectResult objResult = new(new SwissResult(
+ ResponseCode,
+ ErrorList.ToList()))
+ {
+ StatusCode = ResponseCode
+ };
+ await objResult.ExecuteResultAsync(context).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Results/SwissUnprocessableEntityResult.cs b/src/NetSwissTools.Web/Mvc/Results/SwissUnprocessableEntityResult.cs
new file mode 100644
index 0000000..d074c68
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Results/SwissUnprocessableEntityResult.cs
@@ -0,0 +1,96 @@
+using Microsoft.AspNetCore.Mvc;
+using NetSwissTools.Exceptions;
+using System.Net;
+
+namespace NetSwissTools.Web.Mvc.Results
+{
+ public class SwissUnprocessableEntityResult: UnprocessableEntityResult
+ {
+ private readonly ModelException[] ErrorList;
+ private readonly int ResponseCode = StatusCodes.Status422UnprocessableEntity;
+ private readonly object Data;
+
+ public SwissUnprocessableEntityResult(ModelException[] errors)
+ {
+ ErrorList = errors;
+ Data = null;
+ }
+
+ public SwissUnprocessableEntityResult(HttpStatusCode statusCode, ModelException[] errors)
+ {
+ ResponseCode = (int)statusCode;
+ ErrorList = errors;
+ Data = null;
+ }
+
+ public SwissUnprocessableEntityResult(ModelException errors)
+ {
+ ErrorList = new[] { errors };
+ Data = null;
+ }
+
+ public SwissUnprocessableEntityResult(HttpStatusCode statusCode, ModelException errors)
+ {
+ ResponseCode = (int)statusCode;
+ ErrorList = new[] { errors };
+ Data = null;
+ }
+
+ public SwissUnprocessableEntityResult(object data, ModelException[] errors)
+ {
+ ErrorList = errors;
+ Data = data;
+ }
+
+ public SwissUnprocessableEntityResult(HttpStatusCode statusCode, object data, ModelException[] errors)
+ {
+ ResponseCode = (int)statusCode;
+ ErrorList = errors;
+ Data = data;
+ }
+
+ public SwissUnprocessableEntityResult(object data, ModelException errors)
+ {
+ ErrorList = new[] { errors };
+ Data = data;
+ }
+
+ public SwissUnprocessableEntityResult(HttpStatusCode statusCode, object data, ModelException errors)
+ {
+ ResponseCode = (int)statusCode;
+ ErrorList = new[] { errors };
+ Data = data;
+ }
+
+ public override void ExecuteResult(ActionContext context)
+ {
+ context.HttpContext.Response.StatusCode = ResponseCode;
+
+ ObjectResult objResult = new(new SwissResult(
+ ResponseCode,
+ Data,
+ ErrorList != null ? ErrorList.ToList() : new List())
+ )
+ {
+ StatusCode = ResponseCode
+ };
+
+ objResult.ExecuteResult(context);
+ }
+
+ public async override Task ExecuteResultAsync(ActionContext context)
+ {
+ context.HttpContext.Response.StatusCode = ResponseCode;
+
+ ObjectResult objResult = new(new SwissResult(
+ ResponseCode,
+ Data,
+ ErrorList != null ? ErrorList.ToList() : new List())
+ )
+ {
+ StatusCode = ResponseCode
+ };
+ await objResult.ExecuteResultAsync(context).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/Results/SwissUpdatedResult.cs b/src/NetSwissTools.Web/Mvc/Results/SwissUpdatedResult.cs
new file mode 100644
index 0000000..ba96318
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/Results/SwissUpdatedResult.cs
@@ -0,0 +1,45 @@
+using Microsoft.AspNetCore.Mvc;
+using System.Net;
+
+namespace NetSwissTools.Web.Mvc.Results
+{
+ public class SwissUpdatedResult : ObjectResult
+ {
+ public virtual T Entity { get; }
+ public virtual string Id { get; }
+ public virtual string ResourceUrl { get; }
+
+ public SwissUpdatedResult(string id, T entity)
+ : base(entity)
+ {
+ Entity = entity;
+ Id = id;
+ ResourceUrl = "";
+ }
+
+ public SwissUpdatedResult(string resourceUrl, string id, T entity)
+ : base(entity)
+ {
+ Entity = entity;
+ Id = id;
+ ResourceUrl = resourceUrl;
+ }
+
+ public async override Task ExecuteResultAsync(ActionContext context)
+ {
+ IActionResult result = GenerateActionResult();
+ await result.ExecuteResultAsync(context).ConfigureAwait(false);
+ }
+
+ internal IActionResult GenerateActionResult()
+ {
+ if (Entity == null)
+ return new StatusCodeResult((int)HttpStatusCode.NoContent);
+
+ return new ObjectResult(Entity)
+ {
+ StatusCode = (int)HttpStatusCode.OK
+ };
+ }
+ }
+}
diff --git a/src/NetSwissTools.Web/Mvc/SwissControllerApi.cs b/src/NetSwissTools.Web/Mvc/SwissControllerApi.cs
new file mode 100644
index 0000000..4db5922
--- /dev/null
+++ b/src/NetSwissTools.Web/Mvc/SwissControllerApi.cs
@@ -0,0 +1,347 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.ModelBinding;
+using NetSwissTools.Exceptions;
+using NetSwissTools.Services.Interfaces;
+using NetSwissTools.Utils;
+using NetSwissTools.Web.Enums;
+using NetSwissTools.Web.Mvc.Helpers;
+using NetSwissTools.Web.Mvc.Interfaces;
+using NetSwissTools.Web.Mvc.Results;
+using System.Net;
+using System.Text.RegularExpressions;
+
+namespace NetSwissTools.Web.Mvc
+{
+ [ApiController]
+ public abstract class SwissControllerApi : ControllerBase//, IErrorsController, IUrlInfoController, IResultStatusController
+ {
+ private readonly List Errors = new();
+ protected IErrorBaseService[] Services { get; set; }
+ protected IQueryCollection QueryString { get => HttpContext.Request.Query; }
+
+ protected void AddError(Exception exception) =>
+ Errors.Add(new ModelException
+ {
+ ErrorCode = (int)EExceptionErrorCodes.UnhandledException,
+ Field = "",
+ Messages = new[] { exception.Message },
+ Value = ""
+ });
+
+ protected void AddError(string exception) =>
+ Errors.Add(new ModelException
+ {
+ ErrorCode = (int)EExceptionErrorCodes.UnhandledException,
+ Field = "",
+ Messages = new[] { exception },
+ Value = ""
+ });
+
+ protected void AddError(string field, string exception) =>
+ Errors.Add(new ModelException
+ {
+ ErrorCode = (int)EExceptionErrorCodes.UnhandledException,
+ Field = field,
+ Messages = new[] { exception },
+ Value = ""
+ });
+
+ protected void AddError(string field, string exception, string value) =>
+ Errors.Add(new ModelException
+ {
+ ErrorCode = (int)EExceptionErrorCodes.UnhandledException,
+ Field = field,
+ Messages = new[] { exception },
+ Value = value
+ });
+
+ protected void AddError(int code, string field, string exception, string value) =>
+ Errors.Add(new ModelException
+ {
+ ErrorCode = code,
+ Field = field,
+ Messages = new[] { exception },
+ Value = value
+ });
+
+ protected void AddError(ModelException exception) =>
+ Errors.Add(exception);
+
+ protected void AddError(ModelException[] exceptions) =>
+ Errors.AddRange(exceptions);
+
+ protected void ClearErrors() =>
+ Errors.Clear();
+
+ protected ModelException[] GetErrors()
+ {
+ if (IsOperationValid())
+ return Errors.ToArray();
+
+ if (Services != null)
+ {
+ return Services
+ .SelectMany(r => r.Errors)
+ .Select(r => r)
+ .ToArray();
+ }
+
+ return null;
+ }
+
+ protected bool HasAnyErrors()
+ {
+ if (!IsOperationValid())
+ return true;
+
+ if (Services != null)
+ return Services.Where(r => r.Errors.Any()).Any();
+
+ return false;
+ }
+
+ protected bool IsOperationValid() =>
+ !Errors.Any();
+
+ protected bool IsClientError(HttpStatusCode code) =>
+ ResultStatusHelper.IsClientError(code);
+
+ protected bool IsInformational(HttpStatusCode code) =>
+ ResultStatusHelper.IsInformational(code);
+
+ protected bool IsRedirect(HttpStatusCode code) =>
+ ResultStatusHelper.IsRedirect(code);
+
+ protected bool IsServerError(HttpStatusCode code) =>
+ ResultStatusHelper.IsServerError(code);
+
+ protected bool IsSuccess(HttpStatusCode code) =>
+ ResultStatusHelper.IsSuccess(code);
+
+ protected bool IsSuccessReponse(HttpStatusCode code) =>
+ ResultStatusHelper.IsSuccessReponse(code);
+
+ protected int GetPageNumber()
+ {
+ int page;
+ try
+ {
+ var value = QueryString["page"];
+ if (!int.TryParse(value, out page))
+ page = 1;
+ }
+ catch (Exception)
+ {
+ page = 1;
+ }
+
+ return page;
+ }
+
+ protected int GetPageSize()
+ {
+ int limit;
+ try
+ {
+ var value = QueryString["limit"];
+ if (!int.TryParse(value, out limit))
+ limit = 10;
+ }
+ catch (Exception)
+ {
+ limit = 10;
+ }
+
+ return limit;
+ }
+
+ protected string GetSort()
+ {
+ string sort;
+
+ try
+ {
+ sort = QueryString["sort"].ToString().ToUpper();
+ }
+ catch (Exception)
+ {
+ sort = "";
+ }
+ return sort;
+ }
+
+ protected string GetFilter()
+ {
+ string filter;
+
+ try
+ {
+ filter = QueryString["filter"].ToString().ToUpper();
+ }
+ catch (Exception)
+ {
+ filter = "";
+ }
+ return filter;
+ }
+
+ protected string GetQueryColumn()
+ {
+ string column;
+
+ try
+ {
+ column = QueryString["column"];
+ }
+ catch (Exception)
+ {
+ column = "";
+ }
+ return column;
+ }
+
+ protected DateTime? GetDateTime(string pDate)
+ {
+ try
+ {
+ string[] date = null;
+ string[] time = new string[]
+ {
+ "00",
+ "00"
+ };
+ string seconds = "00";
+
+ if (pDate.Length >= 8)
+ {
+ date = new[]
+ {
+ pDate.SubStr(0, 2),
+ pDate.SubStr(2, 2),
+ pDate.SubStr(4, 4)
+ };
+ }
+
+ if (date == null)
+ return null;
+
+ if (pDate.Length >= 12)
+ {
+ time = new[]
+ {
+ pDate.SubStr(8, 2),
+ pDate.SubStr(10, 2)
+ };
+ }
+
+ if (pDate.Length >= 14)
+ seconds = pDate.SubStr(12, 2);
+
+
+ return new DateTime(
+ Convert.ToInt32(date[2]),
+ Convert.ToInt32(date[1]),
+ Convert.ToInt32(date[0]),
+ Convert.ToInt32(time[0]),
+ Convert.ToInt32(time[1]),
+ Convert.ToInt32(seconds));
+ }
+ catch (Exception)
+ {
+
+ }
+ return null;
+ }
+
+ protected bool ValidateModelState(TEntity pModel) where TEntity : class
+ {
+ ModelState.Clear();
+ var result = TryValidateModel(pModel);
+
+ foreach (var item in ModelState.ToList())
+ {
+ if (item.Value.Errors.Any())
+ {
+ var modelError = new ModelException
+ {
+ ErrorCode = (int)EExceptionErrorCodes.ValidationError,
+ Field = item.Key,
+ Messages = item.Value.Errors.Select(x => x.ErrorMessage).ToArray(),
+ Value = ""
+ };
+
+ Errors.Add(modelError);
+ }
+ }
+
+ return result;
+ }
+
+ protected virtual SwissCreatedResult Created(string id, T entity) =>
+ new(id, entity);
+
+ protected virtual SwissCreatedResult Created(string resourceUrl, string id, T entity) =>
+ new(resourceUrl, id, entity);
+
+ protected virtual SwissUpdatedResult Updated(string id, T entity) =>
+ new(id, entity);
+
+ protected virtual SwissUpdatedResult Updated(string resourceUrl, string id, T entity) =>
+ new(resourceUrl, id, entity);
+
+ protected virtual SwissOkResult RequestOK(object result) =>
+ new(result);
+
+ protected virtual SwissOkResult RequestOK(object result, HttpStatusCode httpStatusCode) =>
+ new(httpStatusCode, result);
+
+ protected virtual SwissBadRequestResult BadRequest(object data, ModelException[] errors) =>
+ new(data, errors);
+
+ protected virtual SwissBadRequestResult BadRequest(object data, ModelException error) =>
+ new(data, error);
+
+ protected virtual SwissBadRequestResult BadRequest(ModelException error) =>
+ new(error);
+
+ protected virtual SwissBadRequestResult BadRequest(ModelException[] errors) =>
+ new(errors);
+
+ protected virtual SwissBadRequestResult UnprocessableEntity(object data, ModelException[] errors) =>
+ new(data, errors);
+
+ protected virtual SwissBadRequestResult UnprocessableEntity(object data, ModelException error) =>
+ new(data, error);
+
+ protected virtual SwissBadRequestResult UnprocessableEntity(ModelException error) =>
+ new(error);
+
+ protected virtual SwissBadRequestResult UnprocessableEntity(ModelException[] errors) =>
+ new(errors);
+
+ protected virtual SwissNotFoundResult NotFound(ModelException error) =>
+ new(error);
+
+ protected new virtual SwissNotFoundResult NotFound() =>
+ new();
+
+ protected virtual SwissNotFoundResult Unauthorized(ModelException error) =>
+ new(error);
+
+ protected new virtual SwissNotFoundResult Unauthorized() =>
+ new();
+
+ protected virtual SwissMovedPermanently MovedPermanently(string id) =>
+ new(id);
+
+ protected virtual SwissMovedPermanently MovedPermanently(string id, ModelException error) =>
+ new(id, error);
+
+ protected virtual SwissMovedPermanently MovedPermanently(string resourceUrl, string id) =>
+ new(resourceUrl, id);
+
+ protected virtual SwissMovedPermanently MovedPermanently(string resourceUrl, string id, ModelException error) =>
+ new(resourceUrl, id, error);
+
+ }
+}
diff --git a/src/NetSwissTools.Web/NetSwissTools.Web.csproj b/src/NetSwissTools.Web/NetSwissTools.Web.csproj
new file mode 100644
index 0000000..6b8b196
--- /dev/null
+++ b/src/NetSwissTools.Web/NetSwissTools.Web.csproj
@@ -0,0 +1,51 @@
+
+
+
+ net6.0
+ disable
+ enable
+ pt-BR
+ NetSwissTools.Web
+ Jonathan Vale
+ KennyMack
+ A collection of classes and tools to improve the web development with .NET
+ NetSwissToolsIcon.png
+ https://github.com/KennyMack/NetSwissTools.Web
+ git
+ False
+ Swiss;Tools;SwissArmy;Common;Implementations;Validation;Exception;Task;Empty;Net Tools;Web;Controller;Action
+ README.md
+ MIT
+ true
+ False
+ Library
+
+
+
+ 1701;1702;1701;1702;1307
+
+
+
+ 1701;1702;1701;1702;1307
+
+
+
+
+ True
+ \
+
+
+ True
+ \
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/NetSwissTools.Web/Properties/launchSettings.json b/src/NetSwissTools.Web/Properties/launchSettings.json
new file mode 100644
index 0000000..79747f7
--- /dev/null
+++ b/src/NetSwissTools.Web/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:57932/",
+ "sslPort": 44324
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "NetSwissTools.Web": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "https://localhost:5001;http://localhost:5000"
+ }
+ }
+}
\ No newline at end of file