I have an API which contains a HostedService that is built in VS2022 with .Net 6.
When I run locally the service is called as expected and everything works fine but when deplyed, the service doesn't seem to start.
I have tried many different configurations and even tried using a background service but it all has the same result. Here is my code:
I have an existing app build in VS2019 .Net Core 3.1 that has a HostedService and is working fine. I noticed that when I converted my .Net Core app to .Net 6, the service did not start when I deployed so I decided to just build a little app to try and find what's causing the issue.
Program.cs
using HostedServices.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog((context, loggerConfiguration) => loggerConfiguration
.ReadFrom.Configuration(context.Configuration)
.Enrich.FromLogContext()
.Enrich.WithMachineName());
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddHostedService<MainService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Here is the Hosted Service
namespace HostedServices.Services
{
public class MainService : IHostedService, IDisposable
{
private int executionCount = 0;
private readonly ILogger<MainService> _logger;
private Timer _timer;
private Task _executingTask;
private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource();
public MainService(ILogger<MainService> logger)
{
_logger = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation($"Test Hosted Service Started {DateTime.Now}.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromMinutes(1));
return Task.CompletedTask;
}
private void DoWork(object state)
{
_executingTask = DoWorkAsync(_stoppingCts.Token);
}
private async Task DoWorkAsync(CancellationToken token)
{
_logger.LogInformation(
"Doing work: {0}", DateTime.Now);
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Service is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
}
Everything runs fine locally but when I deploy it, the service doesn't seem to start, no log files are generated and I can't seem to find any errors reported.
Any ideas?
We had the same problem and resolved it by following IIS settings:
Under "Page" Advanced Settings: "Preload Enabled" must be set to "true" (this forces app to run after every app pool recycle and on startup)
Under "App Pool" Advanced settings: "Start mode" must be set to "AlwaysRunning"
"Page" in IIS must have http allowed (since preload enabled works only on http and not via https)
The problem is that while IHostedService start when the site starts when does IIS start the site? By default, it doesn't until a request is made. If your site goes idle for a while IIS will kill the thread as well.
IIS has a feature you can enable called "Application Initialization".
You then need to configure the Application Pool to always start (startMode="AlwaysRunning").
Lastly, you configure the site's application to preload which sends a fake HTTP request to the site on startup (preloadEnabled="true").
The docs for this are here: https://learn.microsoft.com/en-us/iis/get-started/whats-new-in-iis-8/iis-80-application-initialization
Related
I'm currently trying to mount a .NET Core 3.1 MVC application created with dotnet new react. The application works perfectly fine when running it via Visual Studio Code. However, when publishing with dotnet publish -c Release -r win81-x64 and mounting the application in IIS 8.5, the routes for the APIs stop working, sending all requests to the React page.
Currently my configuration in Startup.cs looks like this:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
}
And the code in a test controller I made looks like this:
namespace Application.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase {
private readonly ILogger<TestController> _logger;
public TestController(ILogger<TestController> logger)
{
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<string>> GetTest()
{
return "Test";
}
}
}
I also tried creating a new React project and mounting it, and that does seem to work. However, the Startup.cs file has the exact same configuration, so I can't find anything to modify on my application.
I figured it out. Turns out the first version I uploaded had some issues that prevented routes from working properly, and while I immediately fixed it, the Service Worker that the default .NET project has cached the broken API point as part of the site. Apparently this bypasses having the 'Disable Cache' tick box in developer tools.
I have a server in spring boot, which is running on port 8080.
Now I'm trying to call rest api in my android application using retrofit2.
Here is what I have implemented:
final TextView textView=findViewById(R.id.t1);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:8080/")
.addConverterFactory(GsonConverterFactory.create())
.build();
JsonPlaceHolderApi jsonPlaceHolderApi = retrofit.create(JsonPlaceHolderApi.class);
Call<TC> call = jsonPlaceHolderApi.getPosts();
call.enqueue(new Callback<TC>() {
#Override
public void onResponse(Call<TC> call, Response<TC> response) {
textView.setText(response.toString());
if (!response.isSuccessful()) {
return;
}
TC posts = response.body();
textView.setText(posts.toString());
}
#Override
public void onFailure(Call<TC> call, Throwable t) {
}
});
I can surly say that, it's not working as my api is not even being called. As the hello world screen remains as it is.
And in my server I have logger, which doesn't log anything, so it doesn't get called.
Here is my CORS:
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("*")
.allowedOrigins("*");
}
};
}
The problem is with the word localhost.
As for debugging purpose I'm connecting the android device with my PC so my android device can't connect to localhost as it is just an alias of my IP address.
To resolve this, I opened up CMD and wrote ipconfig, by this command I can see all details related to IP.
And here it shows my IPv4 address as $.$.$.$. I just replaced the localhost with that $.$.$.$.
Now everything is working fine.
Any ideas how to make it work with Asp.net core. I just test it wih my local machine ip address and work perfectly.
Unfortunately, not the case with Asp.net core.
aAndroid + Retrofit + Asp.net API "java.security.cert.CertPathValidatorException: Trust anchor for certification path not found."
I'm trying to use the ShowTypingMiddleware, a custom middleware already given by BotFramework (see here: https://github.com/microsoft/botbuilder-dotnet/blob/master/libraries/Microsoft.Bot.Builder/ShowTypingMiddleware.cs) to send an typing message to my user while the bot is processing his request. I'm using the BotFramework V4.
It all works locally, but not when I publish it on Azure's WebChat.
I've followed the example in Microsoft's samples, where they create an adapter that adds the desired middleware to the bot pipeline (the sample I've used is here: https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/17.multilingual-bot. The custom adapter I'm referring to is AdapterWithErrorHandler.cs, and it adds the TranslationMiddleware to the pipeline).
Running locally, everything works as planned. The problem is: when I'm publishing it to Azure, the webchat stop working. It throws the following exception:
7/21/2019 1:07:33 PM There was an error sending this message to your bot: HTTP status code Unauthorized
7/21/2019 1:07:33 PM There was an error sending this message to your bot:
HTTP status code Unauthorized
In my StartUp.cs's ConfigureServices, I've injected my custom adapter and my middleware:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// Create the credential provider to be used with the Bot Framework Adapter.
services.AddSingleton<ICredentialProvider, ConfigurationCredentialProvider>();
// Create the Bot Framework Adapter.
services.AddSingleton<IBotFrameworkHttpAdapter, AdapterWithTypingAndErrorHandler>();
// Create the bot as a transient. In this case the ASP Controller is expecting an IBot.
services.AddTransient<IBot, MyBot>();
services.AddSingleton<ShowTypingMiddleware>();
}
My AdapterWithTypingAndErrorHandler is as follows:
public class AdapterWithTypingAndErrorHandler : BotFrameworkHttpAdapter
{
public AdapterWithTypingAndErrorHandler(
IConfiguration configuration,
ILogger<BotFrameworkHttpAdapter> logger,
ShowTypingMiddleware showTypingMiddleware) : base(logger: logger)
{
if (showTypingMiddleware == null)
throw new NullReferenceException($"Could not load '{nameof(showTypingMiddleware)}' in custom adapter.");
AddAdapterToPipeline(showTypingMiddleware);
OnTurnError = async (turnContext, exception) =>
{
logger.LogError($"Exception caught : {exception.Message}");
await turnContext.SendActivityAsync("Sorry, something went wrong :/");
};
}
private void AddAdapterToPipeline(ShowTypingMiddleware showTypingMiddleware)
=> Use(showTypingMiddleware);
}
And I'm using it in my controller:
public class BotController : ControllerBase
{
private readonly IBotFrameworkHttpAdapter Adapter;
private readonly IBot Bot;
public BotController(IBotFrameworkHttpAdapter adapter, IBot bot)
{
Adapter = adapter;
Bot = bot;
}
[HttpPost]
public async Task PostAsync()
{
await Adapter.ProcessAsync(Request, Response, Bot);
}
}
As I said, everything works fine, locally, but when I publish it, the WebChat throws the Unauthorized exception. If I use the default Adapter (the BotFrameworkHttpAdapter.cs one), instead of my customized, it all works fine too.
What should I do?
I am using windows authentication for an intranet asp.net core web application running behind IIS.
I'd like to log the event when a user accesses the application and a session is created.
Some of the authentication services provide a way to add an event-handler for events such as "OnSigningIn", "OnSignedIn", "OnTokenvalidated", etc., to options when configuring those services.
Is there a way to do something like that when using Windows Authentication through services.AddAuthentication(IISDefaults.AuthenticationScheme) or services.AddSession(), or some other way?
Windows authentication happens at the IIS level, before ASP.NET Core even sees the request, which is why there aren't any events for it you can handle. Sessions don't have any events either.
You could inject a simple middleware once you inject the logger into Startup,
public class Startup
{
private readonly ILogger<Startup> _logger;
public IConfiguration Configuration { get; }
public Startup(ILogger<Startup> logger, IConfiguration configuration)
{
_logger = logger;
Configuration = configuration;
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// The typical startup crud, then
app.Use(async (context, next) =>
{
int logged = context.Session.GetInt32("Logged") ?? 0;
if (visits == 0 && CheckIfThisRequestNeedsToUseSession(context))
{
// New session
// Log with _logger, then mark so it doesn't repeat
context.Session.SetInt32("IKnowYou", 1);
// ...
}
await next();
});
// …
}
}
I have been struggling with this for several days (three actually). I have AAD B2C working on a web app and an api. I cannot get it running on my Xamarin mobile project. I am using the UWP project to test my configuration since it has the easiest app to troubleshoot on a Windows 10 machine. I am using Visual Studio 2015 Pro.
I am using the Microsoft.Identity.Client 1.1.0-preview.
I used this as my starting point for my attempt to implement.
https://github.com/Azure-Samples/active-directory-b2c-xamarin-native
Right now the project will compile and launch. When I click on Sign in, I get a WebView, but it doesn't look exactly right....
[First Image in Screenshots]
Here are my variables...
public class Constants
{
public static string ApplicationID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
public static string[] Scopes = {""};
public static string SignUpSignInPolicy = "B2C_1_Standard_SignUpSignIn";
public static string ResetPasswordPolicy = "B2C_1_Standard_PasswordReset";
public static string EditProfilePolicy = "B2C_1_Standard_EditProfile";
public static string Authority = "https://login.microsoftonline.com/[MyTennantName].onmicrosoft.com/B2C_1_Standard_SignUpSignIn";
public static string AuthorityEditProfile = "https://login.microsoftonline.com/[MyTennantName].onmicrosoft.com/B2C_1_Standard_EditProfile";
public static string ApiEndpoint = "https://[MyTennantName].onmicrosoft.com/apiservices";
public static UIParent UiParent = null;
}
My Login method is....
async void OnSignInSignOut(object sender, EventArgs e)
{
try
{
if (btnSignInSignOut.Text == "Sign in")
{
AuthenticationResult ar = await App.PCA.AcquireTokenAsync(Constants.Scopes, GetUserByPolicy(App.PCA.Users, Constants.SignUpSignInPolicy), Constants.UiParent);
UpdateUserInfo(ar);
UpdateSignInState(true);
}
else
{
foreach (var user in App.PCA.Users)
{
App.PCA.Remove(user);
}
UpdateSignInState(false);
}
}
catch (Exception ex)
{
// Checking the exception message
// should ONLY be done for B2C
// reset and not any other error.
if (ex.Message.Contains("AADB2C90118"))
OnPasswordReset();
// Alert if any exception excludig user cancelling sign-in dialog
else if (((ex as MsalException)?.ErrorCode != "authentication_canceled"))
await DisplayAlert($"Exception:", ex.ToString(), "Dismiss");
}
}
However before I can even enter my password I get the following....
[Second image in Screenshots]
My application definition looks like this...[Third image in screenshots]
I don't think it is recognizing my tenant and trying to log me in with a Microsoft account. I have double checked my Tenant name and Application ID.
Screenshots
I don't have enough reputation to post more than one link and one picture.
Also, the Azure AD B2C api application works for a web app. I have created a web app that can authenticate and works with the API.
It looks like while modifying the authorization value in the Sample you removed the /tfp/ part.
You should update your values as follows:
public static string Authority = "https://login.microsoftonline.com/tfp/[MyTennantName].onmicrosoft.com/B2C_1_Standard_SignUpSignIn";
public static string AuthorityEditProfile = "https://login.microsoftonline.com/tfp/[MyTennantName].onmicrosoft.com/B2C_1_Standard_EditProfile";