什么return in web api asp net core
What return in web api asp net core
我不确定在 LoginAsync 方法中我应该 return 什么。有时我对 return 有错误,但有时验证成功。我目前正在使用动态,但听说这是不好的做法。我应该用什么?
它是 AccountService 服务中的 LoginAsync:
public async Task<dynamic> LoginAsync(User user)
{
var existingUser_byEmail = await FindUserByEmailAsync(user.Email);
if (existingUser_byEmail == default)
return new Error
{
StatusCode = 400,
ErrorMessages = { { "email", "Nie odnaleziono użytkownika z podanym adresem e-mail" } }
};
if (BCrypt.Net.BCrypt.EnhancedVerify(user.Password, existingUser_byEmail.Password))
return new AuthSuccessful { StatusCode = 200, Token = _jwtService.GenerateToken(existingUser_byEmail) };
else
return new Error { StatusCode = 401, ErrorMessages = { { "password", "Błędne hasło" } } };
}
它是 AccountController 中的登录方法:
[HttpPost("login")]
public async Task<IActionResult> LogIn([FromBody] User user)
{
var response = await _accountService.LoginAsync(user);
return StatusCode(response.StatusCode, response);
}
谢谢大家的回答,祝你有美好的一天! :D
您有多种选择。
1。 Interface/baseclass
似乎您 return 的所有内容都具有相似的结构 – StatusCode
属性,以及在给定状态代码的上下文中有意义的其他一些附加属性。
所以最明显的可能是为这些创建一个基础 class 或一个接口,如下所示:
public interface IOperationResult
{
int StatusCode { get; init; }
object Response { get; }
}
public class Error : IOperationResult
{
public int StatusCode { get; init; }
public string[,] ErrorMessages { get; init; }
public object Response => ErrorMessages;
}
public class AuthSuccessful : IOperationResult
{
public int StatusCode { get; init; }
public string Token { get; init; }
public object Response => Token;
}
这是一个定义明确的结构,可以说支持更复杂的业务逻辑,当您可能需要检查 return 值的确切类型并以类型安全的方式访问它们的属性时。
2。值元组
最近我经常使用的另一个选项是 returning 一个值元组,其中一个成员包含 success/failure,另一个成员包含结果;像下面这样。在这种情况下看起来很糟糕,因为错误消息的格式没有定义。但是,如果您为此使用了 class 或结构,那就没问题了。
public async Task<(int statusCode, object response)> LoginAsync(User user)
{
var existingUser_byEmail = await FindUserByEmailAsync(user.Email);
if (existingUser_byEmail == default)
return (statusCode: 400, response: new[] { new[] { "email", "Nie odnaleziono użytkownika z podanym adresem e-mail" } });
if (BCrypt.Net.BCrypt.EnhancedVerify(user.Password, existingUser_byEmail.Password))
return (statusCode: 200, response: _jwtService.GenerateToken(existingUser_byEmail));
else
return (statusCode: 401, response: new[] { new[] { "password", "Błędne hasło" } });
}
// Then you can do a tuple deconstruction assignment:
[HttpPost("login")]
public async Task<IActionResult> LogIn([FromBody] User user)
{
var (statusCode, response) = await _accountService.LoginAsync(user);
return StatusCode(statusCode, response);
}
3。在服务外做HTTP代码和错误信息选择
更传统的做法是 return 来自身份验证服务的不同标志,然后将其映射到靠近控制器(或控制器内部)某处的 HTTP 代码。通过这种方式,您可以避免将服务与 HTTP 问题耦合,这可以说不应该是他们的责任。
例如很多内置身份服务使用 Microsoft.AspNetCore.Identity.SignInResult
class.
在下面的实现中,我将 LoginAsync
方法更改为 return 在密码无效和电子邮件无效的情况下均失败。这实际上是一种更好的做法,因为如果您告诉尝试登录的人某个电子邮件地址有或没有帐户,您就是在泄露用户信息。
public async Task<(SignInResult result, string token)> LoginAsync(User user)
{
var existingUser_byEmail = await FindUserByEmailAsync(user.Email);
if (existingUser_byEmail == default)
return (SignInResult.Failed, null);
if (BCrypt.Net.BCrypt.EnhancedVerify(user.Password, existingUser_byEmail.Password))
return (SignInResult.Success, _jwtService.GenerateToken(existingUser_byEmail));
else
return (SignInResult.Failed, null);
}
[HttpPost("login")]
public async Task<IActionResult> LogIn([FromBody] User user)
{
var (result, token) = await _accountService.LoginAsync(user);
if (result.Succeeded)
return Ok(token);
// Handle lock-out and 'login not allowed' situation too, if necessary.
return Unauthorized("Invalid password or email.");
}
我不确定在 LoginAsync 方法中我应该 return 什么。有时我对 return 有错误,但有时验证成功。我目前正在使用动态,但听说这是不好的做法。我应该用什么? 它是 AccountService 服务中的 LoginAsync:
public async Task<dynamic> LoginAsync(User user)
{
var existingUser_byEmail = await FindUserByEmailAsync(user.Email);
if (existingUser_byEmail == default)
return new Error
{
StatusCode = 400,
ErrorMessages = { { "email", "Nie odnaleziono użytkownika z podanym adresem e-mail" } }
};
if (BCrypt.Net.BCrypt.EnhancedVerify(user.Password, existingUser_byEmail.Password))
return new AuthSuccessful { StatusCode = 200, Token = _jwtService.GenerateToken(existingUser_byEmail) };
else
return new Error { StatusCode = 401, ErrorMessages = { { "password", "Błędne hasło" } } };
}
它是 AccountController 中的登录方法:
[HttpPost("login")]
public async Task<IActionResult> LogIn([FromBody] User user)
{
var response = await _accountService.LoginAsync(user);
return StatusCode(response.StatusCode, response);
}
谢谢大家的回答,祝你有美好的一天! :D
您有多种选择。
1。 Interface/baseclass
似乎您 return 的所有内容都具有相似的结构 – StatusCode
属性,以及在给定状态代码的上下文中有意义的其他一些附加属性。
所以最明显的可能是为这些创建一个基础 class 或一个接口,如下所示:
public interface IOperationResult
{
int StatusCode { get; init; }
object Response { get; }
}
public class Error : IOperationResult
{
public int StatusCode { get; init; }
public string[,] ErrorMessages { get; init; }
public object Response => ErrorMessages;
}
public class AuthSuccessful : IOperationResult
{
public int StatusCode { get; init; }
public string Token { get; init; }
public object Response => Token;
}
这是一个定义明确的结构,可以说支持更复杂的业务逻辑,当您可能需要检查 return 值的确切类型并以类型安全的方式访问它们的属性时。
2。值元组
最近我经常使用的另一个选项是 returning 一个值元组,其中一个成员包含 success/failure,另一个成员包含结果;像下面这样。在这种情况下看起来很糟糕,因为错误消息的格式没有定义。但是,如果您为此使用了 class 或结构,那就没问题了。
public async Task<(int statusCode, object response)> LoginAsync(User user)
{
var existingUser_byEmail = await FindUserByEmailAsync(user.Email);
if (existingUser_byEmail == default)
return (statusCode: 400, response: new[] { new[] { "email", "Nie odnaleziono użytkownika z podanym adresem e-mail" } });
if (BCrypt.Net.BCrypt.EnhancedVerify(user.Password, existingUser_byEmail.Password))
return (statusCode: 200, response: _jwtService.GenerateToken(existingUser_byEmail));
else
return (statusCode: 401, response: new[] { new[] { "password", "Błędne hasło" } });
}
// Then you can do a tuple deconstruction assignment:
[HttpPost("login")]
public async Task<IActionResult> LogIn([FromBody] User user)
{
var (statusCode, response) = await _accountService.LoginAsync(user);
return StatusCode(statusCode, response);
}
3。在服务外做HTTP代码和错误信息选择
更传统的做法是 return 来自身份验证服务的不同标志,然后将其映射到靠近控制器(或控制器内部)某处的 HTTP 代码。通过这种方式,您可以避免将服务与 HTTP 问题耦合,这可以说不应该是他们的责任。
例如很多内置身份服务使用 Microsoft.AspNetCore.Identity.SignInResult
class.
在下面的实现中,我将 LoginAsync
方法更改为 return 在密码无效和电子邮件无效的情况下均失败。这实际上是一种更好的做法,因为如果您告诉尝试登录的人某个电子邮件地址有或没有帐户,您就是在泄露用户信息。
public async Task<(SignInResult result, string token)> LoginAsync(User user)
{
var existingUser_byEmail = await FindUserByEmailAsync(user.Email);
if (existingUser_byEmail == default)
return (SignInResult.Failed, null);
if (BCrypt.Net.BCrypt.EnhancedVerify(user.Password, existingUser_byEmail.Password))
return (SignInResult.Success, _jwtService.GenerateToken(existingUser_byEmail));
else
return (SignInResult.Failed, null);
}
[HttpPost("login")]
public async Task<IActionResult> LogIn([FromBody] User user)
{
var (result, token) = await _accountService.LoginAsync(user);
if (result.Succeeded)
return Ok(token);
// Handle lock-out and 'login not allowed' situation too, if necessary.
return Unauthorized("Invalid password or email.");
}