在软件项目中,尤其是在后端 (BE) 项目中,响应模型起着极其关键的作用。后端项目与其他服务和应用程序持续通信,BE 返回的响应模型由这些服务和应用程序使用。
因此,让响应模型遵守特定标准对于项目的开发和可持续性非常重要。
响应模型增强了 API 提供的服务的可用性和清晰度。它们定义返回给用户的数据的结构和格式。这允许前端或服务开发人员依赖从后端返回的数据格式,使他们能够更有效地创建与这些数据相关的业务流程。
例如,在电子商务网站上检索产品详细信息的 API 的响应模型可能如下所示:
{
"id": 123,
"name": "Ürün Adı",
"price": 49.99,
"description": "Ürün açıklaması",
"category": {
"id": 1,
"name": "Kategori Adı"
},
"stock": 20
}
此响应模型清楚地向前端开发人员展示了从后端返回的数据的结构和预期字段。因此,前端开发人员可以使用此数据模型创建产品详细信息页面。虽然上述模型可用,但为了提高软件效率而标准化响应模型具有许多优点。
在我的项目中,我使用了四种不同的响应模型:
此外,我将它们分类为:
现在,我们来看看每个响应模型及其用法示例。
在软件项目中标准化响应模型的关键步骤之一是确保所有响应模型具有共同的特征。为了实现这一点,我从特定接口派生响应模型。
这样的接口可以确保响应模型的一致性和兼容性。
下面是我在项目中使用的 IRequestResult 接口。
public interface IRequestResult
{
bool Success { get; }
string Message { get; }
}
bool Success { get; }
此属性确定操作是否成功。
string Message { get; }
此属性提供有关操作结果的详细信息。
下面是实现 IRequestResult 接口的 RequestResult 类。我们稍后将看到的所有成功或错误响应模型都将继承自此类。
让我解释一下代码的功能及其工作原理:
public class RequestResult : IRequestResult
{
// İki parametreli constructor. Bu constructor, Success ve Message özelliklerini ayarlamak için kullanılır.
public RequestResult(bool success, string message) : this(success)
{
Message = message;
}
// Tek parametreli constructor. Bu constructor, sadece Success özelliğini ayarlamak için kullanılır.
public RequestResult(bool success)
{
Success = success;
}
// Success özelliği, işlemin başarılı olup olmadığını belirtir.
public bool Success { get; }
// Message özelliği, işlemin sonucu hakkında bilgi verir.
public string Message { get; }
}
RequestResult 类实现 IRequestResult 接口。因此,它具有 Success 和 Message 属性。
我从 RequestResult 类派生了以下 SuccessRequestResult 和 ErrorRequestResult 类。
public class SuccessRequestResult : RequestResult
{
public SuccessRequestResult(string message) : base(true, message)
{
}
public SuccessRequestResult() : base(true)
{
}
}
让我简单解释一下这门课:
SuccessRequestResult(string message):包含成功操作的消息的构造函数。它使用 true 调用 RequestResult 类的构造函数,并使用表达式 'base(true, message)' 调用 message 参数。
SuccessRequestResult() 的没有成功操作消息的构造函数。它使用表达式 'base(true)' 调用仅包含 true 参数的 RequestResult 类的构造函数。
public class ErrorRequestResult : RequestResult
{
public ErrorRequestResult(string message) : base(false, message)
{
}
public ErrorRequestResult() : base(false)
{
}
}
让我简单解释一下这门课:
ErrorRequestResult(string message):包含错误操作消息的构造函数。它使用 false 调用 RequestResult 类的构造函数,使用表达式 'base(false, message)' 调用 message 参数。
ErrorRequestResult():没有错误操作消息的构造函数。它使用表达式 'base(false)' 调用仅包含 false 参数的 RequestResult 类的构造函数。
到目前为止,我们已经检查了不包含数据的响应模型。总之,我们为成功和不成功的请求创建了两种不同的响应模型,这些模型源自基本响应模型。
那么,如果我们需要在响应模型中返回额外的数据以及 status 和 message,我们应该怎么做呢?
在我的应用程序中,我使用下面解释的结构。
以下 IRequestDataResult<T> 接口派生自 IRequestResult 接口,表示包含泛型数据类型的响应模型。
public interface IRequestDataResult<out T> : IRequestResult
{
T Data { get; }
}
让我简单解释一下这个接口:
< T >: 该接口使用泛型类型 T 定义。out 关键字指示类型 T 是协变的,这意味着它只能用作返回类型。这允许将较宽的类型用作较窄的类型。
IRequestDataResult<T> 中: 此接口扩展了 IRequestResult 接口。除了 IRequestResult 接口中的 Success 和 Message 属性外,它还包括一个名为 Data 的属性。
T Data { get; }: 此属性表示作为请求结果返回的数据。类型 T 是根据使用接口的上下文确定的,由于其通用结构而提供了灵活性。
由于它是使用 get 访问器定义的,因此不能从外部设置此属性,并且是只读的。
以下 RequestDataResult<T> 类是从 RequestResult 类派生的泛型响应模型,并实现 IRequestDataResult<T> 接口。
public class RequestDataResult<T> : RequestResult, IRequestDataResult<T>
{
public RequestDataResult(T data, bool success, string message) : base(success, message)
{
Data = data;
}
public RequestDataResult(T data, bool success) : base(success)
{
Data = data;
}
public T Data { get; }
}
让我简单解释一下这门课:
RequestDataResult<T> 是从 RequestResult 类派生的,因此,它具有 Success 和 Message 属性。RequestDataResult<T> 类是一个全面的响应模型,它包括成功和消息信息(Success、Message)以及返回的数据 (Data)。
由于其通用结构,它可以与任何数据类型一起使用,提供灵活且可重用的设计。通过组合 RequestResult 和 IRequestDataResult<T> 的结构,它确保了响应模型的一致性和标准化。
以下 SuccessRequestDataResult<T> 类派生自 RequestDataResult<T> 类,是用于成功案例的通用响应模型。
public class SuccessRequestDataResult<T> : RequestDataResult<T>
{
public SuccessRequestDataResult(T data, string message) : base(data, true, message)
{
}
public SuccessRequestDataResult(T data) : base(data, true)
{
}
public SuccessRequestDataResult(string message) : base(default, true, message)
{
}
public SuccessRequestDataResult() : base(default, true)
{
}
}
让我简单解释一下这门课:
此类为成功操作提供自定义的响应模型。Success 属性始终设置为 true。它提供了不同的构造函数,其中包括用于成功操作的数据和消息的组合。
由于其通用结构,它可以与任何数据类型一起使用,提供灵活且可重用的设计。
以下 ErrorRequestDataResult<T> 类派生自 RequestDataResult<T> 类,是用于错误情况的通用响应模型。
public class ErrorRequestDataResult<T> : RequestDataResult<T>
{
public ErrorRequestDataResult(T data, string message) : base(data, false, message)
{
}
public ErrorRequestDataResult(T data) : base(data, false)
{
}
public ErrorRequestDataResult(string message) : base(default, false, message)
{
}
public ErrorRequestDataResult() : base(default, false)
{
}
}
让我简单解释一下这门课:
ErrorRequestDataResult<T> 派生自 RequestDataResult<T> 类,因此它具有 Data、Success 和 Message 属性。此类为错误操作提供自定义的响应模型,其中 Success 属性始终设置为 false。
它提供了不同的构造函数,其中包括用于错误情况的数据和消息的组合。由于其通用结构,它可以与任何数据类型一起使用,提供灵活且可重用的设计。
现在,让我们看看如何在 Web API 项目中使用这些包含数据的响应模型。项目文件夹结构如下:
标准响应模型项目的结构
我将接口和类放在 Model 文件夹中。
在 Data 文件夹中,我创建了以下类来模拟数据:
public class UserModel
{
public int Id { get; set; }
public string Name { get; set; }
public List<UserModel> ListUsers()
{
List<UserModel> users = new List<UserModel>();
users.Add(new UserModel { Id = 1, Name = "User Name1" });
users.Add(new UserModel { Id = 2, Name = "User Name2" });
users.Add(new UserModel { Id = 3, Name = "User Name3" });
return users;
}
}
在该项目中,我在 ResponseModelsController.cs中创建了四个终端节点。
[Route("api/[controller]")]
[ApiController]
public class ResponseModelsController : ControllerBase
{
private List<UserModel> _userData = new List<UserModel>();
public ResponseModelsController()
{
UserModel userModel = new UserModel();
_userData = userModel.ListUsers();
}
[HttpGet("SuccessResponseWithoutData")]
public IActionResult SuccessWithoutData()
{
return Ok(new SuccessRequestResult("Success response without data"));
}
[HttpGet("ErrorResponseWithoutData")]
public IActionResult ErrorWithoutData()
{
return BadRequest(new ErrorRequestResult("Error response without data"));
}
[HttpGet("SuccessResponseWithData")]
public IActionResult SuccessWithData()
{
return Ok(new SuccessRequestDataResult<List<UserModel>>(_userData, "Success response with data"));
}
[HttpGet("ErrorResponseWithData")]
public IActionResult ErrrorWithData()
{
return Ok(new ErrorRequestDataResult<List<UserModel>>("Error response with data"));
}
}
当我们运行项目时,Swagger 界面会向我们致意。
StandardResponseTypes 项目的 Swagger 接口
下面是一个不包含任何数据的成功响应模型的输出。
没有数据的成功响应
下面是不包含任何数据的错误响应模型的输出。
无数据的错误响应
下面是包含数据的成功响应模型的输出。
包含数据的成功响应
下面是包含数据的错误响应模型的输出。
带数据的错误响应
在软件项目中,响应模型的标准化起着极其关键的作用,尤其是在后端和前端应用程序之间的通信中。
这种标准化促进了项目的开发过程,并提高了其可持续性。
标准响应模型为所有团队成员提供清晰一致的数据通信。
因此,前端开发人员可以更轻松地理解和处理来自后端的响应。
此外,拥有统一的响应结构可以加快调试和维护过程,因为所有响应都采用相同的格式,从而更快地识别和解决问题。
标准响应模型还增强了代码的可重用性和可扩展性。创建标准模型后,可以轻松地跨不同的模块和项目使用。
这确保了开发人员不必重复重新创建相同的结构,从而加快了开发过程。
此外,使用标准响应模型可以提高软件项目的质量和可靠性。
这些标准允许开发人员以更有条理和结构化的方式工作,从而使项目管理更加有效。
源代码获取:公众号回复消息【code:10013
】