Merge pull request #22840 from dotnet-maestro-bot/merge/release/3.1-to-master

[automated] Merge branch 'release/3.1' => 'master'
This commit is contained in:
William Godbe 2020-06-12 13:03:12 -07:00 committed by GitHub
commit 0343af108a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 128 additions and 35 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -85,7 +85,14 @@ export class WebAssemblyResourceLoader {
const cacheKey = toAbsoluteUri(`${url}.${contentHash}`);
this.usedCacheKeys[cacheKey] = true;
const cachedResponse = await cache.match(cacheKey);
let cachedResponse: Response | undefined;
try {
cachedResponse = await cache.match(cacheKey);
} catch {
// Be tolerant to errors reading from the cache. This is a guard for https://bugs.chromium.org/p/chromium/issues/detail?id=968444 where
// chromium browsers may sometimes throw when working with the cache.
}
if (cachedResponse) {
// It's in the cache.
const responseBytes = parseInt(cachedResponse.headers.get('content-length') || '0');
@ -136,12 +143,19 @@ export class WebAssemblyResourceLoader {
// Add to cache as a custom response object so we can track extra data such as responseBytes
// We can't rely on the server sending content-length (ASP.NET Core doesn't by default)
await cache.put(cacheKey, new Response(responseData, {
const responseToCache = new Response(responseData, {
headers: {
'content-type': response.headers.get('content-type') || '',
'content-length': (responseBytes || response.headers.get('content-length') || '').toString()
}
}));
});
try {
await cache.put(cacheKey, responseToCache);
} catch {
// Be tolerant to errors writing to the cache. This is a guard for https://bugs.chromium.org/p/chromium/issues/detail?id=968444 where
// chromium browsers may sometimes throw when performing cache operations.
}
}
}

View File

@ -163,7 +163,7 @@
<WriteLinesToFile
File="$(_CombinedHashIntermediatePath)"
Lines="@(_ServiceWorkerAssetsManifestItemWithHash->'%(FileHash)')"
Lines="@(_ServiceWorkerAssetsManifestItemWithHash->'%(Integrity)')"
WriteOnlyWhenDifferent="true"
Overwrite="true" />

View File

@ -1,6 +1,7 @@
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Xunit;
@ -41,5 +42,77 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Build
var entries = assets.EnumerateArray().Select(e => e.GetProperty("url").GetString()).OrderBy(e => e).ToArray();
Assert.All(entries, e => expectedExtensions.Contains(Path.GetExtension(e)));
}
[Fact]
public async Task Publish_UpdatesServiceWorkerVersionHash_WhenSourcesChange()
{
// Arrange
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", args: "/bl:initial.binlog /p:ServiceWorkerAssetsManifest=service-worker-assets.js");
Assert.BuildPassed(result);
var publishOutputDirectory = project.PublishOutputDirectory;
var serviceWorkerFile = Assert.FileExists(result, publishOutputDirectory, "wwwroot", "serviceworkers", "my-service-worker.js");
var version = File.ReadAllLines(serviceWorkerFile).Last();
var match = Regex.Match(version, "\\/\\* Manifest version: (.{8}) \\*\\/");
Assert.True(match.Success);
Assert.Equal(2, match.Groups.Count);
Assert.NotNull(match.Groups[1].Value);
var capture = match.Groups[1].Value;
// Act
var cssFile = Path.Combine(project.DirectoryPath, "LinkToWebRoot", "css", "app.css");
File.WriteAllText(cssFile, ".updated { }");
// Assert
var updatedResult = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", args: "/bl:updated.binlog /p:ServiceWorkerAssetsManifest=service-worker-assets.js");
Assert.BuildPassed(result);
var updatedVersion = File.ReadAllLines(serviceWorkerFile).Last();
var updatedMatch = Regex.Match(updatedVersion, "\\/\\* Manifest version: (.{8}) \\*\\/");
Assert.True(updatedMatch.Success);
Assert.Equal(2, updatedMatch.Groups.Count);
Assert.NotNull(updatedMatch.Groups[1].Value);
var updatedCapture = updatedMatch.Groups[1].Value;
Assert.NotEqual(capture, updatedCapture);
}
[Fact]
public async Task Publish_DeterministicAcrossBuilds_WhenNoSourcesChange()
{
// Arrange
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", args: "/bl:initial.binlog /p:ServiceWorkerAssetsManifest=service-worker-assets.js");
Assert.BuildPassed(result);
var publishOutputDirectory = project.PublishOutputDirectory;
var serviceWorkerFile = Assert.FileExists(result, publishOutputDirectory, "wwwroot", "serviceworkers", "my-service-worker.js");
var version = File.ReadAllLines(serviceWorkerFile).Last();
var match = Regex.Match(version, "\\/\\* Manifest version: (.{8}) \\*\\/");
Assert.True(match.Success);
Assert.Equal(2, match.Groups.Count);
Assert.NotNull(match.Groups[1].Value);
var capture = match.Groups[1].Value;
// Act && Assert
var updatedResult = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", args: "/bl:updated.binlog /p:ServiceWorkerAssetsManifest=service-worker-assets.js");
Assert.BuildPassed(result);
var updatedVersion = File.ReadAllLines(serviceWorkerFile).Last();
var updatedMatch = Regex.Match(updatedVersion, "\\/\\* Manifest version: (.{8}) \\*\\/");
Assert.True(updatedMatch.Success);
Assert.Equal(2, updatedMatch.Groups.Count);
Assert.NotNull(updatedMatch.Groups[1].Value);
var updatedCapture = updatedMatch.Groups[1].Value;
Assert.Equal(capture, updatedCapture);
}
}
}

View File

@ -143,6 +143,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
}
readStream = new FileBufferingReadStream(request.Body, memoryThreshold);
// Ensure the file buffer stream is always disposed at the end of a request.
request.HttpContext.Response.RegisterForDispose(readStream);
await readStream.DrainAsync(CancellationToken.None);
readStream.Seek(0L, SeekOrigin.Begin);

View File

@ -124,6 +124,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
}
readStream = new FileBufferingReadStream(request.Body, memoryThreshold);
// Ensure the file buffer stream is always disposed at the end of a request.
request.HttpContext.Response.RegisterForDispose(readStream);
await readStream.DrainAsync(CancellationToken.None);
readStream.Seek(0L, SeekOrigin.Begin);

View File

@ -153,6 +153,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
}
readStream = new FileBufferingReadStream(request.Body, memoryThreshold);
// Ensure the file buffer stream is always disposed at the end of a request.
request.HttpContext.Response.RegisterForDispose(readStream);
await readStream.DrainAsync(CancellationToken.None);
readStream.Seek(0L, SeekOrigin.Begin);
@ -278,7 +280,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
/// <summary>
/// Called during deserialization to get the <see cref="JsonSerializer"/>. The formatter context
/// that is passed gives an ability to create serializer specific to the context.
/// that is passed gives an ability to create serializer specific to the context.
/// </summary>
/// <returns>The <see cref="JsonSerializer"/> used during deserialization.</returns>
/// <remarks>
@ -297,7 +299,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
/// <summary>
/// Called during deserialization to get the <see cref="JsonSerializer"/>. The formatter context
/// that is passed gives an ability to create serializer specific to the context.
/// that is passed gives an ability to create serializer specific to the context.
/// </summary>
/// <param name="context">A context object used by an input formatter for deserializing the request body into an object.</param>
/// <returns>The <see cref="JsonSerializer"/> used during deserialization.</returns>

View File

@ -1,16 +1,16 @@
@page "/error"
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
@page
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>

View File

@ -25,13 +25,13 @@ namespace ComponentsWebAssembly_CSharp
builder.RootComponents.Add<App>("app");
#if (!Hosted || NoAuth)
builder.Services.AddTransient(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
#else
builder.Services.AddHttpClient("ComponentsWebAssembly_CSharp.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
// Supply HttpClient instances that include access tokens when making requests to the server project
builder.Services.AddTransient(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("ComponentsWebAssembly_CSharp.ServerAPI"));
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("ComponentsWebAssembly_CSharp.ServerAPI"));
#endif
#if(!NoAuth)

View File

@ -914,7 +914,7 @@
"Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs",
"Data/Migrations/ApplicationDbContextModelSnapshot.cs",
"Pages/Counter.razor",
"Pages/Error.razor",
"Pages/Error.cshtml",
"Pages/FetchData.razor",
"Pages/Index.razor",
"Pages/_Host.cshtml",
@ -951,7 +951,7 @@
"Data/WeatherForecast.cs",
"Data/WeatherForecastService.cs",
"Pages/Counter.razor",
"Pages/Error.razor",
"Pages/Error.cshtml",
"Pages/FetchData.razor",
"Pages/Index.razor",
"Pages/_Host.cshtml",
@ -988,7 +988,7 @@
"Data/WeatherForecast.cs",
"Data/WeatherForecastService.cs",
"Pages/Counter.razor",
"Pages/Error.razor",
"Pages/Error.cshtml",
"Pages/FetchData.razor",
"Pages/Index.razor",
"Pages/_Host.cshtml",
@ -1024,7 +1024,7 @@
"_Imports.razor",
"Data/WeatherForecast.cs",
"Data/WeatherForecastService.cs",
"Pages/Error.razor",
"Pages/Error.cshtml",
"Pages/Counter.razor",
"Pages/FetchData.razor",
"Pages/Index.razor",
@ -1061,7 +1061,7 @@
"Data/WeatherForecast.cs",
"Data/WeatherForecastService.cs",
"Pages/Counter.razor",
"Pages/Error.razor",
"Pages/Error.cshtml",
"Pages/FetchData.razor",
"Pages/Index.razor",
"Pages/_Host.cshtml",
@ -1098,7 +1098,7 @@
"Data/WeatherForecast.cs",
"Data/WeatherForecastService.cs",
"Pages/Counter.razor",
"Pages/Error.razor",
"Pages/Error.cshtml",
"Pages/FetchData.razor",
"Pages/Index.razor",
"Pages/_Host.cshtml",