MVC API路由当多个GET操作是present [英] MVC API Routing When Multiple Get Actions Are Present

查看:143
本文介绍了MVC API路由当多个GET操作是present的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

似乎有一千人询问关于堆栈溢出同样的问题,但似乎没有成为一个单一的解决这个问题。我要再问吧...

There seems to be a thousand people asking the same question on stack overflow, but there doesn't seem to be a single solution to this problem. I am going to ask it again...

我有了以下操作的API控制器:

I have an API controller that has the following actions:

    // GET api/Exploitation
    public HttpResponseMessage Get() {
        var items = _exploitationRepository.FindAll();

        var mappedItems = Mapper.Map<IEnumerable<Exploitation>, IEnumerable<ExploitationView>>(items);

        var response = Request.CreateResponse<IEnumerable<ExploitationView>>(HttpStatusCode.OK, mappedItems);
        response.Headers.Location = new Uri(Url.Link("DefaultApi", new { }));
        return response;
    }

    // GET api/Exploitation/5        
    [HttpGet, ActionName("Get")]
    public HttpResponseMessage Get(int id) {
        var item = _exploitationRepository.FindById(id);
        var mappedItem = Mapper.Map<Exploitation, ExploitationView>(item);

        var response = Request.CreateResponse<ExploitationView>(HttpStatusCode.OK, mappedItem);
        response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = id }));
        return response;
    }

    // GET api/Exploitation/GetBySongwriterId/5
    [HttpGet, ActionName("GetBySongwriterId")]
    public HttpResponseMessage GetBySongwriterId(int id) {
        var item = _exploitationRepository.Find(e => e.Song.SongWriterSongs.Any(s => s.SongWriterId == id))
                                          .OrderByDescending(e => e.ReleaseDate);
        var mappedItem = Mapper.Map<IEnumerable<Exploitation>, IEnumerable<ExploitationView>>(item);

        var response = Request.CreateResponse<IEnumerable<ExploitationView>>(HttpStatusCode.OK, mappedItem);
        response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = id }));
        return response;
    }

    // GET api/Exploitation/GetBySongwriterId/5
    [HttpGet, ActionName("GetBySongId")]
    public HttpResponseMessage GetBySongId(int id) {
        var item = _exploitationRepository.Find(e => e.SongId == id)
                                          .OrderByDescending(e => e.ReleaseDate);
        var mappedItem = Mapper.Map<IEnumerable<Exploitation>, IEnumerable<ExploitationView>>(item);

        var response = Request.CreateResponse<IEnumerable<ExploitationView>>(HttpStatusCode.OK, mappedItem);
        response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = id }));
        return response;
    }

在我APIConfig我已经定义了以下路线:

In my APIConfig I have defined the following routes:

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        config.Routes.MapHttpRoute(
            name: "ActionApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional, action = RouteParameter.Optional },
            constraints: new { id = @"\d+" }
        );

我发现我可以访问以下操作没有问题:
/ API /开发
/ API /开发/ getbysongwriterid / 1
/ API /开发/ getbysongid / 1

I am finding that I can access the following actions no problem: /api/exploitation /api/exploitation/getbysongwriterid/1 /api/exploitation/getbysongid/1

当我试图访问/ API /开发/ 1我得到这个例外

When I try to access /api/exploitation/1 I get this exception

"Multiple actions were found that match the request: System.Net.Http.HttpResponseMessage Get(Int32) on type Songistry.API.ExploitationController System.Net.Http.HttpResponseMessage GetBySongwriterId(Int32)" exception.

有人能看到什么是错我的路线?还是错别的东西?

Can anyone see what is wrong with my routes? Or wrong with something else?

推荐答案

我已经找到一个优雅的解决这个问题。

I have found an elegant solution to the problem.

我修改了ApiRouteConfig有以下途径:

I modified my ApiRouteConfig to have the following routes:

        config.Routes.MapHttpRoute(
            name: "DefaultGetApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional, action = "Get" },
            constraints: new { id = @"\d+", httpMethod = new HttpMethodConstraint(HttpMethod.Get) }
        );

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: new { id = @"\d+" }
        );            

        config.Routes.MapHttpRoute(
            name: "ActionApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional, action = RouteParameter.Optional }
        );

现在我可以访问:

/api/exploitation
/api/exploitation/1
/api/exploitation/getbysongid/1
/api/exploitation/getbysongwriterid/1

我并不需要修改我的控制器操作这个新的路由配置在所有的工作。

I did not need to modify my controller actions to work with this new routing config at all.

如果你有多个PUT或POST操作,你可以在创建看着新航线如下:

If you had multiple PUT or POST actions you could the create new routes that looked as follows:

    config.Routes.MapHttpRoute(
        name: "DefaultGetApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional, action = "Put" },
        constraints: new { id = @"\d+", httpMethod = new HttpMethodConstraint(HttpMethod.Put) }
    );

    config.Routes.MapHttpRoute(
        name: "DefaultGetApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional, action = "Delete" },
        constraints: new { id = @"\d+", httpMethod = new HttpMethodConstraint(HttpMethod.Delete) }
    );

我希望这个答案可以帮助大家,因为这似乎是人有一个共同的问题。

I hope that this answer helps everyone as this seems to be a common issue that people are having.

这篇关于MVC API路由当多个GET操作是present的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆