diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ActionResultOfT.cs b/src/Microsoft.AspNetCore.Mvc.Core/ActionResultOfT.cs
index f443d78805..048c80ff52 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ActionResultOfT.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ActionResultOfT.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using Microsoft.AspNetCore.Mvc.Core;
using Microsoft.AspNetCore.Mvc.Infrastructure;
namespace Microsoft.AspNetCore.Mvc
@@ -18,6 +19,12 @@ namespace Microsoft.AspNetCore.Mvc
/// The value.
public ActionResult(TValue value)
{
+ if (typeof(IActionResult).IsAssignableFrom(typeof(TValue)))
+ {
+ var error = Resources.FormatInvalidTypeTForActionResultOfT(typeof(TValue), "ActionResult");
+ throw new ArgumentException(error);
+ }
+
Value = value;
}
@@ -27,6 +34,12 @@ namespace Microsoft.AspNetCore.Mvc
/// The .
public ActionResult(ActionResult result)
{
+ if (typeof(IActionResult).IsAssignableFrom(typeof(TValue)))
+ {
+ var error = Resources.FormatInvalidTypeTForActionResultOfT(typeof(TValue), "ActionResult");
+ throw new ArgumentException(error);
+ }
+
Result = result ?? throw new ArgumentNullException(nameof(result));
}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs
index c766cf5a59..1221fccdef 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs
@@ -1480,6 +1480,20 @@ namespace Microsoft.AspNetCore.Mvc.Core
internal static string FormatApiConventionMustBeStatic(object p0)
=> string.Format(CultureInfo.CurrentCulture, GetString("ApiConventionMustBeStatic"), p0);
+ ///
+ /// Invalid type parameter '{0}' specified for '{1}'.
+ ///
+ internal static string InvalidTypeTForActionResultOfT
+ {
+ get => GetString("InvalidTypeTForActionResultOfT");
+ }
+
+ ///
+ /// Invalid type parameter '{0}' specified for '{1}'.
+ ///
+ internal static string FormatInvalidTypeTForActionResultOfT(object p0, object p1)
+ => string.Format(CultureInfo.CurrentCulture, GetString("InvalidTypeTForActionResultOfT"), p0, p1);
+
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx b/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx
index d912ecd0c5..98aa14bda6 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx
@@ -445,4 +445,7 @@
API convention type '{0}' must be a static type.
+
+ Invalid type parameter '{0}' specified for '{1}'.
+
\ No newline at end of file
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ActionResultOfTTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ActionResultOfTTest.cs
index 2445e84677..8f5abec7e5 100644
--- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ActionResultOfTTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ActionResultOfTTest.cs
@@ -1,6 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using System;
+using System.IO;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Xunit;
@@ -8,6 +10,28 @@ namespace Microsoft.AspNetCore.Mvc
{
public class ActionResultOfTTest
{
+ [Fact]
+ public void Constructor_WithValue_ThrowsForInvalidType()
+ {
+ // Arrange
+ var input = new FileStreamResult(Stream.Null, "application/json");
+
+ // Act & Assert
+ var ex = Assert.Throws(() => new ActionResult(value: input));
+ Assert.Equal($"Invalid type parameter '{typeof(FileStreamResult)}' specified for 'ActionResult'.", ex.Message);
+ }
+
+ [Fact]
+ public void Constructor_WithActionResult_ThrowsForInvalidType()
+ {
+ // Arrange
+ var actionResult = new OkResult();
+
+ // Act & Assert
+ var ex = Assert.Throws(() => new ActionResult(result: actionResult));
+ Assert.Equal($"Invalid type parameter '{typeof(FileStreamResult)}' specified for 'ActionResult'.", ex.Message);
+ }
+
[Fact]
public void Convert_ReturnsResultIfSet()
{