Web Api 2 global route prefix for route attributes?
-
23-12-2019 - |
Question
I'd like to expose a company's api by two ways:
api.company.com (pure WebApi web site)
company.com/api (add WebApi to existing MVC5 company site)
So, I placed models/controllers in a separate assembly and reference it from both web sites.
Also, I use route attributes:
[RoutePrefix("products")]
public class ProductsController : ApiController
Now, the controller above can be accessed by:
api.company.com/products which is good
company.com/products which I'd like to change to company.com/api/products
Is there a way to keep using route attributes and setup MVC project so it adds "api" for all routes?
Solution
So this is probably not the only way you could do it, but this is how I would do it:
- Create your own Attribute that inherits from RoutePrefixAttribute
- Override the Prefix property and add some logic in there to prepend "api" to the prefix if running on the desired server.
Based on a setting in your web.config, prepend to the route or not.
public class CustomRoutePrefixAttribute : RoutePrefixAttribute { public CustomRoutePrefixAttribute(string prefix) : base(prefix) { } public override string Prefix { get { if (Configuration.PrependApi) { return "api/" + base.Prefix; } return base.Prefix; } } }
EDIT (The below option is no longer supported as of Web API 2.2)
Alternatively you could also specify more than one route prefix:
[RoutePrefix("api/products")]
[RoutePrefix("products")]
public class ProductsController : ApiController
OTHER TIPS
You can use Map on IAppBuilder
So Startup class will looks something like this
class Startup
{
public void Configuration(IAppBuilder app)
{
app.Map("/api", map =>
{
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
map.UseWebApi(config);
});
}
}
Another option would be to forward traffic from one site to your Web API. Are you set on hosting two instances? If not, you could host only the one instance under say api.company.com/products. On your MVC company site implement an HttpHandler to redirect all traffic matching /api/* to api.company.com:
a. Create the handler in your MVC app:
public class WebApiHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string url = "api.company.com" + context.Request.RawUrl.Replace("/api","");
//Create new request with context.Request's headers and content
//Write the new response headers and content to context.Response
}
}
b. Register the handler in your web.config:
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="api/*" type="Name.Space.WebApiHandler" validate="false" />
</httpHandlers>
</system.web>
</configuration>
c. Enable CORS in your Web API if you haven't done so already.
You can just implement your api service as www.mycompany.com/api.
Then use UrlRewrite to map api.mycompany.com to www.mycompany.com/api
We even support this method of UrlRewrite in link generation, so if you generate links from the api.mycompany.com, your links will point to api.mycompany.com/controller/id.
Note that this is the only form of URL rewrite that works correctly for MVC link generation (api.xxx.yyy -> www.xxx.yyy/api)