从抽象REST控制器继承http谓词属性

时间:2016-10-05 17:50:33

标签: c# rest asp.net-core

我正在尝试在aspnetcore 1.0.1中实现一个基本的REST控制器(有点来自NancyFx),感觉这应该是可以通过这样一个可组合的框架实现的,但是,我只是不能正确。今天google foo对我来说显然很弱!

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

[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一致性,但是将域逻辑从控制器松散地耦合到管理器&#34;充当外观并采用存储库并应用业务逻辑。

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

2 个答案:

答案 0 :(得分: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);
    }
}

答案 1 :(得分:0)

然而,答案就是盯着我的脸!我将父方法声明为受保护而不公开,因此它们不被视为符合条件的操作!

在阅读了有关ApplicationModel here的更多内容后,一切都变得清晰......

  

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

所以下面的修改后的代码可以运行......

$.fn.facebookEvents = function(options){
    var fbEvents = 'https://graph.facebook.com/'+options.id+'/events/?access_token='+options.access_token+'&since=now&limit=500';
    var events = [];
    var deferred=$.Deferred();
    var promises=[];
    var done=false;

    $.when(deferred).then(function(events) {
      console.log(events);
    });

    $.getJSON(fbEvents).done(function(json){
        $.each(json.data, function(){
            promises.push($.getJSON('https://graph.facebook.com/'+this.id+'/?access_token='+options.access_token).done(function(jsonData){ 
                events.push(jsonData);
                var completed=promises.filter(function(element) { return element.state=='pending' }).length==0;
                if(done&&completed) {
                  deferred.resolve(events);
                }
            }));
        });
        done=true;
    });
};