How to stop WebApi project from Owin WebApp - asp.net-web-api

I have a WebApi called MyWebApi project that run on port 42000 in debug mode.
I created a console application with Owin to host MyWebApi using the following technique:
static void Main(string[] args)
{
using (WebApp.Start<WebApi.Startup>("http://localhost:9000/"))
{
Console.WriteLine("Server is running...");
Console.WriteLine("Press Enter key to stop it.");
Console.ReadKey();
}
Console.WriteLine("Server is shutting down...");
}
Everything work fine. I can get and post data from both ports 9000 and 42000.
After I stop my console, I still can post and get data from port 42000.
Are there any way to stop the MyWebApi just like we stop debugging directly from WepApi project?
thanks,
Austin

Try disposing your webApp:
using (var _webApp=WebApp.Start<WebApi.Startup>("http://localhost:9000/"))
{
Console.WriteLine("Server is running...");
Console.WriteLine("Press Enter key to stop it.");
Console.ReadKey();
_webApp.Dispose();// Add this
}
Console.WriteLine("Server is shutting down...");

public class Startup
{
private static readonly IUnityContainer _container = UnityHelpers.GetConfiguredContainer();
public static void StartServer()
{
string baseAddress = "http://localhost:8081/";
var startup = _container.Resolve<Startup>();
IDisposable webApplication = WebApp.Start(baseAddress, startup.Configuration);
try
{
Console.WriteLine("Started...");
Console.ReadKey();
}
finally
{
webApplication.Dispose();
}
}
}
SELF HOST WEBAPI WITH OWIN AND UNITY
webApplication.Dispose(); - stop webapi server

Related

self hosted ASP.NET Core Web Api capable of starting and stopping

I'm attempting to convert an old WCF service to an ASP.NET Core Web API, making use of the CoreWCF package. A key feature of this existing service is that it's being self hosted by an other application and is able to gracefully start & stop, without creating memory leaks.
I have been able to figure out how to start and stop a prototype service. However, after performing some stress testing, it does seem like I've left a memory leak somewhere and I'm sadly out of ideas or available documentation at this point. I'm also considering that an ASP.NET Core Web API just isn't supposed to be used like this and I misunderstood this, if so, be sure to let me know. Also my apologies for the truckload of code, but I'm not sure what's relevant or not to the question.
The code for my prototype service looks like this:
Configuring the webhost:
private void CreateWebHostBuilder(){
host = WebHost.CreateDefaultBuilder()
.UseKestrel(options =>
{
options.AllowSynchronousIO = true;
options.ListenLocalhost(Startup.PORT_NR);
options.ConfigureHttpsDefaults(
options => options.ClientCertificateMode = ClientCertificateMode.RequireCertificate
);
})
.ConfigureLogging(logging => { logging.SetMinimumLevel(LogLevel.Warning); })
.UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
.UseShutdownTimeout(TimeSpan.FromSeconds(1))
.UseStartup<Startup>()
.Build();
}
Inside the Startup class:
Configuring the IApplicationBuilder:
public void Configure(IApplicationBuilder app){
app.UseServiceModel(builder =>
{
// Add the Echo Service
builder.AddService<EchoService>()
// Add service web endpoint
.AddServiceWebEndpoint<EchoService, IEchoService>(
WEB_API_PATH,behavior => { behavior.HelpEnabled = true;}
);
});
app.UseMiddleware<SwaggerMiddleware>();
app.UseSwaggerUI();
app.UseAuthentication();
}
Configuring the services:
public void ConfigureServices(IServiceCollection services){
services.AddServiceModelWebServices()
.AddHostedService<EchoService>()
.AddSingleton(new SwaggerOptions())
.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate();
}
The service interface:
[ServiceContract]
[OpenApiBasePath($"/{Startup.WEB_API_PATH}")]
public interface IEchoService : IHostedService {
[OperationContract]
[WebGet(UriTemplate = "/hello")]
[OpenApiOperation(Description = "Method used to receive a friendly \"Hello world\"",
Summary = "Hello world")]
[OpenApiResponse(Description = "OK Response", StatusCode = HttpStatusCode.OK)]
string HelloWorld();
}
The implemented service:
public class EchoService : IEchoService {
public EchoService() { }
public string HelloWorld() {
return "Hello world!";
}
public Task StartAsync(CancellationToken cancellationToken) {
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
Creating and starting the host + services:
public void StartWebService(object obj){
CreateWebHostBuilder();
host.StartAsync();
}
Stopping and disposing the services and host:
public void StopWebService(object obj) {
host.StopAsync().Wait();
host.Dispose();
}
So if anyone has any suggestions or tutorial reference, be sure to let me know, any help is welcome.

IHostedService .NET 6 not starting when deployed

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

retrofit spring boot not responding

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."

RMI very slow is client and server are not in the same machine

i have a strange problem. I developed client-server application with Java RMI, and in the localhost work very fine, also work very well if i put the client and server on two different MacBook Pro, but work very very slowly if i try to put the client and the server on two computer that are not macbook pro. I have this problem only if i try to send a reference of the client to the server with invocation of a remote method.
This is my code
SERVER:
public class Server{
public static void main(String [] args){
try
{
Server_Impl server=new Server_Impl();
Registry reg=LocateRegistry.createRegistry(1099);
reg.bind("Server",server);
if(new Scanner(System.in).nextInt()==-1){
System.exit(0);
}
}
catch (RemoteException e){e.printStackTrace( );}
catch (AlreadyBoundException e) {e.printStackTrace( );}
}
}
CLIENT
public class Client{
public static Interfaccia_Server Server;
public static void main(String [] args){
try{
Registry reg=LocateRegistry.getRegistry("10.0.1.5",1099);
Server = (Interfaccia_Server) reg.lookup("Server");
Client_Impl c= new Client_Impl(Server);
Server.connect_client(c);
c.check_action();
}
catch(Exception e){
}
}
}
All of the code work, but very very slow if client and server are not on the same machine, or on a apple mac computer.
If i remove this line of code from the client all work very well anywhere, but i need the reference of the client in the server
Server.connect_client(c);
I have no idea about, please help me

Autofac with MEF integration

I need help. I create Windows Service with Autofac container.
And I use MEF Integration service for create several alternative components for my service.
For example:
Module 1
[Export(typeof(IClass1))]
public class Class1 : IClass1
{
public void Show()
{
Console.WriteLine("Hallo from Class1");
}
}
Module 2
[Export(typeof(IClass2))]
public class Class2 : IClass2
{
public void Show()
{
Console.WriteLine("Hallo from Class2");
}
}
Basic class for modules integration - example
class Program
{
private static IContainer Container { get; set; }
static void Main(string[] args)
{
// Create your builder.
var builder = new ContainerBuilder();
/** find all modules in selected folder */
var catalog = new DirectoryCatalog(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + #"\modules", "*Module.dll");
/** register finded modules */
builder.RegisterComposablePartCatalog(catalog);
builder.RegisterType<MyClass>().As<IMyClass>().SingleInstance();
Container = builder.Build();
var cls = Container.Resolve<IMyClass>();
cls.Show();
Console.WriteLine("Class ready. Press Enter");
Console.ReadKey(true);
}
}
class MyClass: IMyClass
{
private readonly IClass1 _class1;
private readonly IClass1 _class3;
private readonly IClass2 _class2;
private readonly IClass2 _class4;
public MyClass(IClass1 class1, IClass2 class2)
{
_class1 = class1;
_class2 = class2;
_class3 = class1;
_class4 = class2;
}
public void Show()
{
_class1.Show();
Console.WriteLine("Class1 ready. Press Enter");
Console.ReadKey(true);
_class2.Show();
Console.WriteLine("Class1 ready. Press Enter");
Console.ReadKey(true);
}
}
internal interface IMyClass
{
void Show();
}
In this example all work fine.This principle I use in my service. For test start and debug my service I use Service.Helper from Nuget packages repository.
Everithyng work fine too.
But. If i create install package in Advance installer and install my service in system (Windows 8.1 x64) service do not start.
Logging exception from service write System.ArgumentNullException in system Event log. Exception most likely in this line
builder.RegisterComposablePartCatalog(catalog);
Service do not load any modules from start folder. Access denied from service to his subfolder. Help please. Thanks.
Try Assembly.GetEntryAssembly().Location insted of Assembly.GetExecutingAssembly().Location

Resources