Plugging MVC5 into an OWIN/Katana Application - c#

I read in article that web api 2 can be easlity be integrated in Owin pipeline.
http://johnatten.com/2015/01/11/asp-net-web-api-2-2-create-a-self-hosted-owin-based-web-api-from-scratch/
// Owin code:
public class Startup
{
public void Configuration(IAppBuilder app)
{
var webApiConfiguration = ConfigureWebApi();
// Use the extension method provided by the WebApi.Owin library:
app.UseWebApi(webApiConfiguration);
}
private HttpConfiguration ConfigureWebApi()
{
var config = new HttpConfiguration();
config.Routes.MapHttpRoute(
"DefaultApi",
"api/{controller}/{id}",
new { id = RouteParameter.Optional });
return config;
}
}
I've read a lot articles about OWIN specification, but I'm still a little confused, please help me to clarify the questions:
Q:
Is it possible to ingtegrate asp.net mvc5 to Owin pipeline in the
same way as Web Api?
Or it is not possible due to tight binding to system.web assymbly?

No unfortunately it's not possible to run ASP.Net MVC 5 on Owin/Katana or self host. It needs IIS.
But ASP.Net Core completely runs on Owin and selfHost.

Related

How to connect container deployed in AKS

I am using the code in the below link to create a web api.
https://learn.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
I am using only the Products controller and Products code from the link and not using the UI related code. With local docker container, it is working fine.
starting Point:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
When I deploy the same in AKS and try to access the api, it is giving an error.
I am using the url "https://{service external ip}/api/products".
Can someone help me to connect to the AKS in the right way if I am doing any mistake.

How to prevent application pool stop, on POST requests?

I have a web api service placed on https sub domain. I used castle Windsor to create all classes (per web request), from controller to domain objects.
I tested all actions on local machine and also using fiddler. everything works fine. And no memory leak was happened. and also we have a mobile programmer which worked with all actions and again every thing was fine.
but after hosting on https, by each request to web api urls, application pool stops.
but the request to authorization works fine. What is wrong with my application? here is my code to Config file:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config, IAppBuilder app)
{
// Web API configuration and services
var container =Bootstrapper.WireUp();
ConfigCors(container, config);
RegisterControllers(container);
UserManagement.Config.Bootstrapper.WireUp(container);
config.Services.Replace(typeof(IHttpControllerActivator), new WindsorControllerActivator(container));
container.Register(Component.For<IDataProtectionProvider>().ImplementedBy<DpapiDataProtectionProvider>()
.UsingFactoryMethod(x => app.GetDataProtectionProvider()));
// Web API routes
config.MapHttpAttributeRoutes();
config.AddFiveLevelsOfMediaType();
config.Routes.MapHttpRoute(
name: "DefaultApiWithAction",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
//config.Routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = #"\d+" });
}
private static void ConfigCors(IWindsorContainer container, HttpConfiguration config)
{
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
}
There is no specific reason that application pool is stopping. It could be a windows registry error, system error or assembly permission error. The best way to find out why is to go and check event viewer.
From Administrative Tools select Event Viewer
Alternatively, press Windows Key and type Event Viewer. Once there look into the into Windows Logs and then Application logs. Search for any error (red icon) or warning (yellow icon) that is related to IIS / ASP.Net or .Net framework. I have attached a sample image from my system -
Another Instance -
** EDIT **: There is one other possibility since it stopped after enabling https. Check the SSL certificate. The most common reason is using same certificate in multiple sites. Only wild card certificates can be used in multiple site. If the certificate is self signed, delete it and create a new one with * , being the prefix for the certificate name. Then use that one.

Self Hosted Owin Web API 2 application: How do I start the web app with arguments

I am trying to add a REST API to a console application using self hosted Owin Web API 2.
// Starting the REST API
string baseAddress = "http://localhost:8000/";
WebApp.Start<WebApi.WebApiStartup>(url: baseAddress);
I am relying on previously instantiated objects to access a third party API (used in the console application).
Since the Web API mimics the console application behavior it should use the same objects. Thus my question: How do I pass those objects to the constructor of the web app?
Once the webapp started I use unity to Inject the objects to the controllers:
var container = new UnityContainer();
container.RegisterInstance<AggregatePosition>(position);
HttpConfiguration config = new HttpConfiguration();
config.DependencyResolver = new UnityResolver(container);
config.Routes.MapHttpRoute(name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
in this example the object "position" should be passed to the web app at initialization. Is there a way to Inject it there?

Azure Mobile App - Getting 405 (Method Not Allowed) when trying POST

I'm trying to migrate my Azure Mobile Service .NET backend to an Azure Mobile App.
I was using some custom Web Api controllers, and after migration I'm getting a 405 (Method Not Allowed) / The requested resource does not support http method 'POST'. error when trying to POST to a controller method that worked before.
I spent hours trying diffent CORS settings but I had no success so far.
This is how I currently configure Web Api:
HttpConfiguration config = new HttpConfiguration();
new MobileAppConfiguration()
.UseDefaultConfiguration()
.ApplyTo(config);
var cors = new EnableCorsAttribute("*", "*","*");
//var cors = new EnableCorsAttribute("*", "*","GET,POST,DELETE,HEAD,PUT,PATCH,OPTIONS");
config.EnableCors(cors);
config.Routes.MapHttpRoute(
name: "Rest",
routeTemplate: "rest/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.MapHttpAttributeRoutes();
The controller looks like that:
[Authorize]
[RoutePrefixAttribute("rest/companies")]
public class CompaniesController : ApiController
{
[HttpPost]
[Route("my-active")]
//[EnableCors("*","*","*")]
public HttpResponseMessage SetActive(/*[FromBody]*/Company company)
{
// Implementation
}
}
What I tried too:
Set CORS settings in web.config (custom headers / different settings), eg. <add name="Access-Control-Allow-Methods" value="GET,POST,DELETE,HEAD,PUT,PATCH,OPTIONS" />
Added a cors message handler according this blog post
(http://blog.bittercoder.com/2012/09/09/cors-and-webapi/)
This handler is also removed: <remove name="OPTIONSVerbHandler" />
One thing I noticed is, that a Azure Mobile App component seems to override the allowed methods and allowed headers that I configured using config.EnableCors(cors). I was only able to control all settings using web.config and the message handler. But it did not solve the 405 problem anyway.
At this point, I'm not sure if it's a CORS problem at all.
Any ideas? It's currently hard to find good documentation on Mobile Apps and I would appreciate if the .NET backend part would be open sourced... It's somewhat of a black box for me.
It could happen when you activate App Service Authorization and forget to change your mobile client url from http to https.
If so, your http Post will be redirected to the https url but with a Get message.
Found it thanks to Fiddler.
OMG, I found the problem with my code. I had to swap this two statements:
// Needs to be called before MapHttpRoute
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "Rest",
routeTemplate: "rest/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
As I was using Azure Mobile Services, calling MapHttpAttributeRoutes caused an error 'An item with the same key has already been added', so I removed that line. I had to re-insert it for Azure Mobile Apps again in order to get attribute routing to work, but I did it at the wrong place, so be careful.
If http Post is redirected to the https url as Get, try calling https directly.
Azure logs looks as follows in this case:
Received request: POST http://xxx.azurewebsites.net/api/Data/test
Information Redirecting: https://xxx.azurewebsites.net/api/Data/test
Received request: GET https://xxx.azurewebsites.net/api/Data/test
in this case call https://xxx.azurewebsites.net/api/Data/test

How does the In-Memory HttpServer know which WebAPI project to host?

I want to run tests against WebAPI project using a popular in-memory hosting strategy.
My tests reside in a separate project.
Here's the start of my test
[TestMethod]
public void TestMethod1()
{
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new {id = RouteParameter.Optional});
HttpServer server = new HttpServer(config);
HttpMessageInvoker client = new HttpMessageInvoker(server)
}
The client is initialized with the HttpServer, establishing the direct client-server connection.
Other than providing route config info, how does HttpServer know which WebAPI project to host?
How to host multiple WebAPI projects at the same time?
Seems HttpServer does some magic to locate WebAPI projects?
Thanks
Web API depends on a service called IAssembliesResolver to get all the assemblies and scans them to find controllers which implement the IHttpController interface.
Now sometimes Web API might be unable to find your controller depending on whether the assembly has been loaded into the current app domain or not. In that scenario you would need to make sure that your assembly is loaded.
Looking at your sample test code, it appears that you are not referring to any type from your Web API project in which case i assume the Web API project's assembly would not be loaded.
Also you seem to be registering the routes again in your test. I would suggest to use the WebApiConfig.Register(HttpConfiguration) of your Web API project to do all the registration stuff. This way you would be testing with the same settings that your Web API project has.
Notes:
When running tests using in-memory server, your requests/responses wouldn't go through the formatters' serialization/deserialization process which is dangerous as you could be having real issues during them. So you would need to make sure to take care about this. Long time back i wrote a blog post regarding this. You can check it out here.
Fiddler tool is very useful in looking at the raw requests/responses to diagnose any issues. You would be loosing this ability if you are doing in-memory testing though.
Web Api should find all your controllers that inherit from ApiController. As long as all your controllers are in the same solution it should work just fine. I have a very similar setup that runs tests using the in-memory httpserver against controllers in another project. This gives me the ability to do very fast "integration" tests in my unit test project.
Just make sure that you are invoking any controller from the web api project into your separate project to ensure that web api project is loaded in in-memory.Example:
[TestMethod]
public void TestMethod1()
{
//// So that the web api project is loaded in-memory
{webapi Project name}.Controller.{controllerName} = new {controller name}() ;
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new {id = RouteParameter.Optional});
HttpServer server = new HttpServer(config);
HttpMessageInvoker client = new HttpMessageInvoker(server)
}

Categories