【问题标题】:Asp.Net Web Api 2 Strange Routing BehaviourAsp.Net Web Api 2 奇怪的路由行为
【发布时间】:2014-08-27 12:37:33
【问题描述】:

我正在使用 vs2012 并使用“ASP.net Web Api 2”模板开始了一个新项目。完成编码并开始测试系统。我观察到路由的奇怪行为。如:

这是我的路线:

config.Routes.MapHttpRoute(
    name: "personRoute",
    routeTemplate: "api/px/{action}/{personid:Guid}",
    defaults: new { controller = "px", personid = RouteParameter.Optional }
);

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

这是我的控制器:

public class PxController : ApiController {

    private Configuration.DatabaseContext dbctx = new Configuration.DatabaseContext();

    [HttpGet]
    public IEnumerable<Models.Person> GetAll() {
        return dbctx.Persons.ToArray();
    }

    [ActionName( "op" )]
    [HttpGet]
    public Models.Person ById( Guid personid ) {
        var data = dbctx.Persons.FirstOrDefault( e => e.PersonId == personid );

        if (data == null) {
            throw new HttpResponseException( HttpStatusCode.NotFound );
        }

        return data;
    }

    [ActionName( "op" )]
    [HttpPost]
    public void Insert( [FromBody] Models.Person newPerson ) {
        dbctx.Persons.Add( newPerson );           
        dbctx.SaveChanges();  
    }

    [ActionName( "op" )]
    [HttpPut]
    public void Update( [FromBody]Models.Person eperson ) {          
        var data = dbctx.Persons.FirstOrDefault( e => e.PersonId == eperson.PersonId );

        if (data == null) {
            throw new HttpResponseException( HttpStatusCode.NotFound );
        }

        dbctx.Entry( eperson ).State = System.Data.Entity.EntityState.Modified;
        dbctx.SaveChanges();
    }

    [ActionName( "op" )]
    [HttpDelete]
    public void DeleteById( Guid personid ) {
        var data = dbctx.Persons.FirstOrDefault( e => e.PersonId == personid );

        if (data == null) {
            throw new HttpResponseException( HttpStatusCode.NotFound );
        }

        dbctx.Entry( data ).State = System.Data.Entity.EntityState.Deleted;
        dbctx.SaveChanges();
    }

    #region |:.Extended Queries.:|
    [HttpGet]
    public IEnumerable<RemoteProperty> Properties( Guid personid ) {
        var data = from n in dbctx.RemoteProperties
                   where n.PersonId == personid && n.ParentId == null
                   orderby n.PropertyType.Name
                   select n;

        if (data == null)
            throw new HttpResponseException( HttpStatusCode.NotFound );

        foreach (var rp in data) {
            rp.Details = dbctx.RemoteProperties.SqlQuery( "SELECT * FROM properties WHERE parentid = @parid" ).ToArray();
        }

        return data.ToArray();
    }

    [HttpGet]
    public IEnumerable<Relation> Relations( Guid personid ) {
        var data = from n in dbctx.Relations
                   where n.PersonId == personid
                   select n;

        if (data == null)
            throw new HttpResponseException( HttpStatusCode.NotFound );

        return data.ToArray();
    }
    #endregion

    [NonAction]
    protected override void Dispose( bool disposing ) {

        if (dbctx != null && dbctx is IDisposable) {
            dbctx.Dispose();
        }

        base.Dispose( disposing );
    }

}

这些是查询的 Fiddler 输出:

http://localhost:49318/api/px/GetAll
/* Works as expected */

http://localhost:49318/api/px/op/dfc737ca-312c-e411-ae3c-78843ccba6ef
/* The requested resource does not support http method 'GET'. */

http://localhost:49318/api/px/op?personid=dfc737ca-312c-e411-ae3c-78843ccba6ef
/* Returns the data with personid, but why the above query fails? */

http://localhost:49318/api/px/properties?personid=dfc737ca-312c-e411-ae3c-78843ccba6ef
/* Returns the data with personid */

http://localhost:49318/api/px/properties/dfc737ca-312c-e411-ae3c-78843ccba6ef
/* No action was found on the controller 'Px' that matches the request */

我的问题是这种行为的原因是什么?我也不能使用类似的路线(因为它们不起作用):

"api/{controller}/{personid}/{action}"

【问题讨论】:

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


    【解决方案1】:

    尝试使用 [Route] 属性而不是 [Action] 属性。

    在我的控制器上,我已成功使用以下内容:

    [RoutePrefix("api/Demo")] // Sets the base route for actions in this controller
    public class DemoController : ApiController
    {
        [HttpGet]
        [Route("DemoAction")] // This makes this function map to route http://site/api/Demo/DemoAction
        public IHttpActionResult PerformComplexApiAction(int id)
        {
            ...
    

    [RoutePrefix] 可以省略,完整的路由可以在每个函数的单独 [Route] 条目中提供。

    【讨论】:

    • 如果我喜欢 [Route("api/px/oper/{pid:Guid}")] 并从 ById(Guid personid) 中删除 [ActionName] 到 ById(Guid pid),它可以工作。但为什么它与路线不匹配?我也没有成功使用 Route Debugger。它甚至没有工作。
    【解决方案2】:

    好的。通过检查整个项目并应用更改(如下所列),我成功地使其工作。所以这就是我所做的:

    • 我使用的是 VS2012 和 web.api 模板 2.0 和 .net 4.5。
    • VS2012 不支持 web.api 2.0,但有更新。
    • 我检查了所有的 DLL 文件引用,发现其中一些有错误的版本。
    • 因此我删除了所有引用。
    • 我从 NuGet 获取 Web.api 2.2 并安装了所有 DLL 文件
    • 瞧。它开始起作用了。

    为了调试项目,MS 提供了一个“跟踪”程序集,我使用了它。它将跟踪消息发送到输出窗口,路由时正在做什么等等。所以我能够看到正在发生的事情。 VS 2012 更新不足以使其工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-25
      • 2011-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-23
      相关资源
      最近更新 更多