Cannot start windows service (.Net Core worker service) due to extra extension methods on IHostBuilder - windows-services

Goal:
I'm trying to run a .Net Core 3.1 Worker service as a windows service.
Setup:
I've used the Worker service default template via Visual Studio.
To add windows service functionality to this, I installed the Microsoft.Extensions.Hosting.WindowsServices nuget and thereafter added .UseWindowsService() as follows:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
})
;
Thereafter, the service can be successfully started via:
sc create <WorkerSvcName> binPath=<C:/local/path/to/exe>
sc start <WorkerSvcName>
Problem:
However, I need to use further extension methods on IHostBuilder, like for example ..UseSerilog(). When I do so, in addition to the above setup, I always get:
[SC] StartService FAILED 1053:
The service did not respond to the start or control request in a timely fashion.
What I've tried:
This persists for all the following configurations:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
X
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
})
X
.UseWindowsService()
X
as well as:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
X
.UseWindowsService()
X
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
})
X
;
where X is a custom extension method on IHostBuilder:
public static IHostBuilder UseSerilog(this IHostBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.UseSerilog((context, services, configuration) =>
{
//do stuff
configuration
.ReadFrom.Configuration(config)
.ReadFrom.Services(services)
});
Log.Information("Serilog has been configured");
return builder;
}
The alternative placements above tell me this may not have anything to do with the order of configuration in CreateHostBuilder().
Question: Any ideas on why I cannot use any other extension methods and continue running the windows service?

This turned out to be a glorious waste of time, since I was looking in exactly the wrong place for quite a while. But it did point out a neat way to get logs from a failing windows service.
My Serilog section in appsettings.json looked like:
"Serilog": {
"Using": [
"Serilog.Sinks.Console",
"Serilog.Sinks.File",
"Serilog.Sinks.Async",
"Serilog.Sinks.Elasticsearch",
"Serilog.Sinks.ApplicationInsights",
"Serilog.Sinks.NewRelic.Logs"
],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
.....
},
{
"Name": "Async",
"Args": {
"configure": [
{
"Name": "File",
..........
}
},
{
"Name": "Elasticsearch",
"Args": {
.......
}
},
{
"Name": "ApplicationInsights",
"Args": {
.......
}
},
{
"Name": "NewRelicLogs",
"Args": {
"applicationName": "<val>",
"licenseKey": "<val>" <-----------------THIS LINE WAS MISSING!!!!!!!
}
}
]
There was indeed a log about this- it just was not in the windows service console window or the console opened up via Visual Studio's IIS Express profile.
To seek logs for failing windows services, try this approach:
Publish the app via Visual Studio to a local folder.
Go the aforementioned folder via command prompt and run .exe in order to execute the application
The resulting logs saved the day for me. Not sure why these do not appear on the console when running in either Debug or Release mode.

Related

ASP.NET core Azure AD authorization problem (chrome doesn't save cookies and makes loop requests)

I'm trying to add azure AD to my project and use this tutorial as example.
With localhost all works fine, but after deploying a have such problem as loop redirects from chrome (version 91) Also i get this problem using last version of opera and edge. While doing the same in safari and Firefox i didn't get any problems.
I think it might be a problem with samesite cookies, but i have already tried every one variant (none,lax,unspecified, strict). Also i noticed, that in Firefox in response Cookies i recieve "AspNetCore.Cookies and in Chome i'm not. but in chrome it's only these one
Is anyone can help me with that problem?
My StartUp file
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.HandleSameSiteCookieCompatibility();
});
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
services.AddMicrosoftIdentityWebAppAuthentication(Configuration);
services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.TokenValidationParameters.RoleClaimType = "roles";
});
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
appsettings.json
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "11111111-1111-1111-1111-111111111111",
"ClientId": "11111111-1111-1111-1111-111111111112",
"CallbackPath": "/signin-oidc"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
Here is a fix (it could be not the best, but it works well for me).
MDN spec says: "The warning appears because any cookie that requests SameSite=None but is not marked Secure will be rejected." That was my problem with browsers run over Chromium engine (Chrome/Opera/Edge). The default value was CookieSecurePolicy.SameAsRequest i changed it to CookieSecurePolicy.Always :
services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.CorrelationCookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.Always;
options.NonceCookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.Always;
});
Some screenshot of warning in chrome:
before
after

System.ArgumentNullException: 'Value cannot be null. (Parameter 'connectionString')'

This is the appsetting.json file
{
"Connection Strings": {
"EmployeeDBConnection": "server=(localhost)\\SQLEXPRESS ; database=EmployeeDB; Trusted_Connection =true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"MyKey": "Value of MYKey from appsettings.json"
}
This is the startup.cs file
namespace EmployeeManagement
{
public class Startup
{
private IConfiguration _config;
public Startup(IConfiguration config)
{
_config = config;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IEmployeeRepository, SQLEmployeeRepository>();
services.AddControllersWithViews();
services.AddDbContextPool<AppDbContext>(options => options.UseSqlServer(_config.GetConnectionString("EmployeeDBConnection")));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World");
});
}
}
}
I have checked that "Connection Strings" has s in the end,
Changed the placement of the connection strings in the appsetting.json file
Instead of just writing the name of the connection string in Configuration.GetConnectionString() in Startup.cs, I put the entire ConnectionString there
I am still having this error.
Your key "Connection Strings" contains space. Change to "ConnectionStrings" for the intended behavior.
"Connection Strings" does not match your parameter "connectionStrings". You need to change that in appsettings.cs. It could also need to be "connectionString" instead, I am a bit confused by your wording. Regardless, your program is looking for "connectionString", not "Connection Strings".

ASP.NET Core 2.0 Error starting Kestrel in Kubernetes

Created a new ASP.NET Core 2.0 project and it runs fine locally.
Then after running it in a Docker container locally it also works fine. But when I try to use the Docker image in a Kubernetes pod, it will run for a couple minutes and then give me this:
Unhandled Exception: System.InvalidOperationException: A path base can
only be configured using IApplicationBuilder.UsePathBase().
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.AddressBinder.
<BindAddressAsync>d__7.MoveNext()
Here is my Program.cs:
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
Startup.cs:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true,
ReactHotModuleReplacement = true
});
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
}
}
When this error was happening, we were using the FROM microsoft/aspnetcore-build:1.1 base image as our build and runtime. At the time we were encountering the error, we had simply tried to upgrade to FROM microsoft/aspnetcore-build:2.0. I'm not certain what specifically the issue with this image was, but Kubernetes didn't like it.
At a later date, we switched the dockerfile to multistage; building with FROM microsoft/aspnetcore-build:1.1 and running with FROM microsoft/dotnet:1.1-runtime, and when we upgraded that to the corresponding 2.0 versions, we didn't encounter this error again.

How to Create Windows Service in .netcoreapp1.0 framework?

I'm working on a netcoreapp1.0 application , ( my target framework is netcoreapp1.0), i want to create a windows service from this application, lets say it is running every 5 minutes.
The package to use for creating ws is this one, but this package only works on full .net framework which is not appropriate for me, I want a solution which works for .netcoreapp1.0 only.
Is there any solution for my problem?
here is my project.json file :
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true
},
"frameworks": {
"netcoreapp1.0": {
}
},
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Microsoft.AspNetCore.Hosting": "1.0.0",
"Microsoft.AspNetCore.Hosting.WindowsServices": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0"
}
}
and here is my program.cs:
public class Program
{
public static void Main(string[] args)
{
var exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
var directoryPath = Path.GetDirectoryName(exePath);
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(directoryPath)
.UseStartup<Startup>()
.Build();
if (Debugger.IsAttached || args.Contains("--debug"))
{
host.Run();
}
else
{
host.RunAsService();
}
}
}

Spring Data Rest Neo4j: Template must not be null or empty

I am creating what I believe to be a fairly simple domain model in Spring.
#NodeEntity
class Dependency {
#GraphId
private Long id
String groupId
String artifactId
String version
#Fetch
#RelatedTo(type = "DEPENDS_ON", direction = OUTGOING)
Set<Dependency> dependencies = new HashSet<Dependency>()
}
note* the above is written in groovy.
I have also created a subsequent Repository (all textbook so far!).
#RepositoryRestResource(collectionResourceRel = "dependency", path = "dependency")
interface DependencyRepository extends PagingAndSortingRepository<Dependency, Long> {
List<Dependency> findByArtifactId(#Param("artifactId") String artifactId)
}
And finally the application class....
#EnableNeo4jRepositories(basePackages = "io.byteshifter.depsgraph")
#SpringBootApplication
class Application extends Neo4jConfiguration {
public Application() {
setBasePackage("io.byteshifter.depsgraph")
}
#Bean(destroyMethod = "shutdown")
GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabase("target/dependency.db")
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application, args)
}
}
Now I would expect when I fire the following payload at http://127.0.0.1:8080/dependency that it would create all the objects and relationships..
{
"groupId": "group1",
"artifactId": "artifact1",
"version": "1.0",
"dependencies" : [
{"groupId": "group2", "artifactId": "artifact2", "version": "2.0"},
{"groupId": "group3", "artifactId": "artifact3", "version": "3.0"}
]
}
Instead, I get..
{
"cause": {
"cause": {
"cause": null,
"message": "Template must not be null or empty!"
},
"message": "Template must not be null or empty! (through reference chain: io.byteshifter.depsgraph.domain.Dependency[\"dependencies\"]->java.util.LinkedHashSet[0])"
},
"message": "Could not read JSON: Template must not be null or empty! (through reference chain: io.byteshifter.depsgraph.domain.Dependency[\"dependencies\"]->java.util.LinkedHashSet[0]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Template must not be null or empty! (through reference chain: io.byteshifter.depsgraph.domain.Dependency[\"dependencies\"]->java.util.LinkedHashSet[0])"
}
I have no doubt this is a lack of understanding on my behalf. If anyone could help steer me in the right direction that would be very welcomed.
My REST knowledge has failed me. I should have been using a URI to represent other dependencies. See below:
{
"groupId": "group3",
"artifactId": "artifact3",
"version": "1.0",
"dependencies": ["http://127.0.0.1:8080/dependency/0", "http://127.0.0.1:8080/dependency/1", "http://127.0.0.1:8080/dependency/2"]
}

Resources