Base solution for your next web application

Activities of "GarethWright"

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?

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?

thank you

Thanks for confirming that @ismcagdas Are there any examples of this setup?

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);
}
  • What is your product version?
  • 9.0.2
  • What is your product type (Angular or MVC)?
  • Angular (Integrated)
  • What is product framework type (.net framework or .net core)?
  • .netCore

I've downloaded the latest 9.2.0...how does one go about updating my project?

.netCore

If issue related with ABP Framework

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 couldn't get it to work. Ended up creating a public facing unauthenticated controller to handle incoming webhooks.

.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&lt;SwaggerEnumParameterFilter&gt;();
                options.SchemaFilter&lt;SwaggerEnumSchemaFilter&gt;();
                options.OperationFilter&lt;SwaggerOperationIdFilter&gt;();
                options.OperationFilter&lt;SwaggerOperationFilter&gt;();
                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&lt;HealthChecksUISettings&gt;(settings =>
                {
                    healthCheckUISection.Bind(settings, c => c.BindNonPublicProperties = true);
                });
                services.AddHealthChecksUI();
            }
        }

        //Configure Abp and Dependency Injection
        return services.AddAbp&lt;inteliProCSWebHostModule&gt;(options =>
        {
            //Configure Log4Net logging
            options.IocManager.IocContainer.AddFacility&lt;LoggingFacility&gt;(
                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&lt;string&gt; { "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&lt;DatabaseCheckHelper&gt;().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&lt;IHangFireNotificationAppService&gt;("Daily CSCS/ ECS Card Check", dd => dd.CheckCSCSECSCardValid(), Cron.Daily(8));
            RecurringJob.AddOrUpdate&lt;IHangFireAppService&gt;("Check access revocation", dd => dd.CheckForAccessRevocation(), "*/5 * * * *");
            RecurringJob.AddOrUpdate&lt;IHangFireAppService&gt;("Monthly Co2Report", mm => mm.MonthlyCo2ReportJob(), Cron.Daily(21));
            RecurringJob.AddOrUpdate&lt;IHangFireAppService&gt;("Weekly Co2Report", ww => ww.WeeklyCo2ReportJob(), Cron.Weekly(DayOfWeek.Friday, 21));
            RecurringJob.AddOrUpdate&lt;IHangFireAppService&gt;("Daily Co2Report", dd => dd.DailyCo2ReportJob(), Cron.Daily(21));
            RecurringJob.AddOrUpdate&lt;IHangFireAppService&gt;("Get Job Request", rs => rs.GetJobRequestResult(), "*/20 * * * *");
            RecurringJob.AddOrUpdate&lt;IHangFireNotificationAppService&gt;
                ("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&lt;AbpCommonHub&gt;("/signalr");
            endpoints.MapHub&lt;ChatHub&gt;("/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&lt;Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions&gt;(options =>
        {
            options.Listen(new System.Net.IPEndPoint(System.Net.IPAddress.Any, 443),
                listenOptions =>
                {
                    var certPassword = _appConfiguration.GetValue&lt;string&gt;("Kestrel:Certificates:Default:Password");
                    var certPath = _appConfiguration.GetValue&lt;string&gt;("Kestrel:Certificates:Default:Path");
                    var cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certPath, certPassword);
                    listenOptions.UseHttps(new HttpsConnectionAdapterOptions()
                    {
                        ServerCertificate = cert
                    });
                });
        });
    }
}

}

I tried the web.config

This doesn't work either

web.config in wwwroot dir

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <staticContent>
      <remove fileExtension=".json" />
      <mimeMap fileExtension=".json" mimeType="application/json" />
	  <mimeMap fileExtension="woff" mimeType="application/font-woff" />
      <mimeMap fileExtension="woff2" mimeType="application/font-woff" /> 
    </staticContent>
    <!-- IIS URL Rewrite for Angular routes -->
    <rewrite>
      <rules>
        <rule name="Angular Routes" enabled="true" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
          </conditions>
          <action type="Rewrite" url="/" />
        </rule>
      </rules>
    </rewrite>
        <defaultDocument>
            <files>
                <clear />
                <add value="index.html" />
            </files>
        </defaultDocument>
  </system.webServer>
</configuration>
Showing 1 to 10 of 17 entries