传回多个服务uris

时间:2016-12-12 14:19:57

标签: asp.net-mvc asp.net-web-api

我创建了一个asp.net web api 2控制器来管理逻辑资产。像往常一样,帖子创建它并将uri返回给资产,删除删除它,但我有2个put来对资产执行单独的操作,所以我的代码看起来像:

public class Controller : ApiController
{        
    public IHttpActionResult Post(Stuff stuff)
    {
        var id = CreateNewStuff(stuff);

        return CreatedAtRoute("DefaultApi", new { id = this.id }, id);
    }   

    [HttpPut]
    public IHttpActionResult ActionA(int id, ActionAStuff stuff)
    {    
        // Perform action A

        return Ok();
    }   

    [HttpPut]
    public IHttpActionResult ActionB(int id, ActionBStuff stuff)
    {    
        // Perform action B

        return Ok();
    }   

    public IHttpActionResult Delete(int id)
    {
        // Delete the asset

        return Ok();
    }  
}

为了让路由理解这一点,我的路由规则是(包括默认规则):

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

这很有效,感觉就像系统通过操作巧妙地分离了代码,并确保系统拒绝我们不支持的操作请求。

问题在于,通过post创建资产的客户端不知道put(action)uris是什么,就像它通过post发回的位置头对资产uri所做的那样。如果我们将来更改uri表单,客户端会因为手动创建uris而中断。

从帖子返回多个服务点uris的正确方法是什么,或者只是更好地执行上述操作。

4 个答案:

答案 0 :(得分:1)

使用Route来区分操作。 例如:

[RoutePrefix("api/Admin")]
public class Controller : ApiController
{        
    [Route("ActionA")
    [HttpPut]
    public IHttpActionResult ActionA(int id, ActionAStuff stuff)
    {    
        // Perform action A

        return Ok();
    }   

    [Route("ActionB")
    [HttpPut]
    public IHttpActionResult ActionB(int id, ActionBStuff stuff)
    {    
        // Perform action B

        return Ok();
    }   

}

然后在webapiconfig.cs中启用属性路由

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API routes
            config.MapHttpAttributeRoutes();

            // Other Web API configuration not shown.
        }
    }

最后在您的客户端中,您可以区分下面的put URI: HTTP(S):/// API /管理/ ActionA

HTTP(S):/// API /管理/ ActionB

答案 1 :(得分:1)

应该为每种方法使用Route前缀进行区分。

[Route("ActionA")
[HttpPut]
public IHttpActionResult ActionA(int id, ActionAStuff stuff)
{    
    // Perform action A

    return Ok();
}

当我们使用来自config.Routes.MapHttpRoute的Route config配置路由时,它必须是正确的顺序,因为它添加到堆栈并从堆栈中使用。

一旦找到路由表中的任何条目,它就会尝试执行它。 因此,更好的方法是使用Route Prefix。

答案 2 :(得分:1)

您可以在POST方法的结果中添加link header

  1. 为了向IHttpActionResult类添加自定义标头,您可以定义扩展方法,例如:

    public static class HttpActionResultHeaderExtensions
    { 
        public static IHttpActionResult AddHeader(this IHttpActionResult action,
                                                  string headerName, 
                                                  params string[] headerValues)
        {
            return new HeaderActionResult(action, headerName, headerValues);
        }
    
        private class HeaderActionResult : IHttpActionResult
        {
            private readonly IHttpActionResult action;
    
            private readonly Tuple<string, IEnumerable<string>> header;
    
            public HeaderActionResult(IHttpActionResult action, 
                                      string headerName,
                                      IEnumerable<string> headerValues)
            {
                this.action = action;
    
                header = Tuple.Create(headerName, headerValues);
            }
    
            public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
            {
                var response = await action.ExecuteAsync(cancellationToken);
    
                response.Headers.Add(header.Item1, header.Item2);
    
                return response;
            }
        }
    }
    
  2. 添加路线属性:

    [System.Web.Http.RoutePrefixAttribute("api/stuff")]
    public class Controller : ApiController
    {           
        [System.Web.Http.HttpPut]
        [System.Web.Http.RouteAttribute("ActionA", Name = "ActionA")]
        public IHttpActionResult ActionA(int id, ActionAStuff stuff)
        {
            // your code            
        }
    
        [System.Web.Http.HttpPut]
        [System.Web.Http.RouteAttribute("ActionB", Name = "ActionB")]
        public IHttpActionResult ActionB(int id, ActionBStuff stuff)
        {
            // your code    
        }         
    }
    
  3. 扩展POST方法,将标题链接添加到结果中:

    public IHttpActionResult Post(Stuff stuff)
    {
        var id = CreateNewStuff(stuff);
    
        var actionALink = this.Url.Link("ActionA", new { id = id });
    
        var actionBLink = this.Url.Link("ActionB", new { id = id });
    
        return CreatedAtRoute("DefaultApi", new { id = id }, id)
            .AddHeader("Link", $"<{actionALink}>; rel=\"ActionA\"",     
                               $"<{actionBLink}>; rel=\"ActionB\"");        
    }
    
  4. 扩展配置:

    config.MapHttpAttributeRoutes();
    
    config.EnsureInitialized();
    

答案 3 :(得分:0)

Web API 2支持一种称为属性路由的新型路由。顾名思义,属性路由使用属性来定义路由。通过属性路由,您可以更好地控制Web API中的URI 您可以在Web Api中使用属性路由来解决您的问题。您的控制器操作应该是这样的,

 [Route("ActionA/{id}"]
  [HttpPut]
public IHttpActionResult ActionA(int id, ActionAStuff stuff)
{    
    // Perform action A

    return Ok();
}   



    [HttpPut]
   [Route("ActionB/{id}"]
    public IHttpActionResult ActionB(int id, ActionBStuff stuff)
       {    
            // Perform action B

            return Ok();
        }  

,您的HTTP请求为http://localhost:1317/ActionA/1http://localhost:1317/ActionB/1