Skip to content

Commit bdc812c

Browse files
committed
Adding implementation for FileStreamResult and LocalRedirectResult
1 parent 3515f5d commit bdc812c

9 files changed

+1094
-646
lines changed

src/Mvc/Mvc.Core/src/FileStreamResult.cs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
using System.Diagnostics.CodeAnalysis;
66
using System.IO;
77
using System.Threading.Tasks;
8+
using Microsoft.AspNetCore.Http;
89
using Microsoft.AspNetCore.Mvc.Infrastructure;
910
using Microsoft.Extensions.DependencyInjection;
11+
using Microsoft.Extensions.Logging;
1012
using Microsoft.Net.Http.Headers;
1113

1214
namespace Microsoft.AspNetCore.Mvc
@@ -15,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc
1517
/// Represents an <see cref="ActionResult"/> that when executed will
1618
/// write a file from a stream to the response.
1719
/// </summary>
18-
public class FileStreamResult : FileResult
20+
public class FileStreamResult : FileResult, IResult
1921
{
2022
private Stream _fileStream;
2123

@@ -79,5 +81,42 @@ public override Task ExecuteResultAsync(ActionContext context)
7981
var executor = context.HttpContext.RequestServices.GetRequiredService<IActionResultExecutor<FileStreamResult>>();
8082
return executor.ExecuteAsync(context, this);
8183
}
84+
85+
async Task IResult.ExecuteAsync(HttpContext httpContext)
86+
{
87+
if (httpContext == null)
88+
{
89+
throw new ArgumentNullException(nameof(httpContext));
90+
}
91+
92+
using (FileStream)
93+
{
94+
var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>();
95+
var logger = loggerFactory.CreateLogger<RedirectResult>();
96+
logger.ExecutingFileResult(this);
97+
98+
long? fileLength = null;
99+
if (FileStream.CanSeek)
100+
{
101+
fileLength = FileStream.Length;
102+
}
103+
104+
var (range, rangeLength, serveBody) = FileResultExecutorBase.SetHeadersAndLog(
105+
httpContext,
106+
this,
107+
fileLength,
108+
EnableRangeProcessing,
109+
LastModified,
110+
EntityTag,
111+
logger);
112+
113+
if (!serveBody)
114+
{
115+
return;
116+
}
117+
118+
await FileStreamResultExecutor.WriteFileAsyncInternal(httpContext, this, range, rangeLength, logger);
119+
}
120+
}
82121
}
83122
}

src/Mvc/Mvc.Core/src/Infrastructure/FileStreamResultExecutor.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
using System;
77
using System.Threading.Tasks;
8+
using Microsoft.AspNetCore.Http;
89
using Microsoft.Extensions.Logging;
910
using Microsoft.Net.Http.Headers;
1011

@@ -77,9 +78,14 @@ protected virtual Task WriteFileAsync(
7778
RangeItemHeaderValue? range,
7879
long rangeLength)
7980
{
80-
if (context == null)
81+
return WriteFileAsyncInternal(context.HttpContext, result, range, rangeLength, Logger);
82+
}
83+
84+
internal static Task WriteFileAsyncInternal(HttpContext httpContext, FileStreamResult result, RangeItemHeaderValue? range, long rangeLength, ILogger logger)
85+
{
86+
if (httpContext == null)
8187
{
82-
throw new ArgumentNullException(nameof(context));
88+
throw new ArgumentNullException(nameof(httpContext));
8389
}
8490

8591
if (result == null)
@@ -94,10 +100,10 @@ protected virtual Task WriteFileAsync(
94100

95101
if (range != null)
96102
{
97-
Logger.WritingRangeToBody();
103+
logger.WritingRangeToBody();
98104
}
99105

100-
return WriteFileAsync(context.HttpContext, result.FileStream, range, rangeLength);
106+
return WriteFileAsync(httpContext, result.FileStream, range, rangeLength);
101107
}
102108
}
103109
}

src/Mvc/Mvc.Core/src/LocalRedirectResult.cs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,20 @@
44
using System;
55
using System.Diagnostics.CodeAnalysis;
66
using System.Threading.Tasks;
7+
using Microsoft.AspNetCore.Http;
78
using Microsoft.AspNetCore.Mvc.Core;
89
using Microsoft.AspNetCore.Mvc.Infrastructure;
10+
using Microsoft.AspNetCore.Mvc.Routing;
911
using Microsoft.Extensions.DependencyInjection;
12+
using Microsoft.Extensions.Logging;
1013

1114
namespace Microsoft.AspNetCore.Mvc
1215
{
1316
/// <summary>
1417
/// An <see cref="ActionResult"/> that returns a Found (302), Moved Permanently (301), Temporary Redirect (307),
1518
/// or Permanent Redirect (308) response with a Location header to the supplied local URL.
1619
/// </summary>
17-
public class LocalRedirectResult : ActionResult
20+
public class LocalRedirectResult : ActionResult, IResult
1821
{
1922
private string _localUrl;
2023

@@ -103,5 +106,39 @@ public override Task ExecuteResultAsync(ActionContext context)
103106
var executor = context.HttpContext.RequestServices.GetRequiredService<IActionResultExecutor<LocalRedirectResult>>();
104107
return executor.ExecuteAsync(context, this);
105108
}
109+
110+
Task IResult.ExecuteAsync(HttpContext httpContext)
111+
{
112+
if (httpContext == null)
113+
{
114+
throw new ArgumentNullException(nameof(httpContext));
115+
}
116+
117+
// IsLocalUrl is called to handle Urls starting with '~/'.
118+
if (!UrlHelperBase.CheckIsLocalUrl(Url))
119+
{
120+
throw new InvalidOperationException(Resources.UrlNotLocal);
121+
}
122+
123+
var destinationUrl = UrlHelperBase.Content(httpContext, Url);
124+
125+
var loggerFactory = httpContext.RequestServices.GetRequiredService<ILoggerFactory>();
126+
var logger = loggerFactory.CreateLogger<RedirectResult>();
127+
logger.LocalRedirectResultExecuting(destinationUrl);
128+
129+
if (PreserveMethod)
130+
{
131+
httpContext.Response.StatusCode = Permanent
132+
? StatusCodes.Status308PermanentRedirect
133+
: StatusCodes.Status307TemporaryRedirect;
134+
httpContext.Response.Headers.Location = destinationUrl;
135+
}
136+
else
137+
{
138+
httpContext.Response.Redirect(destinationUrl, Permanent);
139+
}
140+
141+
return Task.CompletedTask;
142+
}
106143
}
107144
}

0 commit comments

Comments
 (0)