理解NotFound()控制器及自定义过期调查的类似返回结果实现
实现方案
1. 创建自定义Action Result
定义SurveyExpiredResult类封装过期响应逻辑,支持传递额外信息:
public class SurveyExpiredResult : ActionResult { // 可选:传递的过期信息对象 public object ExpiryDetails { get; set; } // 可选:目标组件名称 public string TargetComponent { get; set; } public override async Task ExecuteResultAsync(ActionContext context) { var response = context.HttpContext.Response; // 使用410状态码表示资源已不可用(也可自定义状态码) response.StatusCode = StatusCodes.Status410Gone; // 传递目标组件名到响应头(可选) if (!string.IsNullOrEmpty(TargetComponent)) { response.Headers.Add("X-Target-Component", TargetComponent); } // 序列化过期信息并写入响应体(可选) if (ExpiryDetails != null) { response.ContentType = "application/json"; var json = JsonSerializer.Serialize(ExpiryDetails); await response.WriteAsync(json); } } }
2. 扩展Controller调用方法
给ControllerBase添加扩展方法,实现类似NotFound()的便捷调用:
public static class ControllerExtensions { // 基础版:无额外信息 public static SurveyExpiredResult HasExpired(this ControllerBase controller) { return new SurveyExpiredResult(); } // 重载版:传递过期信息对象 public static SurveyExpiredResult HasExpired(this ControllerBase controller, object expiryDetails) { return new SurveyExpiredResult { ExpiryDetails = expiryDetails }; } // 重载版:传递目标组件名 public static SurveyExpiredResult HasExpired(this ControllerBase controller, string targetComponent) { return new SurveyExpiredResult { TargetComponent = targetComponent }; } // 重载版:同时传递组件名和过期信息 public static SurveyExpiredResult HasExpired(this ControllerBase controller, string targetComponent, object expiryDetails) { return new SurveyExpiredResult { TargetComponent = targetComponent, ExpiryDetails = expiryDetails }; } }
3. 在API接口中使用
按照预期方式在Controller中调用:
[HttpGet("survey/{id}")] public async Task<IActionResult> GetSurvey(int id) { var survey = await _surveyRepository.GetByIdAsync(id); if (survey == null) { return NotFound(); } bool surveyHasExpired = DateTime.Now > survey.ExpiryDate; if (surveyHasExpired) { // 示例:传递包含过期信息的对象 var expiryDetails = new { SurveyId = id, ExpiryDate = survey.ExpiryDate, Message = "该调查已过期,无法访问" }; return HasExpired(expiryDetails); // 其他调用方式: // return HasExpired(); // 仅标记过期 // return HasExpired("SurveyExpiredComponent"); // 指定目标组件名 // return HasExpired("SurveyExpiredComponent", expiryDetails); // 同时传递两者 } return Ok(survey); }
4. Angular客户端处理逻辑
通过HTTP拦截器捕获410状态码,提取信息并路由到对应页面:
@Injectable() export class HttpErrorInterceptor implements HttpInterceptor { constructor(private router: Router) {} intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(request).pipe( catchError((error: HttpErrorResponse) => { if (error.status === 410) { // 提取目标组件名,默认使用"SurveyExpired" const targetComponent = error.headers.get('X-Target-Component') || 'SurveyExpired'; // 提取过期信息 const expiryDetails = error.error; // 路由到对应组件,可通过queryParams传递信息 this.router.navigate([`/${targetComponent}`], { queryParams: expiryDetails }); } return throwError(() => error); }) ); } }
在Angular路由模块中配置对应路由:
const routes: Routes = [ // 其他路由... { path: 'SurveyExpired', component: SurveyExpiredComponent }, { path: 'NotFound', component: NotFoundComponent }, // 通配符路由... ];
内容的提问来源于stack exchange,提问作者Steve Olson
相关产品推荐
相关产品推荐

