1

所以我有一個通用的基礎控制器實現CRUD,它來自APIControllerWeb API 2.2,帶路由覆蓋的繼承控制器(這是可能的)?

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優先於通用的POST。我想通過隱藏的通用路線/方法,這只是工作,但唉,我的想法是不正確的。

回答

3

之所以能夠重現您的問題,並通過試錯的過程中能夠得到它通過繼承的作用使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 
    } 
} 
+0

這幫助,謝謝。 我仍然需要能夠實例化GenericController,所以我創建了一個抽象BaseController,然後派生出我的GenericController,並從GenericController派生出我的DerivedController。所有的作品都符合預期。 :) – Xorcist

+0

這是個好消息。樂意效勞。 – Nkosi

+0

足夠有趣我已經測試過該模型,但沒有包含它,因爲它雖然超出了您的帖子範圍。不知道你必須實例化。 – Nkosi