Web API Interface Version control SDammann.WebApi.Versioning

Source: Internet
Author: User

Objective

When designing external Web APIs, there may be cases where the old and new versions of APIs coexist, such as open Web APIs to vendors, but when the same service is updated, it is not always possible for all vendors to update their systems at the same time, but if the service is changed directly into a new one, These vendors may not be able to connect with your service until they are in the new version of the program code that they can work on.

When this is not allowed, it is often desirable to call "the same api" "with a different version, where the same API contains the old and new versions of the service.

The current environment is the. NET Framework 4.0, Web API 1.0, ASP 4, which hopefully provides a simple way to provide the caller with a simple and understandable understanding: This is the same service for different versions.

Development on the hope can let developer very intuitively know, how to develop different versions of the service, do not need to tube routing this matter, as long as directly design controller content can be.

Description

Find an open source:SDammann.WebApi.Versioning on Github that meets my basic needs , and reference articles can refer to:

ASP. NET Web api:using namespaces to Version Web APIs Versioning ASP. NET Web API Services Using HTTP Headers

This solution provides two ways to define version:

Through routing, which is the URL definition version, in order to identify and find the corresponding controller through the request header, the advantage is that the URL is the same, as long as the request header to specify version, you can find the corresponding CO Ntroller

This article takes everyone fast and simple adopt this solution.

Practice

First build an ASP. NET MVC 4.0 project and select the Web API.

Then installing Sdammann.webapi.versioning,nuget through Nuget basically only helps us to join the relevant reference DLL.

The next action is super simple, in the Controller's folder, add Version1, because Controllerselector will be based on namespace to find the corresponding Controller. After establishing the Version1 folder, add a Hellocontroller:

Simply define a Get method, as well as a custom callback message format, message entity, as shown in the program code:

namespace webapiwithversioning.controllers.version1{public    class Hellocontroller:apicontroller    {        Public Message Get ()        {            return new Message {Token = "joey-v1", Signature = "" "};        }    }    public class Message    {public        string Token {get; set;}        public string Signature {get; set;}}    }

Next, add a Version2 folder under the Controller folders, adding a Hellocontroller, as follows:

Define a Get method, but the method seal can be different from Version1, for example, the return format is Anothermessage, and the program code is as follows:

namespace versioningwebapisample.controllers.version2{public    class Hellocontroller:apicontroller    {        Public Anothermessage Get ()        {            return new Anothermessage {newtoken = "joey-v2", newsignature = "" "};        }    Public    class Anothermessage    {public        string Newtoken {get; set;}        public string Newsignature {get; set;}}    }

To determine the version of a call through URL routing

Two versions of Hellocontroller.get () have already been completed, then just let the caller decide which version of Hello.get () to call.

In fact, as long as the iapiexplorer replaced with Versionedapiexplorer, and then depending on the need to decide to change ihttpcontrollerselector routeversionedcontrollerselector or Acceptheaderversionedcontrollerselector, the former is a URL routing to decide which version of the service to call, the latter is through the request of the accept header to determine the version.

Previous article [ASP. Api]3 minutes to get framework–unity application Block has been introduced, how quickly through Unity to do the Di action, the same way through NuGet to install Unit Y.WEBAPI, and then register the above two interface in Bootstrapper, The program code is as follows:

private static Iunitycontainer Buildunitycontainer ()        {            var container = new UnityContainer ();            Register all your components with the container here            //e.g. container. Registertype<itestservice, testservice> ();                        Container. Registertype<iapiexplorer, versionedapiexplorer> (New Injectionconstructor ( globalconfiguration.configuration));            Container. Registertype<ihttpcontrollerselector, routeversionedcontrollerselector> (New InjectionConstructor ( globalconfiguration.configuration));            Container. Registertype<ihttpcontrollerselector, acceptheaderversionedcontrollerselector> (New InjectionConstructor ( globalconfiguration.configuration));                        return container;        }

The above program code is first to differentiate the version through routing.

Do not forget to call Bootstrapper.initialise () in Global.asax, as follows:

public class WebApiApplication:System.Web.HttpApplication    {        protected void Application_Start ()        {            Bootstrapper.initialise ();            Arearegistration.registerallareas ();            Webapiconfig.register (globalconfiguration.configuration);            Filterconfig.registerglobalfilters (globalfilters.filters);            Routeconfig.registerroutes (routetable.routes);            Bundleconfig.registerbundles (bundletable.bundles);        }    }

The last action is to modify the routing mode, in Webapiconfig, add version of the routing rule, the program code is as follows:

  public static class Webapiconfig {public static void Register (Httpconfiguration config) {c Onfig. Routes.maphttproute (Name: "Defaultapiwithversion", Routet Emplate: "Api/v{version}/{controller}/{action}/{id}", defaults:new {id = routeparameter.            Optional}); Config. Routes.maphttproute (Name: "Defaultapi", Routetemplate: "API                    /{controller}/{action}/{id} ", defaults:new {id = routeparameter.optional}            ); Uncomment the following line of code to enable query support for actions with an IQueryable or iqueryable<t> Retu            RN type. To avoid processing unexpected or malicious queries, with the validation settings on Queryableattribute to validate Inco            Ming queries. For more information, Visit http://go.microsoft.com/fwlink/?LinkId=279712. Config.            Enablequerysupport (); To disable tracing in your application, please comment out or remove the following line's code//For more Information, refer To:http://www.asp.net/web-api config.        Enablesystemdiagnosticstracing (); }    }

Add a/v{version}/in the middle of the Routetemplate section to tell which version to call.

Done, take a look at how to call the Version1 service, as shown in:

The URL is/api/v1/hello/get, and the content is message.

What about the Version2 service? As shown in the following:

URL is/Api/v2/hello/get, callback is the content is anothermessage.

Bottom line: It's so easy to decide which namespace Controller to call through the URL routing!

Determine the version of the call through the Request Header

If you want the URL to be fixed, you can call different versions of the service as soon as you change the request header, which is fairly straightforward in this solution.

First, replace the container registered Ihttpcontrollerselector entity with Acceptheaderversionedcontrollerselector, as follows:

public static class Bootstrapper {public static void Initialise () {var container = Buildunit            Ycontainer ();        GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver (container);            } private static Iunitycontainer Buildunitycontainer () {var container = new UnityContainer (); Register all your components with the container here//e.g. container.                        Registertype<itestservice, testservice> (); Container. Registertype<iapiexplorer, versionedapiexplorer> (New Injectionconstructor (            globalconfiguration.configuration)); Container. Registertype<ihttpcontrollerselector, routeversionedcontrollerselector> (New InjectionConstructor (            globalconfiguration.configuration)); Container. Registertype<ihttpcontrollerselector, acceptheaderversionedcontrollerselector> (New InjectionConstructor ( Globalconfiguration.configuration));        return container; }    }

No, that's it, and then it's tested by the test Client of the help Page. (test client only needs to install A simple Test Client-for-ASP Web API through NuGet, as shown)

Then open the Api/v1/hello/get's description page:

Modify the URL to:api/hello/get, and add the Accept Header:application/json; Version=1 as shown:

After you click Send, you can see the result of the call Version1, as shown in:

We change the first header to version=2, then the result will be the result of Version2, as shown in:

Call different versions of the service, it is so simple, to switch the version of the corresponding way, as long as the container registered parts can be modified, which is also through the DI framework of the powerful convenience.

Extended Topics

One drawback of this solution is that the help Page will have a lot more strange APIs, as shown in:

These are not actually supposed to be called, nor can they be called properly.

Here is a simple modification of the content of the help page, so that the reader can see what we expect the help page look, design how to be flexible, you can ask the reader to think for themselves.

First open the Areas.helppage apidescriptionextensions, add an extension method checkisversioncontrollervalid to judge:

Does the Controller's namespace have version routetemplate with version?

The program code looks like this:

     Todo by Joey, added for version controller processing, is currently hard-code hard dry, future can be modified into regex public        static bool Checkisversioncontrollervalid (This apidescription description)        {            var controllername = (description. Actiondescriptor). ControllerDescriptor.ControllerType.FullName;            var routetemplate = (description. Route). Routetemplate;            var iscontrollerwithversion = Controllername.contains (". Version ");            var isroutetemplatewithversion = Routetemplate.contains ("{version}");            return iscontrollerwithversion = = isroutetemplatewithversion;        }

Then modify the apigroup.cshtml, add the judgment if the Controller's type matches the Version's routetemplate, it appears on the Help Page, as shown in the program code:

The help Page that comes out is what we want, as shown in:

Conclusion

Hope this simple, convenient way to meet the needs of multiple versions of the simultaneous service, but also allows the caller to easily and understood to call different versions of the service, and server-side switching and design can be quite simple, developer almost as long as the new version of the folder and continue writing the controller's contents.

Web API Interface Version control SDammann.WebApi.Versioning

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.