You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

理解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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 06:50:26