用于可返回匿名类型以及 HTTP 状态代码的操作方法的返回类型

本文关键字:状态 HTTP 代码 操作方法 返回类型 返回 类型 用于 | 更新日期: 2023-09-27 18:35:59

我看到有多种方法可以在 Asp.Net 核心控制器中返回数据,当可能出现各种结果时:

1) object

[HttpPost]
public object RefreshToken()
{
    if (Validate())
    {
        return new
               {
                   token = CreateToken()
               };
    }
    return HttpUnauthorized()
}

2) dynamic

[HttpPost]
public dynamic RefreshToken()
{
    if (Validate())
    {
        return new
               {
                   token = CreateToken()
               };
    }
    return HttpUnauthorized()
}

3) IActionResult

[HttpPost]
public IActionResult RefreshToken()
{
    if (Validate())
    {
                return new ObjectResult(new
                {
                    token = CreateToken()
                });
    }
    return HttpUnauthorized()
}

这三种方法有什么区别吗?应该首选哪一个?

用于可返回匿名类型以及 HTTP 状态代码的操作方法的返回类型

如果我正确理解你的问题,问题主要是关于编写程序的风格,因为所有选项都将以相同的方式调用。

MVC 以相同的方式执行所有操作。带有 invocationResult = actionMethodInfo.Invoke(instance, orderedActionArguments); 的行(我在注释中放置!!!)调用控制器操作:

public static Task<object> ExecuteAsync(
    MethodInfo actionMethodInfo,
    object instance,
    object[] orderedActionArguments)
{
    object invocationResult = null;
    try
    {
        invocationResult = actionMethodInfo.Invoke(instance, orderedActionArguments); // !!!
    }
    catch (TargetInvocationException targetInvocationException)
    {
        // Capturing the exception and the original callstack and rethrow for external exception handlers.
        var exceptionDispatchInfo = ExceptionDispatchInfo.Capture(targetInvocationException.InnerException);
        exceptionDispatchInfo.Throw();
    }
    return CoerceResultToTaskAsync(
        invocationResult,
        actionMethodInfo.ReturnType,
        actionMethodInfo.Name,
        actionMethodInfo.DeclaringType);
}

结果将始终解释为objectobject invocationResult)。然后,该方法CoerceResultToTaskAsync测试返回对象的类型是否Task,如果不是,则将其转换为 Task。然后外部方法(var actionReturnValue = await ControllerActionExecutor.ExecuteAsync(...);内部)返回此处的值,并在返回结果具有IActionResult接口的行(var actionResult = actionReturnValue as IActionResult; if (actionResult != null) { return actionResult; })中CreateActionResult测试。如果没有,则返回new ObjectResult(...) .请参阅下面的代码副本

internal static IActionResult CreateActionResult(Type declaredReturnType, object actionReturnValue)
{
    if (declaredReturnType == null)
    {
        throw new ArgumentNullException(nameof(declaredReturnType));
    }
    // optimize common path
    var actionResult = actionReturnValue as IActionResult;
    if (actionResult != null)
    {
        return actionResult;
    }
    if (declaredReturnType == typeof(void) ||
        declaredReturnType == typeof(Task))
    {
        return new EmptyResult();
    }
    // Unwrap potential Task<T> types.
    var actualReturnType = GetTaskInnerTypeOrNull(declaredReturnType) ?? declaredReturnType;
    if (actionReturnValue == null &&
        typeof(IActionResult).GetTypeInfo().IsAssignableFrom(actualReturnType.GetTypeInfo()))
    {
        throw new InvalidOperationException(
            Resources.FormatActionResult_ActionReturnValueCannotBeNull(actualReturnType));
    }
    return new ObjectResult(actionReturnValue)
    {
        DeclaredType = actualReturnType
    };
}

换句话说,所有代码都做同样的事情。第一个选项返回 object ,最后一个选项的工作方式相同。我个人更喜欢使用第一个选项来没有显式调用ObjectResult,但在其他情况下,带有IActionResult的最后一个版本具有足够的可读性。更多的是味道的问题。