动态.NET WebAPI 5.2控制器基于一些抽象基类型

时间:2014-08-18 03:44:44

标签: c# rest asp.net-web-api reflection.emit

假设REST和数据访问交互在某种程度上是标准的,我希望能够创建一个抽象类型来表示实体对象,以便从REST客户端(例如浏览器中的JavaScript)来回传递到持久层编写/注册/路由一堆不同的WebAPI控制器。

如何创建一个控制器基类型实现来管理多个不同实体类型REST交互的持久性?即如何使用WebAPI进行此操作?

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Web;
using System.Web.Http;

namespace DynamicEntityApiControllers
{
    /// <summary>
    /// 
    /// </summary>
    public class EntityController<T> : ApiController
        where T : EntityObject
    {
        private readonly IDaoProvider daoProvider;

        /// <summary>
        /// Initializes a new instance of the <see cref="EntityController{T}"/> class.
        /// </summary>
        /// <param name="daoProvider">The DAO provider.</param>
        protected EntityController(IDaoProvider daoProvider)
        {
            this.daoProvider = daoProvider;
        }

        /// <summary>
        /// Gets the name of the collection.
        /// </summary>
        /// <value>
        /// The name of the collection.
        /// </value>
        protected string CollectionName
        {
            get
            {
                return (string)this.RequestContext.RouteData.Values["controller"];
            }
        }

        /// <summary>
        /// Gets the specified entity by key from the collection.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        public T Get(string key)
        {            
            return this.daoProvider.Output<T>(this.CollectionName, key).Data;
        }

        /// <summary>
        /// Creates or updates the specified entity by key in the collection.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="updating">The updating.</param>
        /// <returns></returns>
        public T Put(string key, [FromBody] T updating)
        {
            var daoObject = DaoEntity.Create(this.CollectionName, key, updating);
            return this.daoProvider.Input<T>(daoObject).Data;
        }

        /// <summary>
        /// Creates or Updates the collection specified entirely.
        /// </summary>
        /// <param name="replacingCollection">The replacing collection.</param>
        /// <returns></returns>
        public IEnumerable<T> Put([FromBody] IEnumerable<T> replacingCollection)
        {
            return this.daoProvider.Input<T>(replacingCollection
                            .Select(o => DaoEntity.Create(this.CollectionName, o)));
        }

        /// <summary>
        /// creates a new entity in the specified collection.
        /// </summary>
        /// <param name="creating">The creating.</param>
        /// <returns></returns>
        public T Post([FromBody] T creating)
        {
            var daoEntity = DaoEntity.Create(this.CollectionName, creating);
            return this.daoProvider.Input(daoEntity).Data;
        }

        /// <summary>
        /// Deletes the specified entity by key from the collection.
        /// </summary>
        /// <param name="key">The key.</param>
        public void Delete(string key)
        {
            this.daoProvider.Delete(this.CollectionName, key);
        }
    }
}

JavaScript客户端必须看起来像这样:

$.ajax({url: '/Book', method: 'POST', data: {title: 'This StackOverflow Post', pageCount: '124' })
    .done(function(data) {
      $.get('/Book/'+data.Key).done(function(data) { 
        // this will return the book you just created
        console.dir(data);
      })
    })

    $.ajax({url: '/Book', method: 'POST', data: {title: 'Some other StackOverflow Post', pageCount: '236' })
    .done(function(data) {
      $.get('/Magazine/'+data.Key).done(function(data) { 
        // this will return 404 status code because you're asking for the book's key 
        // in the Magazines collection
        console.dir(data);
      })
    })

1 个答案:

答案 0 :(得分:0)

示例解决方案在这里有一堆TODO(就像使用ETag标题,if-match等实际做的那样......)但是我必须在StackOverflow上进行大约4次查询才能找到这些位。

先决条件:

  • Autofac(IoC)与WebAPI的集成
  • WebAPI Controller Location / DependencyResolver(这些不一样)
  • C#Generics
  • 反思IL Emitting
  • 非常简单的REST理解和ETag是什么。

GIT source folder

简要地说,这是逻辑:

  • 创建基本类型(entityobject)
  • 通过反射在IoC注册时识别所有这些实体(实施者负责指定要扫描的组件)
  • 通过IL Emitting创建抽象类EntityController的具体实现
    • 告诉SupportsDynamicControllerTypeResolver这些动态类型
  • IDaoProvider实施是&#34;持久性&#34;层。在这里实现你的持久性逻辑..在这个例子中,使用了一个内存字典。

发出请求时会发生什么:   - 询问RouteTable(找到{controller} / {key}路由,这是一个HttpRoute   - 控制器名称与EntityObject实现者名称减去实体匹配。即BookEntity =&gt; BookController的   - 这里需要SupportsDynamicControllerTypeResolver来获取动态程序集类型作为WebApi尝试激活的有效候选者。   - HTTP Put / Get / Post / Delete方法找到正确的方法   - 持久层完成剩下的工作