I have an ASP WebAPI application that works great.
Without changing anything massive within the application, I'm trying to create a new console project with self-hosting components to host the application (mainly for running it fast when debugging other components of my solution without opening and compiling from Visual Studio).
I saw plenty of solutions for using Microsoft.AspNet.SignalR.SelfHost package,
For example: Working With OWIN Hosting and Self Hosting in ASP.Net.
All the solutions I saw, use the following structure:
string baseAddress = "http://localhost:9000/";
// Start OWIN host
using (WebApp.Start<Startup>(url: baseAddress))
{
// Create HttpCient and make a request to api/values
HttpClient client = new HttpClient();
var response = client.GetAsync(baseAddress + "api/values").Result;
Console.WriteLine(response);
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
Console.ReadLine();
This is a bit problematic for me, since using (WebApp.Start<Startup>(url: baseAddress)) is calling the Configuration method in Startup class.
public class Startup
{
// This code configures Web API. The Startup class is specified as a type
// parameter in the WebApp.Start method.
public void Configuration(IAppBuilder appBuilder)
{ ... }
}
My solution has plenty of code inside the Application_Start() (inside the Global.aspx.cs file) that I'm trying to reach when starting the console self-host application. So far without any success.
Is this a lost battle and I should move as much as I can from Application_Start method to Configuration method? Or is there any way I call call the Application_Start somehow, prior to running the Configuration method?
I tried creating an instance of the ASP application and call the Application_Start, but that didn't work.
Thanks!
Guy
Related
I have a service with constructor like this
public FileManager(IServiceProvider services, IServer server)
{
_server = server;
}
Whenever I call the service, I get the error No service for type 'Microsoft.Extensions.Hosting.IHostEnvironment' has been registered.
When I remove the IServer dependency away, the program works fine. I have researched about this alot read this post saw this also on github and so many others but yet the problem seems not to be resolved.
The solution was working perfectly in net5 before I decided to migrate to net6.0
Edited
Must add service to app container in you program.cs before var app=builder.build(); or in ConfigureServices(), by example add singleton builder.Services.AddSingleton<IFileManager,FileManager>();
See you Configure and ConfigureServices methods(in .Net5 project) and move add services to buider.Services.Add... and app.Use.. respectively.
well, I am now learning aspnet core , I can't understand when does the application start its server(like IIS or KestrelServer),and how the server listen the httprequest and forwards the request to the application. can anybody help me? thanks
Well, let's start from beginning (As I couldn't figure out your knowledge about C#)
Every C# application must contain a single Main method specifying where program execution is to begin, so there it is, by default the templates have a Class Program where you can set the type of WebServer that you'll use, and tell the server to start listening for HTTP requests, something like:
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.AddCommandLine(args)
.Build();
var host = new WebHostBuilder()
.UseKestrel()
.UseConfiguration(config)
.UseStartup<Startup>()
.Build();
host.Run();
}
In AspNetCore and even in AspNet (MVC or WebApi) you can (and should) use OWIN (aka Katana or vNext, that are Microsoft's OWIN implementations for AspNet and AspNetCore respectively).
OWIN represents a Interface (just a specification), that tell how WebServers should comunicate with WebApplications. Normally it handle the Http Requests to a pipeline that you can plug Middlewares, like Authentication/Authorization, Log, Error Handlings and so on, and in the end of the pipeline you should plug your Web Application.
In AspNetCore you set your Middleware Pipeline by using UseStartup<MyStartupClass> in your Host configuration see Main method above and simple as that your Pipeline will handle every HttpRequest.
When building a MVC applications in AspNetCore (.UseMvc()) you are setting a middleware that tells your application to look for classes that inherit from Microsoft.AspNetCore.Mvc.Controller to look for RESTful entry points (HTTP GET, POST...)
This is just a simple overview, and you can learn a lot more looking in the documentation of this technologies. Just search for tags like Katana, vNext, OWIN, OWIN Middleware, OWIN Pipeline...
ASP.NET Core application anatomy is discussed here at this asp.net core introduction.
Some important text that answers your question is as follows from the tutorial:
An ASP.NET Core app is simply a console app that creates a web server in its Main method. Main uses WebHostBuilder, which follows the builder pattern, to create a web application host. The builder has methods that define the web server (for example UseKestrel) and the startup class (UseStartup). In the example above, the Kestrel web server is used, but other web servers can be specified. The Startup class is where you define the request handling pipeline and where any services needed by the app are configured. The Startup class must be public and contain the following methods:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app)
{
}
}
I guess this will help you to understand how asp.net core handles Http requests.
Thanks
How do I get OWIN to host a SOAP endpoint (do not care if WCF is or isn't involved, SOAP gives WSDL which makes services easier to consume by certain clients, that's why I want SOAP and REST)
I suspect the answer is: Implement your own middleware that hosts a SOAP endpoint. If that's the answer so be it, but that's a lot of work so I'll probably just end up sticking with WCF and avoiding OWIN if that's the case. I find it hard to believe no one has implemented a SOAP hosting middleware yet...
As a rule we like to do both REST and SOAP endpoints on our services; currently we use IIS and the WCF restful bits to host the SOAP with [ServiceContract]/[OperationContract] attributes, and the rest is defined with [WebInvoke] attributes, with these attributes the services need no reimplementation for the different endpoint types.
We just use the ASP.NET routes to add new ServiceRoutes which add a rest binding to URI/REST with the same service as a soap binding to URI/SOAP.
Now we're looking at doing some new services work and I'd like to move forward to using OWIN so we can implement our new services with hosting agnosticism as some services will be better served by windows service hosting and some better served by IIS service hosting.
All of my fiddling with things and so far I can come up with no way of getting a SOAP endpoint hosted by OWIN. I have the rest handled fine by making my service inherit from ApiController and then using this little snippet of code in the OWIN app's Configuration method:
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
app.UseWebApi(config);
[...]
There is a custom OWIN middleware example on MSDN that shows how to support SOAP requests. It is not a general purpose WCF host but may be enough to expose your existing WCF Services (i.e. [ServiceContract/OperationContract]) within an ASP.NET Core app. The example does not include support for [WebGet/WebInvoke] but may be enough to get you started.
https://blogs.msdn.microsoft.com/dotnet/2016/09/19/custom-asp-net-core-middleware-example/
If your primary goal is simply to begin writing new services using OWIN and you still plan to host them in IIS using Microsoft.Owin.Host.SystemWeb. You could ignore the WCF requests within the OWIN pipeline and allow the IIS ASP.NET pipeline to handle them. This would enable you to write services that are a combination of OWIN middleware and traditional WCF endpoints.
public static class WCFAppBuilderExtensions
{
public static IAppBuilder IgnoreWCFRequests(this IAppBuilder builder)
{
return builder.MapWhen(context => IsWCFRequest(context), appBuilder =>
{
// Do nothing and allow the IIS ASP.NET pipeline to process the request
});
}
private static bool IsWCFRequest(IOwinContext context)
{
// Determine whether the request is to a WCF endpoint
return context.Request.Path.Value.EndsWith(".svc", StringComparison.OrdinalIgnoreCase);
}
}
Then call the IgnoreWCFRequests extension method when configuring your app.
public class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app
.IgnoreWCFRequests()
.UseWebApi(config)
.Run(context =>
{
return context.Response.WriteAsync("Default Response");
});
}
}
It's not so easy to host a WCF infrastructure over an OWIN one, sure it can be possible, with a bit of work it's clear possible to adapt, or proxy the owing request-response layer to the WCF infrastructure; WCF provides a not so easy but a complete infrastructure to do something like that.
cpowers answer may work for some, but didn't for me because I have other Filesystems setup within Owin, and I couldn't get both behaviors (fallback to other handlers when needed and also go through OWIN pipelines).
This was the configuration which made it work for me:
Use Owin automatic startup (Remove any appSettings named owin:AutomaticAppStartup)
Do not manually add its handlers in your web.config (or Startup will run twice) (Remove OwinHttpHandlerfrom from <handlers> in you web.config)
Add appBuilder.UseStageMarker(PipelineStage.MapHandler) after builder.UseFileServer()
UseFileServer must happen after all pipelines you setup, otherwise the ones setup after it will not work and you'll get 404
Optionally Fork the pipeline like cpower mentioned
If your OWIN pipelines does not register middlewares for the paths where your legacy stuff is you don't even need to fork your pipeline (my case).
I am trying to convert an existing ASP.NET Web API project (currently hosted in IIS) into one that can use the SelfHost framework. I'm a bit fuzzy on the actual details but understand I can run a self-host server in a console window and then run the service on top of it. The problem I'm having is that my project is an MVC project and not a console one. My familiarity with console/Windows apps is somewhat limited as I generally work with projects to be hosted in IIS.
What I'm a bit confused on is whether I need to convert my existing Web API project in Visual Studio into a new console application, or if there's a way to create another console application Project in the solution which can act as the web server for the Web API services, or rather if there's a way to add a console element with a Main() entry point to the existing MVC project (overriding the Global.asax entry point.)
Search didn't yield much information that helps me fill this knowledge gap. Hoping someone can point me in the right direction. Even at a high level.
I recently had to convert a Web API project into a self-hosted service using OWIN (on Visual Studio 2013). I did that as follows:
Manually added Program.cs and Startup.cs files at the root of the project. Both files containing code as described here: http://www.asp.net/web-api/overview/hosting-aspnet-web-api/use-owin-to-self-host-web-api.
Went to the properties of the Web API project. On the "Applications" section, I stated "Output Type" as "Console Application", and set the "Program" class as the "Startup object".
Although not required, I slightly modified the using block within Program.Main() to look as follows:
// Start OWIN host
using (WebApp.Start<Startup>(url: baseAddress))
{
// Create HttpCient and make a request to api/values
HttpClient client = new HttpClient();
var response = client.GetAsync(baseAddress + "api/values").Result;
if (response != null)
{
Console.WriteLine("Information from service: {0}", response.Content.ReadAsStringAsync().Result);
}
else
{
Console.WriteLine("ERROR: Impossible to connect to service");
}
Console.WriteLine();
Console.WriteLine("Press ENTER to stop the server and close app...");
Console.ReadLine();
}
Finally, instead of calling config.Routes.MapHttpRoute() multiple times within Startup.Configuration(), you can refer to the routes you already wrote for the Web API:
// Configure Web API for self-host.
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
Please help, I'm trying to self-host a web api.
When the same controller is hosted on a web project, and run on dev, via F5, everything works well.
However now I'm trying to self-host the same, I'm getting 411 and 404. 411, when I use Fiddler to connect, 404 when I'm attempting to connect via another library.
This is the console app that's supposed to host the service:
class Program
{
static int portNumber;
static void Main(string[] args)
{
portNumber = 8089;
var config = new HttpSelfHostConfiguration(
string.Format("http://localhost:{0}", portNumber));
config.Routes.MapHttpRoute(
"API Default", "api/{controller}/{id}",
new { id = RouteParameter.Optional });
using (var server = new HttpSelfHostServer(config))
{
var test = new RetrieveGuidService().Execute(Unit.Instance);
server.OpenAsync().Wait();
Console.ReadLine();
}
}
}
This is what my controller looks like, it doesn't do anything it's just a test.
public class RetrieveGuidServiceController : ApiController
{
public virtual Guid PostExecute(Unit request)
{
IQueryService<Unit,Guid> queryService = new RetrieveGuidService();
return queryService.Execute(request);
}
}
And here's how I'm attempting to access it via fiddler:
The same works when the service is hosted on a web project. I have followed this tutorial almost to the letter: asp.net WebApi self host tutorial which includes running nugget scripts, adding dependencies, etc.
What am I still missing?
The 411 is because you didn't put the Content-Length header. Even if you are not sending content you need to include Content-Length: 0.
Regarding having the Controller in the correct assembly I have had inconsistent behaviour. In some projects it seems to work in other it doesn't. Not sure what I am doing wrong. I have a project here that does both Web Host and Self-Host with all the controllers in a different assembly and it works just fine.
It seems that by default, the services will not look for controllers in assemblies beyond the one hosting the services.
I think it's an omission, unless I'm reading the specs wropng.