2016-10-05 44 views
1

我想在aspnetcore 1.0.1中实现一个基本的REST控制器(类似NancyFx的灵感),感觉这应该是可以用这样的可组合框架实现的东西,然而,我只是不能正确地做对。谷歌foo今天显然很弱!继承来自抽象REST控制器的http动词属性

我有以下基本控制器(显然还没有完全实现)...

[Route("api/[controller]")] 
public abstract class RestApiController<T> : Controller 
{ 
    protected abstract Func<int, Task<T>> Get { get; } 
    protected abstract Func<Task<IEnumerable<T>>> List { get; } 

    [HttpGet()] 
    protected virtual async Task<IEnumerable<T>> OnList() 
    { 
     if (this.List == null) 
     { 
      this.NotFound(); 
     } 

     return await this.List.Invoke(); 
    } 

    [HttpGet("{id:int}")] 
    protected virtual async Task<T> OnGet(int id) 
    { 
     if (this.Get == null) 
     { 
      this.NotFound(); 
     } 

     return await this.Get.Invoke(id); 
    } 
} 

这是由实际控制人做的工作继承...

public class ArticleSummariesController : RestApiController<ArticleExtension> 
{ 
    private readonly ArticleManager articleManager; 

    protected override Func<int, Task<ArticleExtension>> Get => null; 
    protected override Func<Task<IEnumerable<ArticleExtension>>> List => this.ListAll; 

    public ArticleSummariesController(ArticleManager articleManager) 
    { 
     this.articleManager = articleManager; 
    } 

    private async Task<IEnumerable<ArticleExtension>> ListAll() 
    { 
     return await this.articleManager.GetAllAsync(); 
    } 

} 

的想法是基地控制人员将负责处理实际的请求,但将责任委托给其子女提供和操作数据。这样我们就可以确保REST在请求中一致,但将来自控制器的域逻辑松散地耦合到充当门面并采取存储库和应用业务逻辑的“管理者”。

到目前为止,代码的问题是基类上的HttpGet()属性不会为子类生成路由。虽然基类的控制器路由属性被继承(如docs所述)。

回答

0

再一次,答案是盯着我的脸!我有父方法声明为保护不公开,所以他们不认为合格的行动!

阅读更多关于应用模型here之后这一切变得清晰......

ActionModel - 表示控制器的动作。 这个类的实例是为控制器上的每个符合条件的操作而创建的。有 是一个方法成为一个行动的多个要求,如 是公开的,非抽象的,而不是从对象继承。

因此,修改后的代码下面的作品...

[Route("api/[controller]")] 
public abstract class RestApiController<T> : Controller 
{ 
    protected abstract Func<int, Task<T>> Get { get; } 
    protected abstract Func<Task<IEnumerable<T>>> List { get; } 

    [HttpGet()] 
    public virtual async Task<IEnumerable<T>> OnList() 
    { 
     if (this.List == null) 
     { 
      this.NotFound(); 
     } 

     return await this.List.Invoke(); 
    } 

    [HttpGet("{id:int}")] 
    public virtual async Task<T> OnGet(int id) 
    { 
     if (this.Get == null) 
     { 
      this.NotFound(); 
     } 

     return await this.Get.Invoke(id); 
    } 
} 

public class ArticleSummariesController : RestApiController<ArticleExtension> 
{ 
    private readonly ArticleManager articleManager; 

    protected override Func<int, Task<ArticleExtension>> Get => null; 
    protected override Func<Task<IEnumerable<ArticleExtension>>> List => this.ListAll; 

    public ArticleSummariesController(ArticleManager articleManager) 
    { 
     this.articleManager = articleManager; 
    } 

    private async Task<IEnumerable<ArticleExtension>> ListAll() 
    { 
     return await this.articleManager.GetAllAsync(); 
    } 

} 
0

我可能是错的,但我立即假定您需要基类或子类上的RouteAttribute。例如:

[Route("api/[controller]")] 
public abstract class RestApiController<T> : Controller 
{ 
    protected abstract Func<int, Task<T>> Get { get; } 
    protected abstract Func<Task<IEnumerable<T>>> List { get; } 

    [HttpGet, Route("list")] 
    protected virtual async Task<IEnumerable<T>> OnList() 
    { 
     if (this.List == null) 
     { 
      this.NotFound(); 
     } 

     return await this.List.Invoke(); 
    } 

    [HttpGet, Route("get/{id:int}")] 
    protected virtual async Task<T> OnGet(int id) 
    { 
     if (this.Get == null) 
     { 
      this.NotFound(); 
     } 

     return await this.Get.Invoke(id); 
    } 
} 
+0

与路由属性的问题是我就失去了REST像URL。例如。 GET api/articlesummaries而不是api/arriclesummaries/list。虽然路由属性确实继承了http动词属性,但它不会 –