Web Api属性路由与POST请求不匹配

时间:2019-07-16 22:10:42

标签: c# asp.net-mvc-5 asp.net-web-api2 asp.net-web-api-routing

我在控制器上的所有操作上都有属性路由(尽管定义了默认的常规路由)。我(我认为)尝试过是否使用[HttpPost]和是否使用[FromBody]的每种组合。

如果我尝试仅使用定义了控制器名称的属性...

[HttpPost]
[Route("Relationships")]
private async Task<IHttpActionResult> PostRelationship([FromBody]Relationship relationship)

Request URL:http://localhost:51599/api/Relationships
Request method:POST

...我得到405。

似乎正在使用属性路由-调试GetRouteData()显示了一个子路由,该子路由已解析为“ GetController”操作。

subroutes   {System.Web.Http.Routing.IHttpRouteData[1]} System.Collections.Generic.IEnumerable<System.Web.Http.Routing.IHttpRouteData> {System.Web.Http.Routing.IHttpRouteData[]}
-       [0] {System.Web.Http.Routing.HttpRouteData} System.Web.Http.Routing.IHttpRouteData {System.Web.Http.Routing.HttpRouteData}
-           Route   {System.Web.Http.Routing.HttpRoute} System.Web.Http.Routing.IHttpRoute {System.Web.Http.Routing.HttpRoute}
    +           Constraints Count = 0   System.Collections.Generic.IDictionary<string, object> {System.Web.Http.Routing.HttpRouteValueDictionary}
    -           DataTokens  Count = 2   System.Collections.Generic.IDictionary<string, object> {System.Web.Http.Routing.HttpRouteValueDictionary}
        -       [0] {[actions, System.Web.Http.Controllers.HttpActionDescriptor[]]} System.Collections.Generic.KeyValuePair<string, object>
                    Key "actions"   string
            -       Value   {System.Web.Http.Controllers.HttpActionDescriptor[1]}   object {System.Web.Http.Controllers.HttpActionDescriptor[]}
                -       [0] {System.Web.Http.Controllers.ReflectedHttpActionDescriptor} System.Web.Http.Controllers.HttpActionDescriptor {System.Web.Http.Controllers.ReflectedHttpActionDescriptor}
                    +       ActionBinding   {System.Web.Http.Controllers.HttpActionBinding} System.Web.Http.Controllers.HttpActionBinding
                            ActionName  "GetRelationships"  string

如果我尝试使用操作名称作为路线...

[HttpPost]
[Route("Relationships/PostRelationship")]
private async Task<IHttpActionResult> PostRelationship([FromBody]Relationship relationship)

http://localhost:51599/api/Relationships/PostRelationship
Request method:POST

...我得到404。

在这种情况下,它似乎陷入了默认的控制器-调试GetRouteData()表明它认为我正在提供“控制器”和“ id”。

routeData   {System.Web.Routing.RouteData}  System.Web.Routing.RouteData
+       DataTokens  {System.Web.Routing.RouteValueDictionary}   System.Web.Routing.RouteValueDictionary
+       Route   {System.Web.Http.WebHost.Routing.HttpWebRoute}  System.Web.Routing.RouteBase {System.Web.Http.WebHost.Routing.HttpWebRoute}
+       RouteHandler    {System.Web.Http.WebHost.HttpControllerRouteHandler}    System.Web.Routing.IRouteHandler {System.Web.Http.WebHost.HttpControllerRouteHandler}
-       Values  {System.Web.Routing.RouteValueDictionary}   System.Web.Routing.RouteValueDictionary
            Count   2   int
    -       Keys    Count = 2   System.Collections.Generic.Dictionary<string, object>.KeyCollection
                [0] "controller"    string
                [1] "id"    string  
    -       Values  Count = 2   System.Collections.Generic.Dictionary<string, object>.ValueCollection
                [0] "Relationships" object {string}
                [1] "PostRelationship"  object {string}

这是整个控制器:

    [RoutePrefix("api")]
    public class RelationshipsController : ApiController
    {
        private CMDBContext db = new CMDBContext();

        [Route("Relationships")]
        public IQueryable<Relationship> GetRelationships()
        {
            return db.Relationships;
        }

        [Route("Relationships/{id:int}")]
        private async Task<Relationship> GetRelationship(int id)
        {
            Relationship relationship = await db.Relationships.FindAsync(id);
            if (relationship == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            return relationship;
        }

        [HttpPost]
        [Route("Relationships/PostRelationship")]
        private async Task<IHttpActionResult> PostRelationship([FromBody]Relationship relationship)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            db.Relationships.Add(relationship);
            await db.SaveChangesAsync();

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

        [HttpGet]
        [Route("Relationships/RelTypes")]
        public Dictionary<string, string> RelTypes()  // returns a list of available Relationship types
        {
            var RelTypesDict = new Dictionary<string, string>();
            foreach (var type in Relationship.RelTypes)
            {
                RelTypesDict.Add(type, Regex.Replace(type, @"(\B[A-Z]+?(?=[A-Z][^A-Z])|\B[A-Z]+?(?=[^A-Z]))", " $1")); // expands camel case with spaces for display
            }
            return RelTypesDict;
        }

        private bool RelationshipExists(int id)
        {
            return db.Relationships.Count(e => e.Id == id) > 0;
        }
    }

和WebApiConfig:

// Web API routes
config.MapHttpAttributeRoutes();

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

和我用来调用它的AJAX:

async function postEdge() {  // persists a new edge to data store from form
    var ItemLeftId = $('#ItemLeftId').val();
    var ItemRightId = $('#ItemRightId').val();
    var RelType = $('#ddlRelType').val();
    var Description = $('#Description').val();
    $.ajax({
        method: "POST",
        contentType: "application/json; charset=utf-8",
        url: '/api/Relationships',
        data: {
            Id: 0,  // TESTING
            ItemLeftId: ItemLeftId,
            ItemRightId: ItemRightId,
            RelType: RelType,
            Description: Description,
        }, 

1 个答案:

答案 0 :(得分:0)

我发现了-如果您在上方查看,GetRelationship和PostRelationship方法都设置为Private。这是我从另一个基类继承Relationship并使用其他公共方法进行区分时剩下的。愚蠢的错误,但是如果症状不是那么奇怪/无关的话,就会更容易发现。