How to host .NET 6 Web API as Windows Service? - asp.net-core

I have .NET 6 Web API and want to host as a windows service on my own virtual server. I read many questions and answers and applied them, but I still get an error when starting the application (error 1053: the service did not respond to the start or control request in a timely fashion) Also I couldn't find a detailed error description when I looked in the event log.
I'm using Microsoft.Extensions.Hosting.WindowsServices package and Program.cs is below
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
ContentRootPath = WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : default
});
builder.Host.UseWindowsService();
var connectionString = builder.Configuration.GetConnectionString("MongoDB");
...
I'm developing on MAC so publishing my codes with the following command
dotnet publish --runtime win7-x64 --self-contained --configuration Release
I'm creating my windows service like this
sc create "MySvc" binPath= "C:\Users\Administrator\Desktop\test\MySvc.exe"
Where am I doing wrong or how can I find the error?

Related

Redis backplane with SignalR and AspNetBoilerPlate

I have implemented SignalR with AspNetBoilerPlate with .Net core 3.1. We have an azure server with multiple instances. So I am trying to implement Redis.
I followed this link and installed Microsoft.AspNetCore.SignalR.StackExchangeRedis package.
Added following code in startups ConfigureServices()
services.AddSignalR().AddStackExchangeRedis("localhost:6379", options => {
options.Configuration.ChannelPrefix = "dhub";
});
I go to cmd and write redis-cli and added following command:
> PSUBSCRIBE d*
> PSUBSCRIBE dhub*
No message gets displayed when I send a message through SendNotificationsAsync() of IRealTimeNotifier of ASPNetBoilerPlate.
But it is not working.

CryptographicException when deploying IdentityServer4 solution with AddDeveloperSigningCredential to IIS

I have a working Auth service built on IdentityServer3 and .NET Framework. I'm in the process of building a new version of it on IdentityServer4 and ASP.NET Core. In this early stage in development, I'm still using AddDeveloperSigningCredential. When I deploy it to my local development box (Windows 10) in a console window, it runs fine. When I deploy it to IIS Express on my local development box, it gets the following error on startup:
UnauthorizedAccessException: Access to the path 'C:\Program Files\IIS Express\tempkey.rsa' is denied.
I don't really care if it runs in IIS Express (since it runs fine in a console window), but I include this information in case it is relevant to my problem.
When I deploy the solution to a remote server running IIS (Windows Server 2008 R2, IIS 7.5) it fails on startup with this error:
Application startup exception:
Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Object was not found
at System.Security.Cryptography.CngKeyLite.GenerateNewExportableKey(String algorithm, Int32 keySize)
at System.Security.Cryptography.RSAImplementation.RSACng.GetDuplicatedKeyHandle()
at System.Security.Cryptography.RSAImplementation.RSACng.ExportKeyBlob(Boolean includePrivateParameters)
at System.Security.Cryptography.RSAImplementation.RSACng.ExportParameters(Boolean includePrivateParameters)
at Microsoft.Extensions.DependencyInjection.IdentityServerBuilderExtensionsCrypto.AddDeveloperSigningCredential(IIdentityServerBuilder builder, Boolean persistKey, String filename)
at Orvis.Authorization.Service.Startup.ConfigureServices(IServiceCollection services) in C:\Workspaces\Orvis\orvis-microservices\orvis-authorization\Orvis.Authorization.Service\Startup.cs:line 20
Will IdentityServer4 and, in particular AddDeveloperSigningCredential, work on Windows Server 2008 R2 and IIS 7.5 or do I need a newer development server? Or, if the age of the O/S is not the problem, what else might be causing this error?
Well I got this working. At some point along the way the symptom changed and I'm not sure why, but I'll recount here what I know.
I originally had the .AddDeveloperSigningCertficate call hard-coded in my startup code - like this:
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetTestUsers());
That produced the WindowsCryptographicException on startup as noted in the original post. Following some updated IdentityServer4 documentation, I changed that to:
var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetTestUsers());
if (Environment.IsDevelopment())
{
builder.AddDeveloperSigningCredential();
}
else
{
throw new Exception("Need to configure key material");
}
Once I made sure my target server had the correct environment variable to define itself as a Development environment, I think that should have produced the same result. But instead it produced the access denied error that I'd seen earlier in my attempts to deploy locally to IIS Express.
Given that error, I was able to grant the IIS ApplicationPoolIdentity identity write access to c:\windows\system32\inetsrv, which is where it was trying to write the tempkey.rsa developer credential file. This article provides a good overview of ApplicationPoolIdentity and details on how to grant permissions to that identity for your app pool. Granting permissions to that system directory required first taking ownership of the directory.
With all of that done, my service is now running successfully with the developer signing credentials in IIS on my development server.

AspNet Core 2.0 Windows Service and unique ASPNETCORE_ENVIRONMENT variable

I have an ASPNET Core 2.0 Windows Service executing on server A. It was created using:
sc create...
Server A has sytem ASPNETCORE_ENVIRONMENT="Staging". The Windows Service uses appsettings.Staging.json for settings.
I want to install a duplicate Windows service for demo purposes, which needs to point to appsettings.demo.json for settings.
How can the ASPNET Core 2.0 demo Windows Service execute with an unique ASPNETCORE_ENVIRONMENT="Demo"?
Thanks.
I had this exact issue and you can actually set the environment through passing in a command line argument. You will need to create your service like so:
sc create MyDemoService binPath= "C:\MyDemoService.exe --environment Demo"
That will pass in an argument that you can then use in your Main function in Program.cs when building your WebHost. Like so:
var builder = new ConfigurationBuilder();
builder.AddCommandLine(args);
var config = builder.Build();
var host = new WebHostBuilder()
.UseConfiguration(config)
...
As I'm accessing the appsettings.{EnvName}.json elsewhere in my application I have needed to register the IHostingEnvironment as singleton and then I can read the environment name for that service only without having to set the ASPNETCORE_ENVIRONMENT.

Using a ReceiveActivity in a Sharepoint Workflow

I've made my first little workflow in sharepoint and I am trying to access it from the outside using a ReceiveActivity. I have created a WCF svc file with
and created a website in IIS with the same application pool as the sharepoint site.
Now I can start the workflow from my doclib, but when I try to reach the ReceiveActivity like below, I get the following error: "the workflow hosting environment does not have a persistence service as required by an operation on the workflow instance".
I think it has something to do with not using the Sharepoint persistence service in my own WCF website, but I'm not sure. Any idea's on this one???
DoMyThingContractClient proxy = new DoMyThingContractClient ();
IContextManager contextManager = proxy.InnerChannel.GetProperty<IContextManager>();
IDictionary<string, string> context = contextManager.GetContext();
context.Add("instanceId", myInstanceId);
contextManager.SetContext(context);
result = proxy.GetMyMethod(tb1.Text, tb2.Text);
Have you created the SQL tables that host the workflows? The ones at C:\Windows\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\en? If you did, you now need to add the required tags to your config (your WCF's folder with the svc file in this case) as explained at msdn.
Edit after comments: try to run a Persistance Service in your code:
SqlWorkflowPersistenceService ps = new SqlWorkflowPersistenceService("Initial Catalog=SqlPersistenceService;Data Source=localhost;Integrated Security=SSPI");
currentWorkflowRuntime.AddService(ps);

WCF / Silverlight Call Back to Server Fails in IIS

Using Silverlight 3, Windows XP, IIS 5.1, I've written a small app which uses the channel method of calling the server rather than the 'add service reference' as per this MSFT article.
The application opens and the call to the server work when running it on the development computer in VS 2008 using the address localhost plus the port number. When I change the address to the computer name, dellnov2006, and publish the application to IIS, the application opens, but the call to the web service does not work.
Watching the call in Web Dev Helper, I see that the app was trying to call the service file, http://dellnov2006/Service1.svc, and is getting a 404 error.
So far, I've:
-In IIS mapped the .svc type to aspnet-isapi.dll
-Run the utility CleanIISScriptMaps
-Run aspnet_regiis.exe -i –enable
Any help would be appreciated - I am running out of ideas on this.
--
Here is the call back to the server, and the contents of the Service1.svc file:
private void Button_Click(object sender, RoutedEventArgs e)
{
// create a custom binding that uses HTTP and binary encoding
var elements = new List<BindingElement>();
elements.Add(new BinaryMessageEncodingBindingElement());
elements.Add(new HttpTransportBindingElement());
var binding = new CustomBinding(elements);
// create a channel factory for the service endpoint configured
// with custom binding
//var cf = new ChannelFactory<IService1>(binding,
// new EndpointAddress("http://localhost:1042/Service1.svc"));
var cf = new ChannelFactory<IService1>(binding,
new EndpointAddress("http://dellnov2006/Service1.svc"));
// save the syncronized context for the ui thread
uiThead = SynchronizationContext.Current;
// open the channel
IService1 channel = cf.CreateChannel();
// invoke the method asychrnoously
channel.BeginGetPerson(4, GetPersonCallback, channel);
}
Here are the contents of the svc file for what they are worth:
<%# ServiceHost Language="C#" Debug="true" Service="SilverlightChannelApp1.Web.Service1" CodeBehind="Service1.svc.cs" %>
Many thanks
Mike Thomas
Could be one of the following:
A problem with the web.config of the service. For example that localhost was part of the address.
That the service cannot find the dll which should be in the bin directory
Try browsing to the service with a web browser
Try adding the port number to the computer name. Whenever I'm testing local sites through a virtual machine that is always a necessity for me.
Change this:
new EndpointAddress("http://dellnov2006/Service1.svc"));
To this:
new EndpointAddress("http://dellnov2006:1042/Service1.svc"));
The solution to this was very simple, but it took both of your answers for me to think of
it.
Browsing to the service as suggested by Shiraz worked, so problem with calling service.
Suggestion to change endpoint address to include port # sounded good, but did not work.
Solution was to change:
new EndpointAddress("http://dellnov2006/Service1.svc"));
to this:
new EndpointAddress("http://dellnov2006/Silverlight/Service1.svc"));
where 'Silverlight' is the alias of the virtual directory. In other words, I open the app on IIS as 'http://dellnov2006/Silverlight/
Many thanks, I cannot believe how simple that was after so much time spent looking. I work alone and if it were not for this forum I'd be in serious trouble.
Mike Thomas