Web Api documentation with swashbuckle - asp.net-web-api2

We are currently trying to start writing WebApi services for our products switching from traditional WCF SOAP based services. The challenge we have got is how to provide the api documentation. I came across the SwaggerUi/swash buckle.
One limitation we have is we do not want to host the WebApi services in IIS but in a Windows Service. I am new to Web Api so I might be doing things the wrong way.
So for testing, I am hosting the web api in a console application. I can use the HttpClient to invoke the Get method on the Web Api but I can't access the same if I type the url in a web browser (is this normal for self hosted web api?).
So I installed the Swashbuckle.core nuget package and included the following code in the Startup class (Owin selfhosted).
var config = new HttpConfiguration();
config
.EnableSwagger(c =>
{
c.IncludeXmlComments(GetXmlCommentsPath());
c.SingleApiVersion("v1", "WebApi");
c.ResolveConflictingActions(x => x.First());
})
.EnableSwaggerUi();
private static string GetXmlCommentsPath()
{
var path = $#"{AppDomain.CurrentDomain.BaseDirectory}\WebApiHost.XML";
return path;
}
When I browse to the following location
http://localhost:5000/swagger/ui/index
I get "page cannot be displayed" in IE. Similar for chrome.
Is there anything special that needs to be done when hosting a WebApi in a console/windows service application to get the documentation automatically?
(I have enabled Xml documentation for the project)
I have now attached a test project. Please follow the link below:
Test project
Regards,
Nas

Your problem is not with Swashbuckle, which is configured correctly. Instead it is with the fact that your OWin web app has closed by the time the browser navigates to the swagger URI. Your using statement means that the web app is shut down at the end of it - well before Chrome has opened and navigated to the swagger path. You need to ensure the web app is still running - then your path will be valid (although in your source code you have different ports 9000 and 5000 in your url variables).

Related

How to republish an ASP.NET Core 5 web application in IIS. Changes not taking effect

I've published an ASP.NET Core 5 Web API to IIS (using VS 2019 webdeploy), and it is running fine. Now I've made some minor changes and republished.
The changes take affect on my local machine using IIS Express, but I do not see them when I publish to my IIS server. I can see that the exe and dlls are updated, but the webapi behaviour does change.
Something as simple as setting the swaggerdoc title doesn't take affect.
Is there something else I need to do to refresh the app? I've tried recycling the app pool and doing an iisreset, but no luck. I've read that IIS is merely acting as a reverse proxy to Kestrel which is actually hosting the api. If so how do I recycle that?
As a test, I delete all the files in my web api directory. I browse to the web api and get the following error:
HTTP Error 500.31 - Failed to load ASP.NET Core runtime Common
solutions to this issue: The specified version of
Microsoft.NetCore.App or Microsoft.AspNetCore.App was not found.
Troubleshooting steps:
Check the system event log for error messages
Enable logging the application process' stdout messages Attach a
debugger to the application process and inspect For more information
visit: https://go.microsoft.com/fwlink/?LinkID=2028526
I then re-publish the web api and browse to it, but it still has the old behavior. I'm really confused, because I know the published dll for my service is correct.
If I use ILSpy I can see the following code:
public void ConfigureServices(IServiceCollection services)
{
IConfigurationSection appSettingsSection = Configuration.GetSection("ApplicationSettings");
ApplicationSettings appSettings = appSettingsSection.Get<ApplicationSettings>();
services.AddSingleton(appSettingsSection.Get<ApplicationSettings>());
services.AddControllers()
.AddXmlSerializerFormatters()
.AddJsonOptions(delegate(JsonOptions o)
{
o.JsonSerializerOptions.PropertyNamingPolicy = null;
o.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
services.AddSwaggerGen(delegate(SwaggerGenOptions c)
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "My Demo Service (" + appSettings.Environment + ")",
Version = "v1"
});
});
}
When I browse to the swagger page of my API on my local dev box the title matches code, and the property naming is what I want. When I browse to it on the server, the title of the swagger page is the old value, and the property naming policy is camel case, so I'm pretty sure I'm publishing the new version of my web api, but it's not being executed when I make http requests to the api. Something must be cached somewhere.

UrlHelper returning http links on Azure App Service

I have a service that when deployed on Azure App Services returns http links instead of https links when using UrlHelper. When testing on my development machine it returns https links as expected, and the service is available and accessed through https requests.
An example of the type of route from my startup I'm trying to use is:
routes.MapRoute(
"FooBar",
"api/Foo/{Id}/Bar");
The link is then constructed using:
IUrlHelper _urlHelper = // Injected into class via service registration
int id = 42; // Arbitrary value for example
_urlHelper.Link("FooBar", new {Id = id});
When running on my local machine using Docker on Windows from Visual Studio I get a link of https://localhost:1234/api/Foo/42/Bar, but on my deployed Linux Container App Service on Azure I get http://my-app-name.azurewebsites.net/api/Foo/42/Bar.
I don't know what I'm doing wrong to get an http link instead of an https link, and would appreciate any advice/pointing in the right direction.
So I found the solution was with the configuration of the ASP.Net Core app itself. I performed the following modifications and then everything worked correctly:
Added app.UseForwardedHeaders(); to the request pipeline.
Added the following snippet to service container registration:
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.All;
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
The KnownNetworks and KnownProxies need to be cleared as they default to assuming an IIS hosting environment. For extra security you can add the known proxy/network IPs instead of clearing them here.

Asp.Net Core signalR is not working if publishing inside virtual directory

I have developed an application in asp.net core and used signalR. When i publish it in root directory it works fine, but if i publish it inside virtual directory it doesn't work. My signalR hub is always pointing to the root directory.
Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ... other middleware ...
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chat");
});
}
And i have initialized it in client side like this,
chat.js
var connection = new signalR.HubConnection("/chat");
After publishing it inside virtual directory(/development/chatapp/source) it points like this,
http://localhost:100/chat?userId=1
But actually it has to point like this, so that it will work
http://localhost:100/development/chatapp/source/chat?userId=1
I have used asp.net core 2.0 and this signalR version(1.0.0-preview1-final).
Someone please suggest me to resolve this issue.
With the help of my friend i have found the root cause for this issue and i fixed it. Actually javascript doesn't know whether the application is hosted in root folder or sub folder(in virtual directory). It always points the root folder.
So when we are initializing it in js like this(new signalR.HubConnection("/chat")), it points the root directory as below,
http://localhost:100/chat?userId=1
Since javascript doesn't aware of IIS hosting, we need to tell the relative path from c#. So i get my application's base path as follows in controller,
ViewData["PathBase"] = Request.PathBase.ToString();
And if it has some value i just prepend it to '/chat', otherwise i just initialize it as '/chat'.
var connection = new signalR.HubConnection("/development/chatapp/source/chat");
This solves my problem :-)
Kailash P : With the help of my friend i have found the root ...
OK, thanks for your sharing.
I'm publish the SignalR Chat sample to IIS but NOT WORKS --X
SignalRChat :
 Tutorial: Get started with ASP.NET Core SignalR
 https://learn.microsoft.com/zh-tw/aspnet/core/tutorials/signalr?view=aspnetcore-2.2&tabs=visual-studio
*With Visual Studio debugging, the sample are works but NOT WORKS publish to IIS.
In page load, the send message button not enabled because there have some errors :
Failed to load resource: the server responded with a status of 500 (Internal Server Error)  chatHub/negotiate:1
[2019-11-18T06:40:26.977Z] Error: Failed to complete negotiation with the server: Error: Internal Server Error  Utils.ts:179
--
After add the vitural directory the SignalR Chat sample WORKS :
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
->
var connection = new signalR.HubConnectionBuilder().withUrl("/chat1/chatHub").build();
Don't know why there have no any official note about this problem (SignalR publishing).
[NET Core 2.2]
[Visual Studio 2019]

Can no longer access the list of API descriptors after installing Glimpse

We would like to use Glimpse in our ASP.net MVC project but are running into a problem when accessing the list of Web API descriptors.
We have installed Glimpse.Mvc4 1.2.2 using the Nuget Package Manager.
The following snippet gets all API descriptors and it works fine before we install Glimpse. After installing we do only get an empty list.
IEnumerable<ApiDescription> apiDescriptors = System.Web.Http.GlobalConfiguration
.Configuration
.Services
.GetApiExplorer()
.ApiDescriptions
Does anyone know why this call does not work when Glimpse is installed?
The problem is that the Glimpse ASP.NET module wraps all routes in its own objects. So API Explorer ignores them (thinks that they are not Web API routes).
To work around this issue, you must initialize a fresh copy of System.Web.Http.HttpConfiguration instead of using GlobalConfiguration.Configuration.
// need to create a custom configuration instance because the default one can be
// processed by Glimpse and be thus full of wrapped routesthat the ApiExplorer
// does not recognize.
var config = new System.Web.Http.HttpConfiguration();
WebApiConfig.Register(config);
// these line is useful if you use WebAPI Help page package
HelpPageConfig.Register(config);
Controllers.HelpController.Configuration = config;
// otherwise just get the `IApiExplorer` interface from the fresh configuration:
var apis = config.Services.GetApiExplorer().ApiDescriptions;

ASP.NET WebAPI fails from MVC4 controller

I'm new to ASP.NET Web API and I'm struggling with a very strange problem.
I have some code which calls a RESTful service and it executes fine from a console project, but I can't get it to run from an MVC4 project running under .NET 4.0
The code to call the service is very simple:
internal string Test()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://testserver");
var task = client.GetAsync("/someUri")
var response = task.Result;
response.EnsureSuccessStatusCode();
return response.Content.ReadAsStringAsync().Result;
}
}
As mentioned, called from a console project it works as expected and I get a response in milliseconds, however if I call the method from an action in my MVC4 controller after a few seconds I get a message stating that:
"A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to repond".
Weirdly, when debugging the MVC4 version, the task status always shows as WaitingForActivation.
Running fiddler doesn't show any request being made from the MVC4 version, but again does for the Console version.
After a fairly serious bit of googling I can't find anyone else who seems to have had this problem, so I'm guessing that I've fundamentally misunderstood something, but at the moment I'm not sure what!
Updated 16:55 BST, 11/09/2012
To make things even weirder, I've just created a new MVC4 site and I can call the method without any problems! I'm now trying to compare the sites, however one was an existing site that was upgraded to MVC4 and the other is a new blank site, so spotting the relevant difference could be tricky.
Updated 16:44 BST, 14/09/2012
This is now looking like some infrastructure / networking issue.
I upgraded the project to VS2012 with .NET 4.5 so that I could use async/await to try the suggested implementations to avoid a deadlock. This didn't change anything so I went back to square 1.
I created a new solution with a new MVC4 project, a new services library and a unit test project to run the service library outside of MVC.
In the service library I created one method to call a public "what's my IP" service, and another to call a company service that's exposed publicly but only responds properly to company IP addresses.
For some background, I connect in to the company LAN via a VPN.
When disconnected from the VPN, in both unit tests and MVC, the IP service responds HTTP 200, the company service responds HTTP 404 as expected.
When connected to the VPN, unit tests both respond HTTP 200, MVC both timeout.
Next I ran MS Soap Tool locally and used that to proxy calls to the company services. All calls (whether from unit tests or MVC) show a request and response, but the unit test registers the response whilst the MVC controller does not.
My only other thought is that it could be something to do with the size of the reply? All the "successes" have very small replies other than the unit test calling the company service?
The Microsoft recommended way to upgrade an MVC3 to MVC4 site is to start with a completely new MVC4 site a migrate your views, controllers & code over. So I think that your upgrade steps may be part of your issue, since you were able to get it to work in the new MVC4 site you created. If you need to manually upgrade your existing site, I would follow the steps outlined in Upgrading ASP.NET MVC 3 Project to ASP.NET MVC 4