Console app gets a token successfully but returns 401 Unauthorised when connecting to the api endpoint from a remote ip. Works fine if connecting via localhost. I think this may be something to do with IdentityServer being configured to use .AddDeveloperSigninCredentials but I have no idea how I would configure this to work in a multi tenant environment where the host is at https://api.{tenant_name}.domain.com
.net core Angular Single Project 9.0.1
This works fine locally but when publishing to IIS any deep link i.e /account/login returns a 404.
It should all as the provided
app.Use(async (context, next) => { await next(); if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value)) { context.Request.Path = "/index.html"; await next();
} });
should handle those 404s
namespace PROJECT.Web.Startup { public class Startup { private const string DefaultCorsPolicyName = "localhost";
private readonly IConfigurationRoot _appConfiguration;
private readonly IWebHostEnvironment _hostingEnvironment;
public Startup(IWebHostEnvironment env)
{
_hostingEnvironment = env;
_appConfiguration = env.GetAppConfiguration();
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
//MVC
services.AddControllersWithViews(options =>
{
options.Filters.Add(new AbpAutoValidateAntiforgeryTokenAttribute());
}).AddNewtonsoftJson();
services.AddSignalR();
//Configure CORS for angular2 UI
services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
{
//App:CorsOrigins in appsettings.json can contain more than one address with splitted by comma.
builder
.WithOrigins(
// App:CorsOrigins in appsettings.json can contain more than one address separated by comma.
_appConfiguration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.RemovePostFix("/"))
.ToArray()
)
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
if (bool.Parse(_appConfiguration["KestrelServer:IsEnabled"]))
{
ConfigureKestrel(services);
}
IdentityRegistrar.Register(services);
AuthConfigurer.Configure(services, _appConfiguration);
//Identity server
if (bool.Parse(_appConfiguration["IdentityServer:IsEnabled"]))
{
IdentityServerRegistrar.Register(services, _appConfiguration, options =>
options.UserInteraction = new UserInteractionOptions()
{
LoginUrl = "/UI/Login",
LogoutUrl = "/UI/LogOut",
ErrorUrl = "/Error"
});
}
if (WebConsts.SwaggerUiEnabled)
{
//Swagger - Enable this line and the related lines in Configure method to enable swagger UI
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo() { Title = "inteliProCS API", Version = "v1" });
options.DocInclusionPredicate((docName, description) => true);
options.ParameterFilter<SwaggerEnumParameterFilter>();
options.SchemaFilter<SwaggerEnumSchemaFilter>();
options.OperationFilter<SwaggerOperationIdFilter>();
options.OperationFilter<SwaggerOperationFilter>();
options.CustomDefaultSchemaIdSelector();
}).AddSwaggerGenNewtonsoftSupport();
}
//Recaptcha
services.AddreCAPTCHAV3(x =>
{
x.SiteKey = _appConfiguration["Recaptcha:SiteKey"];
x.SiteSecret = _appConfiguration["Recaptcha:SecretKey"];
});
if (WebConsts.HangfireDashboardEnabled)
{
//Hangfire(Enable to use Hangfire instead of default job manager)
services.AddHangfire(config =>
{
config.UseSqlServerStorage(_appConfiguration.GetConnectionString("Default"));
});
}
if (WebConsts.GraphQL.Enabled)
{
services.AddAndConfigureGraphQL();
}
if (bool.Parse(_appConfiguration["HealthChecks:HealthChecksEnabled"]))
{
services.AddAbpZeroHealthCheck();
var healthCheckUISection = _appConfiguration.GetSection("HealthChecks")?.GetSection("HealthChecksUI");
if (bool.Parse(healthCheckUISection["HealthChecksUIEnabled"]))
{
services.Configure<HealthChecksUISettings>(settings =>
{
healthCheckUISection.Bind(settings, c => c.BindNonPublicProperties = true);
});
services.AddHealthChecksUI();
}
}
//Configure Abp and Dependency Injection
return services.AddAbp<inteliProCSWebHostModule>(options =>
{
//Configure Log4Net logging
options.IocManager.IocContainer.AddFacility<LoggingFacility>(
f => f.UseAbpLog4Net().WithConfig(_hostingEnvironment.IsDevelopment()
? "log4net.config"
: "log4net.Production.config")
);
options.PlugInSources.AddFolder(Path.Combine(_hostingEnvironment.WebRootPath, "Plugins"), SearchOption.AllDirectories);
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
//Initializes ABP framework.
app.UseAbp(options =>
{
options.UseAbpRequestLocalization = false; //used below: UseAbpRequestLocalization
});
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseStatusCodePagesWithRedirects("~/Error?statusCode={0}");
app.UseExceptionHandler("/Error");
}
app.Use(async (context, next) => { await next(); if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value)) { context.Request.Path = "/index.html"; await next();
} });
// app.UseDefaultFiles(new DefaultFilesOptions { DefaultFileNames = new List<string> { "index.html" }});
app.UseStaticFiles();
app.UseRouting();
app.UseCors(DefaultCorsPolicyName); //Enable CORS!
app.UseAuthentication();
app.UseJwtTokenMiddleware();
if (bool.Parse(_appConfiguration["IdentityServer:IsEnabled"]))
{
app.UseJwtTokenMiddleware("IdentityBearer");
app.UseIdentityServer();
}
app.UseAuthorization();
using (var scope = app.ApplicationServices.CreateScope())
{
if (scope.ServiceProvider.GetService<DatabaseCheckHelper>().Exist(_appConfiguration["ConnectionStrings:Default"]))
{
app.UseAbpRequestLocalization();
}
}
if (WebConsts.HangfireDashboardEnabled)
{
//Hangfire dashboard &server(Enable to use Hangfire instead of default job manager)
app.UseHangfireDashboard(WebConsts.HangfireDashboardEndPoint, new DashboardOptions
{
// Authorization = new[] { new AbpHangfireAuthorizationFilter(AppPermissions.Pages_Administration_HangfireDashboard) }
});
var options = new BackgroundJobServerOptions
{
Queues = new[] { "WindowsService", "default" }
};
app.UseHangfireServer(options);
RecurringJob.AddOrUpdate<IHangFireNotificationAppService>("Daily CSCS/ ECS Card Check", dd => dd.CheckCSCSECSCardValid(), Cron.Daily(8));
RecurringJob.AddOrUpdate<IHangFireAppService>("Check access revocation", dd => dd.CheckForAccessRevocation(), "*/5 * * * *");
RecurringJob.AddOrUpdate<IHangFireAppService>("Monthly Co2Report", mm => mm.MonthlyCo2ReportJob(), Cron.Daily(21));
RecurringJob.AddOrUpdate<IHangFireAppService>("Weekly Co2Report", ww => ww.WeeklyCo2ReportJob(), Cron.Weekly(DayOfWeek.Friday, 21));
RecurringJob.AddOrUpdate<IHangFireAppService>("Daily Co2Report", dd => dd.DailyCo2ReportJob(), Cron.Daily(21));
RecurringJob.AddOrUpdate<IHangFireAppService>("Get Job Request", rs => rs.GetJobRequestResult(), "*/20 * * * *");
RecurringJob.AddOrUpdate<IHangFireNotificationAppService>
("Send Warning Notification", r => r.SendNotificationForHangFire(),
"*/10 * * * *");
}
if (bool.Parse(_appConfiguration["Payment:Stripe:IsActive"]))
{
StripeConfiguration.ApiKey = _appConfiguration["Payment:Stripe:SecretKey"];
}
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<AbpCommonHub>("/signalr");
endpoints.MapHub<ChatHub>("/signalr-chat");
endpoints.MapControllerRoute("defaultWithArea", "{area}/{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
if (bool.Parse(_appConfiguration["HealthChecks:HealthChecksEnabled"]))
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions()
{
Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
}
});
if (bool.Parse(_appConfiguration["HealthChecks:HealthChecksEnabled"]))
{
if (bool.Parse(_appConfiguration["HealthChecks:HealthChecksUI:HealthChecksUIEnabled"]))
{
app.UseHealthChecksUI();
}
}
if (WebConsts.SwaggerUiEnabled)
{
// Enable middleware to serve generated Swagger as a JSON endpoint
app.UseSwagger();
// Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint(_appConfiguration["App:SwaggerEndPoint"], "API V1");
options.IndexStream = () => Assembly.GetExecutingAssembly()
.GetManifestResourceStream("inteliProCS.Web.wwwroot.swagger.ui.index.html");
options.InjectBaseUrl(_appConfiguration["App:ServerRootAddress"]);
}); //URL: /swagger
}
}
private void ConfigureKestrel(IServiceCollection services)
{
services.Configure<Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions>(options =>
{
options.Listen(new System.Net.IPEndPoint(System.Net.IPAddress.Any, 443),
listenOptions =>
{
var certPassword = _appConfiguration.GetValue<string>("Kestrel:Certificates:Default:Password");
var certPath = _appConfiguration.GetValue<string>("Kestrel:Certificates:Default:Path");
var cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certPath, certPassword);
listenOptions.UseHttps(new HttpsConnectionAdapterOptions()
{
ServerCertificate = cert
});
});
});
}
}
}
This doesn't work either
.netCore
Latest
I'm trying to integrate with GoCardless to add Direct Debit Payments for memberships. They sent a webhook when payments are complete and I need to add the following to a controller to process that event.
[HttpPost]
[AllowAnonymous]
public async Task<StatusCodeResult> WebhookEvent()
{
var requestBody = HttpContext.Request.Body;
requestBody.Seek(0, System.IO.SeekOrigin.Begin);
var requestJson = new StreamReader(requestBody).ReadToEnd();
// We recommend storing your webhook endpoint secret in an environment variable
// for security
var secret = AppConsts.GoCardlesssSandBoxToken;
var signature = Request.Headers["Webhook-Signature"];
try
{
// Webhooks can contain many events. In a real implementation, you should handle
// the processing of each event asychronously to avoid timing out here.
// You could check whether you've processed the event before (by recording the event
// ID when you process it) and retrieve the associated resource to ensure that you have
// the most up-to-date information about it.
foreach (GoCardless.Resources.Event whevent in WebhookParser.Parse(requestJson, secret, signature))
{
// To keep this example simple, we're only handling Mandate events
if (whevent.ResourceType == GoCardless.Resources.EventResourceType.Mandates)
{
switch (whevent.Action)
{
case "created":
Console.WriteLine($"Mandate {whevent.Links.Mandate} has been created, yay!");
break;
case "cancelled":
Console.WriteLine($"Oh no, mandate {whevent.Links.Mandate} was cancelled!");
break;
default:
Console.WriteLine($"{whevent.Links.Mandate} has been {whevent.Action}");
break;
}
}
else
{
Console.WriteLine($"No method to handle {whevent.ResourceType} events yet");
}
}
return new StatusCodeResult((int)HttpStatusCode.OK);
}
catch (InvalidSignatureException e)
{
return new BadRequestResult();
}
}
I've added to the MVC controller but I keep getting 302 redirected to login page. I can't figure out why as I've added the [AllowAnonymous] Attribute. I've also tried the [abpAllowAnonymous] attribute with no success.
I've downloaded the latest 9.2.0...how does one go about updating my project?
Language is set to English UK and date set to 2020-07-13 in datepicker.
Date saved is 2020-07-12 because it is not accounting for daylight savings time.
More worrying is that on updating the entity all the date fields are changed to the previous day.
I think this is because if the language is 'en' it just returns the promise without checking any locale specifics like DST. <br>
static registerNgxBootstrapDatePickerLocales(): Promise {
if (abp.localization.currentLanguage.name === 'en') {
return Promise.resolve(true);
}
I have a requirement whereby the aspnet zero site is running on a local server in single tenent mode and the same application is also available in multitenant online.
i would like to have the tenent site online sync changes from the local install and webhooks seem to be a viable option for doing so.
Has anyone used webhooks in this way?
I downloaded with the merged project, but in hindsight could do with them seperate? The downloader does not let me do this, can you facilitate?