Web API 2.2, Inherited Controller with Route Overrides (Is this possible)?

瘦欲@ 提交于 2020-01-16 05:17:30

问题


So I have a generic base controller implementing CRUD, which derives from 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();
    }

}

And have allowed controller inheritance via a CustomDirectRouteProvider as such:

config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());

Where my CustomDirectRouteProvider is:

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

And this all works beautifully, until I want to override methods like POST. As an example:

[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
    }

}

At which point I get the error:

"Multiple actions were found that match the request"

So my question is, how can I override the route itself? I basically want my new POST to take precedence over the generic one. I thought by virtue of the generic route/method being hidden that this would just work, but alas I was incorrect in my thinking.


回答1:


Was able to recreate your issue, and through a process of trial and error was able to get it to work by making GenericController an abstract class

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);
    }
}

and removing the attributes on the inherited action of the DerivedController as they matched the inherited class

[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
    }
}


来源:https://stackoverflow.com/questions/36012524/web-api-2-2-inherited-controller-with-route-overrides-is-this-possible

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!