用于可返回匿名类型以及 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()
}
这三种方法有什么区别吗?应该首选哪一个?
如果我正确理解你的问题,问题主要是关于编写程序的风格,因为所有选项都将以相同的方式调用。
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);
}
结果将始终解释为object
(object 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
的最后一个版本具有足够的可读性。更多的是味道的问题。