简易问卷系统(二)接口设计

分类: 开发笔记

前言

上一节已经设计好了问卷系统的数据模型,同时提供了C#和TypeScript中对模型的定义。

在本节中,我将会设计并实现RESTful API。

前端SPA将直接通过JavaScript的Fetch API来请求后端。

  • 怎么在设计阶段,就想到有哪些API需要设计并实现?
  • 显然,这份API边做边改了很多次了。

接口设计

ApiQuestionaireController

路由 功能 解释
GET api/Questionaire 获取全部问卷 获取全部问卷的安全内容(SafeContent),按更新时间降序排列。
GET api/Questionaire/title/{title} 验证问卷标题,获取错误信息 用于标题重复检测。
GET api/Questionaire/{id} 获取指定问卷 获取指定ID的问卷的安全内容(SafeContent)。
GET api/Questionaire/check/{id}/{guid} 检查问卷密钥 检查指定ID的问卷的GUID是否与提供的GUID吻合。
GET api/Questionaire/questions/{id} 获取问卷的问题 获取指定ID的问卷的全部问题。
GET api/Questionaire/answers/{id}/{questionId}/{guid} 获取问卷指定题目的答案 获取指定ID的问卷的指定Question ID的问题的全部答案,需要验证问卷的GUID。
PUT api/Questionaire/{id}/{guid}

参数:Questionaire
修改问卷 修改指定ID的问卷为提供的参数,需要验证问卷的GUID。
POST api/Questionaire

参数:Questionaire
新建问卷 按提供的参数新建问卷,返回包含ID、GUID的建好的问卷。(唯一获得GUID的方法)
DELETE api/Questionaire/{id}/{guid} 删除问卷 删除指定ID的问卷,需要验证问卷的GUID。

ApiQuestionController

这里有一个结构体,用于PUT参数传递:

public struct QuestionContent 
{
    public int ID { get; set; }
    public string Content { get; set; }
}
路由 功能 解释
GET api/Question/{id} 获取指定问题 获取指定ID的问题。
PUT api/Question/{id}/{guid}

参数:QuestionContent
修改指定问题的内容 根据参数修改指定ID的问题的内容,需要验证问题所属问卷的GUID。
GET api/Question/move/{id}/{dstOrder}/{guid} 移动问题次序 移动指定ID的问题的次序到指定次序,需要验证问题所属问卷的GUID。
POST api/Question/{guid}

参数:Question
新建问题 按照给定参数,新建问卷的一个问题,需要验证问卷的GUID。
DELETE api/Question/{id}/{guid} 删除指定问题 删除指定ID的问题,需要验证问题所属问卷的GUID。
PUT api/Question/saveAll/{guid}

参数:List<QuestionContent>
保存全部问题 保存参数中包含的全部问题,需要验证问题所属问卷的GUID。

ApiQuestionTypeController

路由 功能 解释
GET api/QuestionType 获取全部题型 获取全部题型的{ ID, Name, CreatedAt,UpdatedAt },按更新时间降序排列。
GET api/QuestionType/name/{name} 验证题型名称,获取错误信息 用于题型名称重复检测。
GET api/QuestionType/{id} 获取指定题型 获取指定ID的题型的安全内容(SafeContent)。
POST api/QuestionType

参数:QuestionType
新建题型 按照给定参数,新建题型。

ApiAnswerController

路由 功能 解释
GET api/Answer 获取当前用户的全部答案 获取当前用户(根据Session)的全部答案的安全内容(SafeContent)。
GET api/Answer/{questionId} 获取指定问题的答案 获取当前用户指定ID的问题的答案,需验证Session是否相符(作答者是否为当前用户)。
POST api/Answer

参数:Answer
新建答案 按照给定参数,保存答案。

在 ASP.NET Core 中使用Session

在Controller类中,直接操作HttpContext.Session即可。例如GetStringSetString等。

我在ApiAnswerController类中,为了给当前用户一个唯一标识,设置了一个只读属性:

private string SessionID
{
    get
    {
        if (HttpContext.Session == null)
        {
            // 不支持Session
            return null;
        }
        else
        {
            // 获取当前SessionID
            var id = HttpContext.Session.GetString("SessionID");
            if (id != null)
            {
                return id;
            }
            else
            {
                // 为当前Session分配新的SessionID
                id = Guid.NewGuid().ToString() + DateTime.Now.ToString();
                HttpContext.Session.SetString("SessionID", id);
                return id;
            }
        }
    }
}

然后存储用户作答的答案的时候,即可同时存储SessionID来区分作答的用户。也可以在获取答案的时候比较SessionID,判断存储的答案的作答者,是否为当前用户。