【问题标题】:Web API 2.2, Inherited Controller with Route Overrides (Is this possible)?Web API 2.2,带有路由覆盖的继承控制器(这可能吗)?
【发布时间】:2016-03-15 13:20:19
【问题描述】:

所以我有一个实现 CRUD 的通用基本控制器,它派生自 APIController

public class GenericController<TEntity> : ApiController where TEntity : class {

    private readonly GenericModel<TEntity> _model;

    public IModel Model {
        get { return _model; }
    }

    public GenericController(IGenericModel<TEntity> model) {
        _model = (GenericModel<TEntity>)model;
    }

    [HttpPost, Route]
    public IHttpActionResult Post(TEntity entity) {
        TEntity newEntity = _model.Create(entity);
        String urlLink = $"{Request.RequestUri}{RequestContext.VirtualPathRoot}{((IGenericEntity)newEntity).ID}";
        return Created(urlLink, newEntity);
    }

    [HttpGet, Route]
    public IHttpActionResult GetList() {
        return Ok(_model.ReadList());
    }

    [HttpGet, Route("{ID:int}")]
    public IHttpActionResult Get(Int64 ID) {
        return Ok(_model.Read(ID));
    }

    [HttpPut, Route]
    public IHttpActionResult Put(TEntity entity) {
        _model.Update(entity);
        return Ok();
    }

    [HttpDelete, Route("{ID:int}")]
    public IHttpActionResult Delete(Int64 ID) {
        _model.Delete(ID);
        return Ok();
    }

}

并允许通过CustomDirectRouteProvider 继承控制器:

config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());

我的 CustomDirectRouteProvider 在哪里:

public class CustomDirectRouteProvider : DefaultDirectRouteProvider {
    protected override IReadOnlyList<IDirectRouteFactory> GetActionRouteFactories(HttpActionDescriptor actionDescriptor) {
        return actionDescriptor.GetCustomAttributes<IDirectRouteFactory> (inherit: true);
    }
}

这一切都很好,直到我想覆盖像 POST 这样的方法。举个例子:

[RoutePrefix(@"api/Test")]
public class DerivedController : GenericController<ConcreteEntity> {

    public DerivedController (IGenericModel<ConcreteEntity> model) : base(model) {
    }

    [HttpPost, Route]
    public new IHttpActionResult Post(ConcreteEntity entity) {
        //New Post Functionality Here
    }

}

此时我得到了错误:

"Multiple actions were found that match the request"

所以我的问题是,我怎样才能覆盖路线本身?我基本上希望我的新 POST 优先于通用的。我认为由于隐藏了通用路线/方法,这将起作用,但可惜我的想法不正确。

【问题讨论】:

    标签: c# inheritance controller asp.net-web-api2 asp.net-web-api-routing


    【解决方案1】:

    能够重新创建您的问题,并且通过反复试验的过程能够通过将GenericController 设为抽象类来使其正常工作

    public abstract class GenericController<TEntity> : ApiController where TEntity : class {
    
        [HttpPost, Route]
        public virtual IHttpActionResult Post(TEntity entity) {
            TEntity newEntity = _model.Create(entity);
            String urlLink = $"{Request.RequestUri}{RequestContext.VirtualPathRoot}{((IGenericEntity)newEntity).ID}";
            return Created(urlLink, newEntity);
        }
    }
    

    并删除 DerivedController 的继承操作上的属性,因为它们与继承的类匹配

    [RoutePrefix(@"api/Test")]
    public class DerivedController : GenericController<ConcreteEntity> {
    
        public DerivedController (IGenericModel<ConcreteEntity> model) : base(model) {
        }
    
        public override IHttpActionResult Post(ConcreteEntity entity) {
            //New Post Functionality Here
        }
    }
    

    【讨论】:

    • 这有帮助,谢谢。我仍然需要能够实例化 GenericController,所以我创建了一个抽象 BaseController,然后从中派生了我的 GenericController,最后从 GenericController 派生了我的 DerivedController。所有部件都按预期安装和工作。 :)
    • 有趣的是,我也测试了该模型,但没有包含它,因为我认为它超出了您的帖子范围。不知道你必须实例化。
    猜你喜欢
    • 1970-01-01
    • 2015-02-27
    • 2013-12-19
    • 1970-01-01
    • 1970-01-01
    • 2016-07-12
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    相关资源
    最近更新 更多