Versioning of REST API Built With ASP.NET MVC 3 -

2019-06-24 00:43发布

I am wondering if there is a best practice for creating a REST API with ASP.NET MVC 3? At the moment I am thinking of creating a controller for each version of the REST API. For example, so far I have:

public class V1Controller : Controller
{
    public V1Controller()
    {
    }

    public ActionResult GetUser(string userId, IUserRepository userRepostory)
    {
        //code to pull data and convert to JSON string
        return View("Results");
    }

    public ActionResult GetUsersByGroup(string groupId, IUserRepository userRepostory)
    {
        //code to pull data and convert to JSON string
        return View("Results");
    }
}

Then for the views I overwrite the _ViewStart.cshtml to remove the layout and then I have Results.cshtml that just outputs the data that is formatted in the controller action, right now JSON. Having every single REST call in one controller seems like a bit too much but it is the best way I can think of so that I can keep clean separate versions of the API so that when it comes to creating version 2 of the API, I can create a V2Controller and not break the existing API to give people time to switch over to the new API.

Is there a better way to create a REST API with ASP.NET MVC 3?

3条回答
We Are One
2楼-- · 2019-06-24 00:51

I was able to find a decent solution using MVC's use of Areas.

First, I wanted to have my API follow this URL Definition:

http://[website]/[major_version]_[minor_version]/{controller}/{action}/...

I also wanted to break up the different versions in separate Project files and use the same Controller names in each version:

"../v1_0/Orders/ViewOrders/.."  => "../v2_3/Orders/ViewOrders/.."

I searched around and found a workable solution with the use of MVC Areas.

I created a new project in my solution called "Api.Controllers.v1_0" and, as a test, put a SystemController.cs file in there:

using System.Web.Mvc;

namespace Api.Controllers.v1_0
{
    public class SystemController : Controller
    {
        public ActionResult Index()
        {
            return new ContentResult() {Content = "VERSION 1.0"};
        }
    }
}

I then added a v1_0AreaRegistration.cs file:

using System.Web.Mvc;

namespace Api.Controllers.v1_0
{
    public class v1_0AreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get{ return "v1_0";}
        }

        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "v1_0",
                "v1_0/{controller}/{action}/{id}",
                new { controller = "System", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

I walked through the same steps above for a "..v1_1" project with the corresponding files in there, added the projects as references into my "Api.Web" MVC project and was off and running.

查看更多
淡お忘
3楼-- · 2019-06-24 01:09

If all you are returning is JSON, you do not need a view. Jusr return

new JsonResult(){Data = Data};

Look in here.


Also in terms of versioning, versions can be implemented as different controllers or as extra methods in the same controller. But without knowing why you would need versions and why your clients (which I assume are browsers) would need to know about versioning is not clear from your question.

查看更多
我只想做你的唯一
4楼-- · 2019-06-24 01:10

A controller such as the one you posted in your example code should always keep that methods that you have now for instance GetUsersByGroup() with the same signature. I don't see how there could be a different version of that method.

The inputs are group and repository (which I believe comes from DI). The output is a list of users in JSON format. That's all that matters to the users of the API. What you do inside this method is no one's business.

You should think more of inputs and outputs. You shouldn't be changing the signatures of existing actions unless it is really neccessary to do so.

Think of the controller class in terms of implementing the interface. You have an interface and controller class is it's implementation (I mean you don't need to have it but just think of it in that way). You will rarely change the interface once one or several classes implement it. But you might add the methods to it. And that requires only changes in implementing classes - it does not break the functionality of the API and everyone who's using it will be able to continue using it.

查看更多
登录 后发表回答