我创建了一个表单,用户可以在其中更新他的数据帐户。通过这种形式,用户还可以更改帐户密码,在执行此操作之前,我先询问他当前的密码,这是字段:
<div class="form-group">
<label>Current Password</label>
<input class="form-control" id="oldPassword"
asp-for="@Model.ExistingPassword" type="password" />
<div class="invalid-feedback"></div>
</div>
您可以看到oldPassword
输入绑定到属性ExistingPassword
,该属性是该ViewModel
的{{1}}的一部分,并具有以下声明:
View
提交表单后,我将调用以下[Required, MinLength(6), MaxLength(50), DataType(DataType.Password)]
public string ExistingPassword { get; set; }
函数:
ajax
函数的参数采用形式,特别是:
$.post(url, user, function (response) {
//Some stuff
}).done(function (response) {
alert("Updated executed");
}).fail(function (jqXHR, textStatus, errorThrown) {
alert("Error happened!");
});
$(this).attr('action');
该表单的操作将调用以下控制器:$(this).serialize();
。
在User\UpdateUser
方法内部,执行以下检查:
UpdateUser
基本上,条件检查当前密码是否正确,否则,将引发异常。
现在,我的问题是:我怎么知道该方法生成了哪种类型的异常?
我需要知道方法public async Task<UserProfileViewModel> UpdateUserAsync(UserProfileViewModel updatedUser)
{
if (!await _userManager.CheckPasswordAsync(originalUser, updatedUser.ExistingPassword))
throw new Exception("Invalid password");
生成了哪种类型的异常,因为该方法中存在不同的异常。
假设引发了UpdateUser
异常,我需要在Invalid Password
旁边的invalid-feedback
div中显示一条消息,以便用户知道更新失败的原因。
在此先感谢您的帮助。
答案 0 :(得分:1)
通常,除实际例外情况外,我建议不要使用例外,但是考虑到您设计例外的方式,您可以有一些选择。
我建议创建一个可引发的自定义“ UpdateUserException”,其中将包含其他信息,这些信息可以由枚举或仅由字符串提供。
public class UpdateUserException : Exception {
public UpdateUserError ErrorCondition;
public UpdateUserException(UpdateUserError error, string message)
{
ErrorCondition = error;
Message = message;
}
}
然后您将其扔掉
throw new UpdateUserException(UpdateUserError.BadPassword, "Invalid Password");
那么你会抓住它
try {}
catch (UpdateUserException e)
{
if (e.ErrorCondition == UpdateUserException.BadPassword)
{
// handle your exception.
}
}
答案 1 :(得分:0)
看看UserManager ChangePassword方法。
您可以像这样(在Startup.cs中)将UserManager绑定为使用DependencyInjection
public async void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseAuthentication();
app.UseMvc();
var scopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>();
using (var scope = scopeFactory.CreateScope())
{
UserManager<User> userManager = scope.ServiceProvider.GetRequiredService<UserManager<User>>();
}
}
然后在您的Controller的构造函数中
private readonly UserManager<User> _userManager;
public AccountController(UserManager<User> userManager)
{
_userManager = userManager;
}
最后是端点:
[HttpPost("ChangePassword")]
public async Task<IActionResult> ChangePassword([FromBody]ChangePasswordRequest changePasswordParams)
{
if (changePasswordParams == null)
return BadRequest($"{nameof(changePasswordParams)} must not be null!");
if (string.IsNullOrWhiteSpace(changePasswordParams.OldPassword) || string.IsNullOrWhiteSpace(changePasswordParams.NewPassword))
return BadRequest("old and new passwords have to be provided, but they both are empty.");
var userId = User.Claims.FirstOrDefault(c => c.Type == "id")?.Value;
var user = await _userManager.FindByIdAsync(userId);
var result = await _userManager.ChangePasswordAsync(user, changePasswordParams.OldPassword, changePasswordParams.NewPassword);
if (result.Succeeded)
return NoContent();
return BadRequest(result.Errors);
}
之后,您可以在switch语句中处理the errors。
答案 2 :(得分:0)
不建议将异常用于处理的错误,因为它们通常最终会导致内部服务器错误,而实际上这超出了其目的。
最好的方法是按照@maerlin的说明发送BadRequest。
但是,如果您坚持要在应用程序中使用异常,或者您的应用程序被设计为以这种方式工作。我建议您从ApplicationException继承新的CustomApplcationException类,然后从CustomApplicationException类继承UpdateUserException和vs。之后,建议您在ErrorHandlingMiddleware中处理异常,并至少使用BadRequest(400)状态代码返回HandledExceptions。
示例代码为
public class ExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILoggerManager _logger;
public ExceptionMiddleware(RequestDelegate next, ILoggerManager logger)
{
_logger = logger;
_next = next;
}
public async Task InvokeAsync(HttpContext httpContext)
{
try
{
await _next(httpContext);
}
catch (CustomApplicationException cae)
{
await HandleCustomExceptionAsync(httpContext, cae);
}
catch (Exception ex)
{
_logger.LogError($"Something went wrong: {ex}");
await HandleExceptionAsync(httpContext, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return context.Response.WriteAsync(new ErrorDetails()
{
StatusCode = context.Response.StatusCode,
Message = "Internal Server Error from the custom middleware."
}.ToString());
}
private static Task HandleCustomExceptionAsync(HttpContext context, Exception exception)
{
context.Response.StatusCode = 400;
return context.Response.WriteAsync(new ErrorDetails()
{
StatusCode = context.Response.StatusCode,
Message = exception.Message
}.ToString());
}
}
然后您需要在Startup.cs中重新注册中间件
app.UseMiddleware<ExceptionMiddleware>();
请参阅https://code-maze.com/global-error-handling-aspnetcore/和http://www.talkingdotnet.com/global-exception-handling-in-aspnet-core-webapi/了解更多详细信息。