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?

Was it helpful?

Solution

So this is probably not the only way you could do it, but this is how I would do it:

  1. Create your own Attribute that inherits from RoutePrefixAttribute
  2. Override the Prefix property and add some logic in there to prepend "api" to the prefix if running on the desired server.
  3. 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)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top