Error enabling swagger with swashbucle - asp.net-web-api2

I am trying to create a WebApi project with a couple of simple controllers. If I call the methods using fiddler all is fine, however I prefer to use swashbuckle as it's a bit prettier.
However, with swashbuckle installed using the default configuration it isn't working.
When I navigate to
http://localhost/api/mycontroller/swagger
it redirects to
http://localhost/api/mycontroller/swagger/ui/index
But then it just displays the following error:
<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://localhost/api/Management/swagger/ui/index'.
</Message>
<MessageDetail>
No type was found that matches the controller named 'swagger'.
</MessageDetail>
</Error>
My routing is as follows:
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);

We found a very simple solution to our issue.
When swagger was added to the project it automatically updated the Bootstrapper.cs within App_Start, and it looked like this:
WebApiConfig.Register(config);
UnityConfig.Register(config, container);
SignalRConfig.Register(app, container);
SwaggerConfig.Register(config);
Simply moving swagger to the top of the list allowed it to register it's routes correctly before the web api routes:
SwaggerConfig.Register(config); // Swagger must be the first thing in this sequence or it just does not work...
WebApiConfig.Register(config);
UnityConfig.Register(config, container);
SignalRConfig.Register(app, container);
Just posting this in the hope that it helps someone else.

I had the same issue, we are only using attribute routing so this may not apply to everyone.
By default the WebApiConfig looks like this:
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
If you remove the section for to MapHttpRoute for the default routing and just have:
config.MapHttpAttributeRoutes();
It works like a champ!!! I tried following the FAQ regarding fixing it but this was the only thing that worked. Also another item to consider is that I only needed Swashbuckle.Core.

Related

Hosting MVC 4 Application in IIS Application

I have several applications deployed to IIS. I created a site for each application and mapped them using different port number. Recently, I was asked to use virtual directory instead of mapping them using different port number. I created the virtual directory and add a route for it. When I tried to test the application locally, I was getting a 403.14. After reading several post online, I made the following changes to my web.config file
<modules>
<remove name="UrlRoutingModule-4.0"/>
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule,
System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
preCondition="" />
</modules>
I am not getting a directory with all the files name. I updated my route in the
RouteConfig.cs file to
routes.MapRoute(
name: "Default",
url: "CollegeOfBusiness/{controller}/{action}/{id}",
defaults:
new { controller = "Account", action = "Logon", id = UrlParameter.Optional},
namespaces: new[] { "MyCollege.Controllers" }
);
After making those changes, I am not getting the 400.13 anymore; however, I am not getting the login page. I am getting a directory of all the files. I ran the command "aspnet_regiis /i" and then aspnet_regiis -ir to make sure that it was not a registration issue. I have not had any luck so far. I am looking for any information or resources that could help fix this issue.
Local System:
Windows 7
IIS 7.5
Visual Studio 2017
Asp.net MVC 4
Jquery 2.3
Update 07/03/2018 #9:45
I modified the route as shown below. I am not getting the directory listing anymore. However, POSTs and GETs are not routing to the appropriate controller.
The url when the page first loaded looked as shown here:
http://localhost/CollegeOfBusiness
I added the custom route below. It is added right above the default route.
RouteConfig.cs file to
routes.MapRoute(
name: "CollegeOfBusiness",
url: "CollegeOfBusiness/{controller}/{action}/{id}",
defaults:
new { controller = "Account", action = "Logon", id = UrlParameter.Optional},
namespaces: new[] { "MyCollege.Controllers" }
);
Then, I add the default route at the bottom.
RouteConfig.cs file to
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults:
new { controller = "Account", action = "Logon", id = UrlParameter.Optional},
namespaces: new[] { "MyCollege.Controllers" }
);
When the user clicked on login button, the post URL looked as follow:
/CollegeOfBusiness/Account/Logon
Finally, I was able to get it to work.
1. I removed the below custom route because it was not needed.
RouteConfig.cs file to
routes.MapRoute(
name: "CollegeOfBusiness",
url: "{controller}/{action}/{id}",
defaults:
new { controller = "Account", action = "Logon", id = UrlParameter.Optional},
namespaces: new[] { "MyCollege.Controllers" }
);
As suggested in this POST, I added the url to a div and get it based on the Id. I also change the src for all js and css file to use #Url.Action().
I had to prepend '/CollegeOfBusiness' in front of all requests
I changed the application pool to use a service account. This account did not have access to update the database, so I fixed that as well.

Unable to change swagger ui path

I'm using Swagger / Swashbuckle version 5.6 to generate documentation for my ASP.Net Web API 2 project.
By default API documentation is accessible at URL http://localhost:56081/swagger/ui/index
But, I want it should be available at http://localhost:56081/apihelp/
I searched a lot, tried changing settings in the SwaggerConfig.cs file but nothing seems to make this work.
So, is this even possible? if yes, can anyone help me with this ?
You can add the path to the call of EnableSwaggereUi,
e.g.:
SwaggerConfig.Register(HttpConfiguration config)
{
config.EnableSwaggerUi("apihelp/{*assetPath}", c =>
... // following lines omitted
}
You can then call the UI with the URL http://localhost:56081/apihelp/index
See https://github.com/domaindrivendev/Swashbuckle#custom-routes for reference.
Please note: the default setting 'swagger' redirects automatically to 'swagger/ui/index', but this custom setting does not automaically redirect to 'apihelp/index' when you just use 'apihelp'.
To achieve an automatic redirect you can add the route in WebApiConfig:
config.Routes.MapHttpRoute(
name: "Swagger UI",
routeTemplate: "apihelp",
defaults: null,
constraints: null,
handler: new RedirectHandler(message => message.RequestUri.ToString().TrimEnd('/'), "/index"));
The redirect code is based on v.karbovnichy's answer in How to redirect from root url to /swagger/ui/index?

Asp.Net Web API action string route mapping

I have a contoller named customer and an action method for GetAllCustomers which recieves single string input parameter as FirstName. The issue is that I want the url to be like
MyAPI/Customer/MyFirstName
but the above stated URL is not working for me instead it working as below
MyAPI/Customer?firstname=MyFirstName
How can I make it work like the first url using ApplicationRouting (nuget package)? I have configured the attrbute route for the action method as below.
[GET("Customer/{firstname}")]
public List<Customer> GetAllCustomersFirstname(String firstname)
{
//code goes here
}
Edit
Here is the reference whatI am trying to achieve but it is not happening for me in ApiController
Attribute Routing Github
Open up ApiConfig in the AppStart folder. You need to add the route for that particular action. I think you'll need more than just what you showed there for route since you have to tell it which action to call and what methods to allow. E.g.
config.Routes.MapHttpRoute(
name: "yourRoute",
routeTemplate: "api/{controller}/{firstname}",
defaults: new { controller = "Customer", action = "GetAllCustomersFirstname" });

MVC Web API route config - filter controllers in route templates

My WebApiConfig.cs Register method looks like this:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "ClassroomContentApi",
routeTemplate: "classroomContent/{controller}/{id}",
defaults: new {id = RouteParameter.Optional}
);
// Default
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new {id = RouteParameter.Optional});
MediaTypeHeaderValue appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
}
My Controllers folder in my MVC project is structured like this (these are not the real names of the controllers but that's not important):
Controllers
ClassroomContent
ClassroomController.cs
ClassroomController2.cs
ClassroomController3.cs
SchoolInfo
CampusController.cs
CampusController2.cs
CampusController3.cs
StudentInfo
StudentController.cs
StudentController2.cs
StudentController3.cs
etc...
I want all the controllers in the ClassroomContent folder to use the first route above, and all the other controllers (in any other folders) to use the second route above.
The issue I am having is that the first route above picks up web api actions in controllers outside the ClassroomContent controllers folder, and vice versa.
For example, I can access http://MYHOST/classroomContent/Campus or http://MYHOST/api/Classroom. I want to be able to access the Classroom controller only from http://MYHOST/classroomContent/Classroom and the Campus controller only from http://MYHOST/api/Campus.
I understand that this is "expected behavior" in that nothing is preventing this from the perspective of how my routes are configured. But how do I prevent it?
What I have considered:
Using areas. However, from what I read, they are not supported for Web API (at least not out of the box). I could try to explore the option of trying to implement areas functionality, but it seems like a lot when I am not even sure that they are the right solution.
Defining a separate route for each controller. However, I have many controllers, so this seems very cumbersome.
What would be the best way to approach this problem? Is there any way to do it without trying to implement areas for Web API myself? Ideally I'd be able to somehow "filter" which controllers are valid values for the {controller} parameter of each route template.
RouteConstraints should also work if you prefer not to use attribute routing.
Assuming your controllers are named: ClassRoom1Controller, ClassRoom2Controller etc the following should work (note that you can use regular expressions to configure the constraints so there should be many possibilities to configure this as you like):
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "ClassroomContentApi",
routeTemplate: "classroomContent/{controller}/{id}",
defaults: new {id = RouteParameter.Optional},
constraints: new { controller = "classRoom1|classRoom2|classRoom3" }
);
// Default
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new {id = RouteParameter.Optional},
constraints: new { controller = #"^((?!(classRoom1|classRoom2|classRoom3)).)*$" });
MediaTypeHeaderValue appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
}
This link should help you : http://aspnetwebstack.codeplex.com/wikipage?title=Attribute%20routing%20in%20Web%20API
You can define custom routes at controller level with Web Api 2.

WebAPI routeTemplate customization

I'm trying to figure out if its possible to change the routeTemplate format of WebAPI.
Currently the default is set to be api/{controller}/{id}
I want to know if its possible to change the "api" part to say something else so the format would be something like
myapi/{controller}/{id}
I changed it in the global.asax.cs file but when I build the project, in order to load the service it still requires me to browse to /api/ instead of what I put in its place.
Thanks in advance :)
Are you using RTM version of MVC 4?
The reason why I am asking is that in RTM the HTTP route is in App_Start\WebApiConfig.cs, and, yes, changing the route from "api" to "myapi" here should work.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}