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 }
);
}
}
Related
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.
I have an MVC4 project with many controllers. I added an Api controller called BatchDetailsController in the root directory of the project.
I also created a WebApiConfig class as below
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
I also invoke the above register method from global.asax as
WebApiConfig.Register(GlobalConfiguration.Configuration);
in Application_Start
Now I have tried to access the controller by using then Urls
/BatchDetails
/api/BatchDetails
/BatchDetails/Get
/api/BatchDetails/Get
All of them return 404
What is the URL I need to use in this case
for example when using visual studio to debug/host the project the url would be http://localhost:port/api/BatchDetals/{method}
Right click on the project and see if IIS express is selected and note the port number. The project should come up via run/f5 in visual studio at the Project URL.
If not I would re-install IIS8 express.
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.
I have a api controller :
public class ExchangesController : ApiController
{
[HttpGet]
public List<ExchangesTrade> GetTrades(long tid)
{
I want to be able to call it from browser like /api/USD/trades.json?tid=5
How should I write "routes.MapRoute" in my RouteConfig ?
Firstly, routes.MapRoute will add routes for a traditional MVC app, if you want to add routes for your web api you need to add Http routes using MapHttpRoute on your web api HttpConfiguration routes.
In your web api config, you can add a URI path mapping extension like this:
config.Formatters
.JsonFormatter
.MediaTypeMappings
.Add(new UriPathExtensionMapping("json", "application/json"));
Add a route like this:
config.Routes.MapHttpRoute(
name: "ExchangesRouteWithExtensions",
routeTemplate: "api/USD/{action}.{ext}/{tid}",
defaults: new { controller = Exchanges, tid = RouteParameter.Optional }
);
Then access you endpoint like this:
api/USD/trades.json?tid=5
I have a WCF service that lives side-by-side with an MVC2 web site. I'd like for my URL for the service to look like this:
http://localhost/projdir/Service
The MVC site is in its infancy so it still has all its boilerplate controllers etc.
The following code works at first glance in global.asax:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new ServiceRoute("Service", new ServiceHostFactory(),
typeof(MyService)));
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index",
id = UrlParameter.Optional } // Parameter defaults
);
}
The service appears just where I described and works as advertised. Great.
However, I just noticed that ordering my code this way changes all of my ActionLink's. For example, the "About" tab on the MVC site now appears like this:
http://localhost/projdir/Service?action=About&controller=Home
This is obviously incorrect (it should be http://localhost/projdir/Home/About/ ).
If I move the ServiceRoute addition below the default MapRoute() call, then I get a missing controller error. (Actually I get a "StructureMapControllerFactory did not return an instance of a controller" error, because I'm wired up with StructureMap, duh, it's not a controller to begin with.)
Interestingly, it only seems to be affecting the output of Html.ActionLink(). I can manually type in http://localhost/projdir/Home/About/ and get to the correct page.
What horribly obvious newbie mistake am I making?
Try moving the Service route after the MVC route. But to avoid the "missing controller" error that you got before, add the MVC route with a Route Constraint. These route constraints can be Regex - basically you'd want your route constraint to be any controller that is not "Service". When a request for "Service" is requested, it will make it fall through and his the WCF Service Route.
I resolved with that:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "^(?!api).*" }
);
routes.Add(new ServiceRoute("api", new DataServiceHostFactory(), typeof(dwService)));
I hope this good for you
Another solution is to inherit the ServiceRoute and override the GetVirtualPath method to return null as described here
public class AppServiceRoute : ServiceRoute
{
public AppServiceRoute(string routePrefix, ServiceHostFactoryBase serviceHostFactory, Type serviceType)
: base(routePrefix, serviceHostFactory, serviceType)
{
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}
This way, reverse route mapping never select this route for any Action. Works like a charm