.NET 4.8 Owin ASP.NET SSL/HTTPS - c#

I have a simple self-hosted OWIN ASP.NET API as seen in the code below.
I need to run this over https. Is it as simple as changing the BaseAddress and installing a self-signed certificate as given here:
https://chavli.com/how-to-configure-owin-self-hosted-website-with-ssl/
If not, what's the simplest way of configuring SSL for this case ?
internal class Program
{
private static string BaseAddress = "http://localhost:9005/";
private static void Main(string[] args)
{
var app = WebApp.Start<Startup>(url: BaseAddress);
Console.ReadLine();
}
}
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)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}

Related

OWIN Startup class is being executed along with WebAPIConfig.Register method

I am using Microsoft.Owin.Hosting in my one of integration test project to self-host the Web API in order to test end to end functionality.
[TestMethod]
public void GetLoanApplications()
{
using (WebApp.Start<Startup>(url: url))
{
using (var client = new HttpClient())
{
// Create httpclient and send request-and-response-metadata-in-aspnet-web-api
}
}
}
I am able to self-host the web API and able to invoke the controller action. Owin requires some Startup class configuration, which is as follows:
[assembly: OwinStartup(typeof(MyService.App_Start.Startup))]
namespace MyService.App_Start
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
app.UseWebApi(config);
}
}
}
Here is my Web API Config method looks like:
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Problem
When I run my main application (not the test project) both the Owin startup and web API config methods are getting called.
Let's say if I have some services or filters to be configured, it will get invoked twice.
What I thought is IF I am running test project it should only invoke owin startup file (which it is doing right now) and when I am debugging my main app it should only call web API config register method.
Any idea on is this the way it should work or I am doing something wrong?
First the system would need a way to differentiate between the environments.
<appSettings>
<add key="APP_ENVIRONMENT" value="Development" />
<!-- ... -->
</appSettings>
Since when run in production both the Owin startup and web api config methods are getting called then OWIN is already configured as a first class citizen in the project.
I suggest moving the code from Application_Start into owin start up
public class WebApiApplication : System.Web.HttpApplication {
protected void Application_Start() {
//REMOVE THIS AND LET OWIN STARTUP HANDLE SETUP
//GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
so that it is only invoked once depending on the configured environment.
[assembly: OwinStartup(typeof(MyService.App_Start.Startup))]
namespace MyService.App_Start {
public class Startup {
const string EnvironmentKey = "APP_ENVIRONMENT";
const string PRODUCTION = "Production";
const string TEST = "Test";
public void Configuration(IAppBuilder app) {
string ENVIRONMENT = ConfigurationManager.AppSettings[EnvironmentKey]
?? Production;
if(ENVIRONMENT == TEST) {
var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);
} else {
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}
}
}
Note the reuse of the WebApiConfig.Register to avoid repeated code. The same configuration will be applied for either environment and all in the same place if additional configurations were to be implemented (ie Development, Testing, Staging, Procustion...etc)
The test project app.config would include the current environment's setting
<appSettings>
<add key="APP_ENVIRONMENT" value="Test" />
<!-- ... -->
</appSettings>
and invoke the start up configuration for self-hosting otherwise it will default back to production settings, but would have also been configured in the web.config
<appSettings>
<add key="APP_ENVIRONMENT" value="Production" />
<!-- ... -->
</appSettings>
You need to chose between init your web api from the OWIN pipeline or with the old method in the Application_Start, see the application lifecycle.
If you keep Application_Start and OwinSartup then your web api is initialized twice

asp.net webapi selfhost controllers from another project

I have a webapi2 project and I want to selfhost this api in another project and call the methods with a httpClient. Here is my code:
namespace TestSelfHosting.Controllers
{
public class ProductsController : ApiController
{
[HttpGet]
public string GetProduct()
{
return "test";
}
}
}
And the code from the test project:
namespace TestSelfHosting.Tests
{
public class Startup
{
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
}
namespace TestSelfHosting.Tests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
const 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/products").Result;
var content = response.Content.ReadAsStringAsync().Result;
}
}
}
}
But when I'm calling client.GetAsync method, is throwing an error (404, not found). Is this possible to achieve or am I doing something wrong?
I've followed the tutorial from here
Have you referenced your webapi2 project in the self-host project (test project)?
If not, go to your self-host project -> references -> add reference -> locate your webapi2.dll and add it (you must build your webapi2 project beforehand to “generate” the dll file)

Issue in angularjs2 with restful web API

I am doing AngularJS2 with Restful web API , and getting some console errors while calling HTTP post. Errors are listed below,
Hope you help
Controller code snippet
namespace SoomWebApi.Controllers
{
[EnableCors(origins: "http://localhost:64336", headers: "*", methods: "*")]
public class UserController : ApiController
{
public HttpResponseMessage UserLogin([FromBody] LoginRequestData objValidate)
{
UserModelManager _UserModelManagerr = new Models.UserModelManager();
return Request.CreateResponse(HttpStatusCode.OK, _UserModelManagerr.Login(objValidate), GetJSONFormatter());
}
}
}
Webapiconfig code snippet
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
It look like a CORS problem .. try to put in your Startup.cs file in WebAPI something like:
using Microsoft.Owin;
using Owin;
public void Configuration(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
ConfigureAuth(app);
}
If you want to limit to some specific host ..try something like:
var corspolicy = new corspolicy
{
allowanymethod = true,
allowanyheader = true,
supportscredentials = true,
origins = { "http://www.example.com", "http://localhost:38091", "http://localhost:39372" }
};
app.usecors(new corsoptions
{
policyprovider = new corspolicyprovider
{
policyresolver = context => task.fromresult(corspolicy)
}
});
Your server should support CORS to allow access from different domains. Update your server configuration to allow only predefined set of domains to allow access.
Access-Control-Allow-Origin: "domains"
If you have this problem on debug only and do not plan use CORS after deploy - mostly local web server starts your Angular application on localhost:some-port and server deployed on localhost also - use IE for debugging - it works good even when your angular middleware and backend works on different ports.
If the code in production will be on the same domain as REST API, you can install chrome extension to avoid CORS error:
Chrome CORS extension

404 not found when self hosting ASP.NET Web API, works fine within IIS

I'm currently stuck with a self-hosted Web API I'm trying to use within a unit test.
Whatever route I try, I get a 404 not found error. The issue is, when hosting the very same Web API within IIS, everything works fine. I'm guessing it's a simple typo/mistake in my test config, but I can't make it work, any help appreciated.
Here's the fully working config I used for my Web API when hosted within IIS:
public class WebApiApplication : System.Web.HttpApplication
{
/// <summary>
/// Entry point of the application.
/// </summary>
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
}
}
public static void Register(HttpConfiguration config)
{
// IoC configuration
var container = new UnityContainer();
UnityContainerConfigurator.Configure(container, new PerRequestLifetimeManager());
// Set the dep resolver
config.DependencyResolver = new UnityDependencyResolver(container);
// Web API routes
config.MapHttpAttributeRoutes();
// Only supports JSON formatter
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
config.Formatters.JsonFormatter.SerializerSettings = CustomJsonSerializerSettings.Create();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional });
// Custom filter
var providers = config.Services.GetFilterProviders().ToList();
var defaultprovider = providers.Single(i => i is ActionDescriptorFilterProvider);
config.Services.Remove(typeof(IFilterProvider), defaultprovider);
config.Services.Add(typeof(IFilterProvider), new UnityFilterProvider(container));
}
Here's the non-working config I'm using for my unit test:
var config = new HttpSelfHostConfiguration(webApiURL);
#if DEBUG
// For debug purposes
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
#endif
// Web API routes
config.MapHttpAttributeRoutes();
// Only supports JSON formatter
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
config.Formatters.JsonFormatter.SerializerSettings = CustomJsonSerializerSettings.Create();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional });
// Custom filter
var providers = config.Services.GetFilterProviders().ToList();
var defaultprovider = providers.Single(i => i is ActionDescriptorFilterProvider);
config.Services.Remove(typeof(System.Web.Http.Filters.IFilterProvider), defaultprovider);
config.Services.Add(typeof(System.Web.Http.Filters.IFilterProvider), new UnityFilterProvider(this.UnityContainer));
// Overwrites the IoC configuration
config.DependencyResolver = new UnityDependencyResolver(this.UnityContainer);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
this.webApiServer = new HttpSelfHostServer(config);
this.webApiServer.OpenAsync().Wait();
enter code here
I also tried the new Owin hosting services, same result:
public class Startup
{
private static IUnityContainer container;
/// <summary>
/// Overwrites the IoC configuration.
/// </summary>
/// <param name="container">The container.</param>
public static void ConfigureIoC(IUnityContainer container)
{
Startup.container = container;
}
/// <summary>
/// This code configures Web API. The Startup class is specified as a type
/// parameter in the WebApp.Start method.
/// </summary>
/// <param name="appBuilder">The application builder.</param>
public void Configuration(IAppBuilder appBuilder)
{
if (Startup.container == null)
{
throw new Exception("Call ConfigureIoC first");
}
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional });
// Web API routes
config.MapHttpAttributeRoutes();
// Only supports JSON formatter
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
config.Formatters.JsonFormatter.SerializerSettings = CustomJsonSerializerSettings.Create();
// Custom filter
var providers = config.Services.GetFilterProviders().ToList();
var defaultprovider = providers.Single(i => i is ActionDescriptorFilterProvider);
config.Services.Remove(typeof(System.Web.Http.Filters.IFilterProvider), defaultprovider);
config.Services.Add(typeof(System.Web.Http.Filters.IFilterProvider), new UnityFilterProvider(container));
// Overwrites the IoC configuration
config.DependencyResolver = new UnityDependencyResolver(Startup.container);
appBuilder.UseWebApi(config);
}
}
The very same REST request I'm starting with Postman is a success when hosted within IIS, and a 404 when hosted within my unit test as a self hosted service.
Any hint?
You should check whether your self hosting application contains a Virtual Directory (like IIS). And as you mentioned ensure the base path is valid.

ASP.NET Web-API OWIN: No HTTP resource was found that matches the request URI

Thanks to the help of some users on this site, I got my test application working and am now starting to write the actual application I need.
I have a C# application which uses OWIN to host a ASP.NET Web API. I need the application to supply information about other open applications. I have programmed it nearly exactly the same as my test/example program which I got working, but changed a few names.
When I try to access `http://localhost:9000/api/applications I get an error message:
<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://localhost:9000/api/applications'.
</Message>
<MessageDetail>
No type was found that matches the controller named 'applications'.
</MessageDetail>
</Error>
`The Server class is the main class:
namespace Server
{
public class Server
{
public const string baseAddress = "http://localhost:9000/";
static void Main(string[] args)
{
ApplicationManager.getManager().AddApplication(new Application(1, "Chrome", 0.5f));
ApplicationManager.getManager().AddApplication(new Application(2, "Windows Media Player", 1.0f));
ApplicationManager.getManager().AddApplication(new Application(3, "Minecraft", 1.0f));
using (WebApp.Start<Startup>(url: baseAddress))
{
Console.ReadKey();
}
}
}
}
This is a my Web API config class:
namespace Server
{
public class Startup
{
public void Configuration(IAppBuilder appBuilder)
{
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
}
And here is my controller:
namespace Server.Api.Controllers {
public class ApplicationController : ApiController
{
public IEnumerable<Application> Get()
{
return ApplicationManager.getManager().GetApplications();
}
public IHttpActionResult Get(int id)
{
Application app = ApplicationManager.getManager().GetApplication(id);
if (app == null)
{
return NotFound();
}
return Ok(app);
}
} }
The Application object just contains a few properties and constructors. The ApplicationManager class just adds applications to a list of applications, which is used by the controller.
Replace http://localhost:9000/api/applications by http://localhost:9000/api/application. Last letter s caused this issue. Hope this helps!
I was facing this problem as well. After struggling a lot I realized that my Controller class was private which was causing the issue.

Categories