前言
上一节已经设计好了问卷系统的数据模型,同时提供了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
即可。例如GetString
、SetString
等。
我在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,判断存储的答案的作答者,是否为当前用户。