Fix #7258 - remove components.server dependencies on blazor-specific plumbing (#7934)

* Removes a bunch of trivial usage of Blazor

... in names and comments where we don't specifically mean Blazor.

* Remove obsolete Startup from Components app

* Move UseBlazor into Blazor.Server

Moves UseBlazor and the related features in Blazor.Server - along with
some other general cleanup of misc shared files.

Now Components.Server has a much slimmer set of dependencies (MVC is
gone) and doesn't contain the "double startup" pattern that we
introduced (sorry).

We'll revisit UseBlazor and the dependencies there once the new
MapFallbackToFile support is available from static files.

* minor PR feedback

* Update reference assemblies

* fix broken test
This commit is contained in:
Ryan Nowak 2019-02-28 10:36:07 -08:00 committed by GitHub
parent f168835c0a
commit cb21edc500
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 182 additions and 275 deletions

View File

@ -1,6 +1,14 @@
; EditorConfig to support per-solution formatting.
; Use the EditorConfig VS add-in to make this work.
; http://editorconfig.org/
;
; Here are some resources for what's supported for .NET/C#
; https://kent-boogaart.com/blog/editorconfig-reference-for-c-developers
; https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference?view=vs-2017
;
; Be **careful** editing this because some of the rules don't support adding a severity level
; For instance if you change to `dotnet_sort_system_directives_first = true:warning` (adding `:warning`)
; then the rule will be silently ignored.
; This is the default for the codeline.
root = true
@ -13,7 +21,7 @@ insert_final_newline = true
[*.cs]
indent_size = 4
dotnet_sort_system_directives_first = true:warning
dotnet_sort_system_directives_first = true
[*.{xml,config,*proj,nuspec,props,resx,targets,yml,tasks}]
indent_size = 2

View File

@ -0,0 +1,18 @@
// 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.
namespace Microsoft.AspNetCore.Components.Shared
{
// Constants for type and method names used in code-generation
// Keep these in sync with the actual definitions
internal static class ComponentsApi
{
public static readonly string AssemblyName = "Microsoft.AspNetCore.Components";
public static class ParameterAttribute
{
public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.ParameterAttribute";
public static readonly string MetadataName = FullTypeName;
}
}
}

View File

@ -20,7 +20,6 @@
</ItemGroup>
<ItemGroup>
<Compile Include="$(ComponentsSharedSourceRoot)src\ComponentsApi.cs" LinkBase="Shared" />
<Compile Update="Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>

View File

@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test
{
public class ComponentParametersShouldNotBePublic : CodeFixVerifier
{
static string BlazorParameterSource = $@"
static string ParameterSource = $@"
namespace {typeof(ParameterAttribute).Namespace}
{{
public class {typeof(ParameterAttribute).Name} : System.Attribute
@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test
{
public string MyProperty { get; set; }
}
}" + BlazorParameterSource;
}" + ParameterSource;
VerifyCSharpDiagnostic(test);
}
@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test
[Parameter] protected string MyPropertyProtected { get; set; }
[Parameter] internal string MyPropertyInternal { get; set; }
}
}" + BlazorParameterSource;
}" + ParameterSource;
VerifyCSharpDiagnostic(test);
}
@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test
[Parameter] public string BadProperty1 { get; set; }
[Parameter] public object BadProperty2 { get; set; }
}
}" + BlazorParameterSource;
}" + ParameterSource;
VerifyCSharpDiagnostic(test,
new DiagnosticResult
@ -103,7 +103,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test
[Parameter] string BadProperty1 { get; set; }
[Parameter] object BadProperty2 { get; set; }
}
}" + BlazorParameterSource);
}" + ParameterSource);
}
[Fact]
@ -120,7 +120,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test
[Parameter] public object MyProperty2 { get; protected set; }
[Parameter] public object MyProperty2 { get; internal set; }
}
}" + BlazorParameterSource;
}" + ParameterSource;
VerifyCSharpDiagnostic(test);
}

View File

@ -78,3 +78,15 @@ namespace Microsoft.AspNetCore.Blazor.Services
public static void NotifyLocationChanged(string newAbsoluteUri) { }
}
}
namespace Microsoft.AspNetCore.Components.Builder
{
public static partial class ComponentsApplicationBuilderExtensions
{
public static void AddComponent<TComponent>(this Microsoft.AspNetCore.Components.Builder.IComponentsApplicationBuilder app, string domElementSelector) where TComponent : Microsoft.AspNetCore.Components.IComponent { }
}
public partial interface IComponentsApplicationBuilder
{
System.IServiceProvider Services { get; }
void AddComponent(System.Type componentType, string domElementSelector);
}
}

View File

@ -9,7 +9,7 @@ using System.Runtime.ExceptionServices;
using Microsoft.AspNetCore.Components.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Components.Hosting
namespace Microsoft.AspNetCore.Blazor.Hosting
{
// Keeping this simple for now to focus on predictable and reasonable behaviors.
// Startup in WebHost supports lots of things we don't yet support, and some we

View File

@ -5,7 +5,7 @@ using System;
using Microsoft.AspNetCore.Components.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Components.Hosting
namespace Microsoft.AspNetCore.Blazor.Hosting
{
internal interface IBlazorStartup
{

View File

@ -8,7 +8,6 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Blazor.Http;
using Microsoft.AspNetCore.Blazor.Rendering;
using Microsoft.AspNetCore.Components.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.JSInterop;

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Components.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.AspNetCore.Blazor.Hosting

View File

@ -11,9 +11,4 @@
<Reference Include="Microsoft.AspNetCore.Components.Browser" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(ComponentsSharedSourceRoot)src\ConventionBasedStartup.cs" Link="Hosting\ConventionBasedStartup.cs" />
<Compile Include="$(ComponentsSharedSourceRoot)src\IBlazorStartup.cs" Link="Hosting\IBlazorStartup.cs" />
</ItemGroup>
</Project>

View File

@ -6,7 +6,10 @@
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
<Compile Include="Microsoft.AspNetCore.Blazor.Server.netcoreapp3.0.cs" />
<Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
<Reference Include="Microsoft.AspNetCore.SpaServices.Extensions" />
<Reference Include="Microsoft.AspNetCore.StaticFiles" />
<Reference Include="Microsoft.AspNetCore.WebSockets" />
<Reference Include="Microsoft.Extensions.FileProviders.Embedded" />
<Reference Include="Newtonsoft.Json" />
<Reference Include="Mono.Cecil" />
</ItemGroup>

View File

@ -3,8 +3,18 @@
namespace Microsoft.AspNetCore.Builder
{
public static partial class BlazorApplicationBuilderExtensions
{
public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseBlazor(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Builder.BlazorOptions options) { throw null; }
public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseBlazor<TProgram>(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) { throw null; }
}
public static partial class BlazorMonoDebugProxyAppBuilderExtensions
{
public static void UseBlazorDebugging(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) { }
}
public partial class BlazorOptions
{
public BlazorOptions() { }
public string ClientAssemblyPath { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
}

View File

@ -1,15 +1,15 @@
// 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 Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Components.Server.AutoRebuild;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Blazor.Server;
using Microsoft.AspNetCore.Blazor.Server.AutoRebuild;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Builder
{

View File

@ -1,10 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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.Threading.Tasks;
namespace Microsoft.AspNetCore.Components.Server.AutoRebuild
namespace Microsoft.AspNetCore.Blazor.Server.AutoRebuild
{
/// <summary>
/// Represents a mechanism for rebuilding a .NET project. For example, it

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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;
@ -6,7 +6,7 @@ using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Microsoft.AspNetCore.Components.Server.AutoRebuild
namespace Microsoft.AspNetCore.Blazor.Server.AutoRebuild
{
internal static class ProcessUtils
{

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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;
@ -6,7 +6,7 @@ using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Components.Server.AutoRebuild
namespace Microsoft.AspNetCore.Blazor.Server.AutoRebuild
{
internal static class StreamProtocolExtensions
{

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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;
@ -7,7 +7,7 @@ using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Components.Server.AutoRebuild
namespace Microsoft.AspNetCore.Blazor.Server.AutoRebuild
{
/// <summary>
/// Finds the VS process that launched this app process (if any), and uses

View File

@ -5,7 +5,7 @@ using System;
using System.IO;
using System.Linq;
namespace Microsoft.AspNetCore.Components.Server
namespace Microsoft.AspNetCore.Blazor.Server
{
internal class BlazorConfig
{

View File

@ -1,15 +1,14 @@
// 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 Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Net.Http.Headers;
using System.Net.Mime;
using System;
using System.IO;
using System.Net.Mime;
using Microsoft.AspNetCore.Blazor.Server;
using Microsoft.Extensions.FileProviders;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Hosting;
namespace Microsoft.AspNetCore.Builder
@ -70,7 +69,7 @@ namespace Microsoft.AspNetCore.Builder
{
FileProvider = new PhysicalFileProvider(config.DistPath),
ContentTypeProvider = CreateContentTypeProvider(config.EnableDebugging),
OnPrepareResponse = SetCacheHeaders
OnPrepareResponse = CacheHeaderSettings.SetCacheHeaders,
});
// * Before publishing, we serve the wwwroot files directly from source
@ -84,7 +83,7 @@ namespace Microsoft.AspNetCore.Builder
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(config.WebRootPath),
OnPrepareResponse = SetCacheHeaders
OnPrepareResponse = CacheHeaderSettings.SetCacheHeaders,
});
}
@ -97,7 +96,7 @@ namespace Microsoft.AspNetCore.Builder
? null : new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.GetDirectoryName(indexHtmlPath)),
OnPrepareResponse = SetCacheHeaders
OnPrepareResponse = CacheHeaderSettings.SetCacheHeaders,
};
childAppBuilder.UseSpa(spa =>
@ -136,24 +135,6 @@ namespace Microsoft.AspNetCore.Builder
return null;
}
internal static void SetCacheHeaders(StaticFileResponseContext ctx)
{
// By setting "Cache-Control: no-cache", we're allowing the browser to store
// a cached copy of the response, but telling it that it must check with the
// server for modifications (based on Etag) before using that cached copy.
// Longer term, we should generate URLs based on content hashes (at least
// for published apps) so that the browser doesn't need to make any requests
// for unchanged files.
var headers = ctx.Context.Response.GetTypedHeaders();
if (headers.CacheControl == null)
{
headers.CacheControl = new CacheControlHeaderValue
{
NoCache = true
};
}
}
private static bool IsNotFrameworkDir(HttpContext context)
=> !context.Request.Path.StartsWithSegments("/_framework");

View File

@ -6,10 +6,16 @@
<IsShippingPackage>true</IsShippingPackage>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(ComponentsSharedSourceRoot)\src\CacheHeaderSettings.cs" Link="Shared\CacheHeaderSettings.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
<Reference Include="Microsoft.AspNetCore.SpaServices.Extensions" />
<Reference Include="Microsoft.AspNetCore.StaticFiles" />
<Reference Include="Microsoft.AspNetCore.WebSockets" />
<Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
<Reference Include="Microsoft.Extensions.FileProviders.Embedded" />
<Reference Include="Newtonsoft.Json" />
<!-- Used by ws-proxy sources only. Remove this once we're able to consume ws-proxy as a NuGet package. -->

View File

@ -10,7 +10,7 @@
<ItemGroup>
<Reference Include="Microsoft.AspNetCore" />
<Reference Include="Microsoft.AspNetCore.Components.Server" />
<Reference Include="Microsoft.AspNetCore.Blazor.Server" />
</ItemGroup>
</Project>

View File

@ -23,13 +23,13 @@ namespace Microsoft.AspNetCore.Components.Browser
// By default the registry will be set to a default value. This means that
// things will 'just work when running in the browser.
//
// Running in Server-Side Blazor - any call into the Circuit will set this value via
// Running in Server-Side Components - any call into the Circuit will set this value via
// the async local. This will ensure that the incoming call can resolve the correct
// renderer associated with the user context.
static RendererRegistry()
{
_current = new AsyncLocal<RendererRegistry>();
_globalRegistry = new RendererRegistry();
_globalRegistry = new RendererRegistry();
}
/// <summary>

View File

@ -207,7 +207,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Ne
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.JsonPatch", "..\Features\JsonPatch\src\Microsoft.AspNetCore.JsonPatch.csproj", "{DC47C40A-FC38-44E4-94A4-ADE794E76309}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.VisualStudio.BlazorExtension", "blazor\BlazorExtension\src\Microsoft.VisualStudio.BlazorExtension.csproj", "{9088E4E4-B855-457F-AE9E-D86709A5E1F4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.VisualStudio.BlazorExtension", "blazor\BlazorExtension\src\Microsoft.VisualStudio.BlazorExtension.csproj", "{9088E4E4-B855-457F-AE9E-D86709A5E1F4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BB236B66-28C0-49DD-9CD4-C4673CD4E7B4}"
ProjectSection(SolutionItems) = preProject
..\..\.editorconfig = ..\..\.editorconfig
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Components.Performance
renderer = new FakeRenderer();
// A simple component for basic tests -- this is similar to what MVC scaffolding generates
// for bootstrap3 form fields, but modified to be more Blazorey.
// for bootstrap3 form fields, but modified to be more Component-like.
original = new RenderTreeBuilder(renderer);
original.OpenElement(0, "div");
original.AddAttribute(1, "class", "form-group");
@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Components.Performance
modified.AddAttribute(5, "data-unvalidated", false);
modified.AddContent(6, "Car");
modified.CloseElement();
modified.OpenElement(7, "input");
modified.AddAttribute(8, "class", "form-control");
modified.AddAttribute(9, "type", "text");
@ -67,12 +67,12 @@ namespace Microsoft.AspNetCore.Components.Performance
modified.AddAttribute(11, "data-validation-state", "invalid");
modified.AddAttribute(12, "value", "Lamborghini");
modified.CloseElement();
modified.OpenElement(13, "span");
modified.AddAttribute(14, "class", "text-danger field-validation-invalid"); // changed
modified.AddContent(15, "No, you can't afford that.");
modified.CloseElement();
modified.CloseElement();
}

View File

@ -615,18 +615,6 @@ namespace Microsoft.AspNetCore.Components
public double DeltaZ { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
}
namespace Microsoft.AspNetCore.Components.Builder
{
public static partial class ComponentsApplicationBuilderExtensions
{
public static void AddComponent<TComponent>(this Microsoft.AspNetCore.Components.Builder.IComponentsApplicationBuilder app, string domElementSelector) where TComponent : Microsoft.AspNetCore.Components.IComponent { }
}
public partial interface IComponentsApplicationBuilder
{
System.IServiceProvider Services { get; }
void AddComponent(System.Type componentType, string domElementSelector);
}
}
namespace Microsoft.AspNetCore.Components.Forms
{
public partial class DataAnnotationsValidator : Microsoft.AspNetCore.Components.ComponentBase

View File

@ -1,9 +1,9 @@
// 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 Microsoft.AspNetCore.Components.RenderTree;
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.RenderTree;
namespace Microsoft.AspNetCore.Components
{

View File

@ -14,22 +14,22 @@ namespace Microsoft.AspNetCore.Components
internal static class ComponentResolver
{
/// <summary>
/// Lists all the types
/// Lists all the types
/// </summary>
/// <param name="appAssembly"></param>
/// <returns></returns>
public static IEnumerable<Type> ResolveComponents(Assembly appAssembly)
{
var blazorAssembly = typeof(IComponent).Assembly;
var componentsAssembly = typeof(IComponent).Assembly;
return EnumerateAssemblies(appAssembly.GetName(), blazorAssembly, new HashSet<Assembly>(new AssemblyComparer()))
return EnumerateAssemblies(appAssembly.GetName(), componentsAssembly, new HashSet<Assembly>(new AssemblyComparer()))
.SelectMany(a => a.ExportedTypes)
.Where(t => typeof(IComponent).IsAssignableFrom(t));
}
private static IEnumerable<Assembly> EnumerateAssemblies(
AssemblyName assemblyName,
Assembly blazorAssembly,
Assembly componentAssembly,
HashSet<Assembly> visited)
{
var assembly = Assembly.Load(assemblyName);
@ -40,9 +40,9 @@ namespace Microsoft.AspNetCore.Components
}
visited.Add(assembly);
var references = assembly.GetReferencedAssemblies();
if (!references.Any(r => string.Equals(r.FullName, blazorAssembly.FullName, StringComparison.Ordinal)))
if (!references.Any(r => string.Equals(r.FullName, componentAssembly.FullName, StringComparison.Ordinal)))
{
// Avoid traversing references that don't point to blazor (like netstandard2.0)
// Avoid traversing references that don't point to Components (like netstandard2.0)
yield break;
}
else
@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.Components
yield return assembly;
// Look at the list of transitive dependencies for more components.
foreach (var reference in references.SelectMany(r => EnumerateAssemblies(r, blazorAssembly, visited)))
foreach (var reference in references.SelectMany(r => EnumerateAssemblies(r, componentAssembly, visited)))
{
yield return reference;
}

View File

@ -163,7 +163,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
}
// We have to block. That's the contract of Send - we don't expect this to be used
// in many scenarios in Blazor.
// in many scenarios in Components.
//
// Using Wait here is ok because the antecedant task will never throw.
antecedant.Wait();

View File

@ -2513,7 +2513,7 @@ namespace Microsoft.AspNetCore.Components.Test
{
// This represents the scenario where the same event handler is being triggered
// rapidly, such as an input event while typing. It only applies to asynchronous
// batch updates, i.e., server-side Blazor.
// batch updates, i.e., server-side Components.
// Sequence:
// 1. The client dispatches event X twice (say) in quick succession
// 2. The server receives the first instance, handles the event, and re-renders

View File

@ -10,7 +10,7 @@ using Interop = Microsoft.AspNetCore.Components.Browser.BrowserUriHelperInterop;
namespace Microsoft.AspNetCore.Components.Server.Circuits
{
/// <summary>
/// A Server-Side Blazor implementation of <see cref="IUriHelper"/>.
/// A Server-Side Components implementation of <see cref="IUriHelper"/>.
/// </summary>
public class RemoteUriHelper : UriHelperBase
{

View File

@ -44,14 +44,14 @@ namespace Microsoft.AspNetCore.Components.Server
var prepareResponse = options.OnPrepareResponse;
if (prepareResponse == null)
{
options.OnPrepareResponse = BlazorApplicationBuilderExtensions.SetCacheHeaders;
options.OnPrepareResponse = CacheHeaderSettings.SetCacheHeaders;
}
else
{
void PrepareResponse(StaticFileResponseContext context)
{
prepareResponse(context);
BlazorApplicationBuilderExtensions.SetCacheHeaders(context);
CacheHeaderSettings.SetCacheHeaders(context);
}
options.OnPrepareResponse = PrepareResponse;

View File

@ -13,19 +13,23 @@
<IsPackable>false</IsPackable>
<GenerateEmbeddedFilesManifest>false</GenerateEmbeddedFilesManifest>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(ComponentsSharedSourceRoot)\src\ConventionBasedStartup.cs" Link="Hosting\ConventionBasedStartup.cs" />
<Compile Include="$(ComponentsSharedSourceRoot)\src\IBlazorStartup.cs" Link="Hosting\IBlazorStartup.cs" />
<Compile Include="$(ComponentsSharedSourceRoot)\src\CacheHeaderSettings.cs" Link="Shared\CacheHeaderSettings.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Components.Browser" />
<Reference Include="Microsoft.AspNetCore.SignalR" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" />
<Reference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" />
<Reference Include="Microsoft.AspNetCore.StaticFiles" />
<Reference Include="Microsoft.AspNetCore.SpaServices.Extensions" />
<Reference Include="Microsoft.Extensions.FileProviders.Composite" />
<Reference Include="Microsoft.Extensions.FileProviders.Embedded" />
<!--
Temporary until we move the prerendering APIs into this assembly.
-->
<Reference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" />
</ItemGroup>
<ItemGroup Condition="'$(BuildNodeJS)' != 'false'">

View File

@ -0,0 +1,29 @@
// 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 Microsoft.AspNetCore.Http;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNetCore.StaticFiles
{
internal static class CacheHeaderSettings
{
internal static void SetCacheHeaders(StaticFileResponseContext ctx)
{
// By setting "Cache-Control: no-cache", we're allowing the browser to store
// a cached copy of the response, but telling it that it must check with the
// server for modifications (based on Etag) before using that cached copy.
// Longer term, we should generate URLs based on content hashes (at least
// for published apps) so that the browser doesn't need to make any requests
// for unchanged files.
var headers = ctx.Context.Response.GetTypedHeaders();
if (headers.CacheControl == null)
{
headers.CacheControl = new CacheControlHeaderValue
{
NoCache = true
};
}
}
}
}

View File

@ -1,133 +0,0 @@
// 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.
namespace Microsoft.AspNetCore.Components.Shared
{
// Constants for method names used in code-generation
// Keep these in sync with the actual definitions
internal static class ComponentsApi
{
public static readonly string AssemblyName = "Microsoft.AspNetCore.Components";
public static class ComponentBase
{
public static readonly string Namespace = "Microsoft.AspNetCore.Components";
public static readonly string FullTypeName = Namespace + ".ComponentBase";
public static readonly string MetadataName = FullTypeName;
public static readonly string BuildRenderTree = nameof(BuildRenderTree);
}
public static class ParameterAttribute
{
public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.ParameterAttribute";
public static readonly string MetadataName = FullTypeName;
}
public static class LayoutAttribute
{
public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.Layouts.LayoutAttribute";
}
public static class InjectAttribute
{
public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.InjectAttribute";
}
public static class IComponent
{
public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.IComponent";
public static readonly string MetadataName = FullTypeName;
}
public static class IDictionary
{
public static readonly string MetadataName = "System.Collection.IDictionary`2";
}
public static class RenderFragment
{
public static readonly string Namespace = "Microsoft.AspNetCore.Components";
public static readonly string FullTypeName = Namespace + ".RenderFragment";
public static readonly string MetadataName = FullTypeName;
}
public static class RenderFragmentOfT
{
public static readonly string Namespace = "Microsoft.AspNetCore.Components";
public static readonly string FullTypeName = Namespace + ".RenderFragment<>";
public static readonly string MetadataName = Namespace + ".RenderFragment`1";
}
public static class RenderTreeBuilder
{
public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder";
public static readonly string OpenElement = nameof(OpenElement);
public static readonly string CloseElement = nameof(CloseElement);
public static readonly string OpenComponent = nameof(OpenComponent);
public static readonly string CloseComponent = nameof(CloseComponent);
public static readonly string AddMarkupContent = nameof(AddMarkupContent);
public static readonly string AddContent = nameof(AddContent);
public static readonly string AddAttribute = nameof(AddAttribute);
public static readonly string AddElementReferenceCapture = nameof(AddElementReferenceCapture);
public static readonly string AddComponentReferenceCapture = nameof(AddComponentReferenceCapture);
public static readonly string Clear = nameof(Clear);
public static readonly string GetFrames = nameof(GetFrames);
public static readonly string ChildContent = nameof(ChildContent);
}
public static class RuntimeHelpers
{
public static readonly string TypeCheck = "Microsoft.AspNetCore.Components.RuntimeHelpers.TypeCheck";
}
public static class RouteAttribute
{
public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.RouteAttribute";
}
public static class BindElementAttribute
{
public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.BindElementAttribute";
}
public static class BindInputElementAttribute
{
public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.BindInputElementAttribute";
}
public static class BindMethods
{
public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.BindMethods";
public static readonly string GetValue = "Microsoft.AspNetCore.Components.BindMethods.GetValue";
public static readonly string GetEventHandlerValue = "Microsoft.AspNetCore.Components.BindMethods.GetEventHandlerValue";
public static readonly string SetValueHandler = "Microsoft.AspNetCore.Components.BindMethods.SetValueHandler";
}
public static class EventHandlerAttribute
{
public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.EventHandlerAttribute";
}
public static class ElementRef
{
public static readonly string FullTypeName = "Microsoft.AspNetCore.Components.ElementRef";
}
}
}

View File

@ -37,8 +37,16 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures
private static Dictionary<string, string> FindProjects()
{
var solutionDir = FindSolutionDir();
return Directory.GetFiles(solutionDir, "*.csproj", SearchOption.AllDirectories)
.ToDictionary(Path.GetFileNameWithoutExtension, Path.GetDirectoryName);
var testAssetsDirectories = new[]
{
Path.Combine(solutionDir, "test", "testassets"),
Path.Combine(solutionDir, "blazor", "testassets"),
};
return testAssetsDirectories
.SelectMany(d => new DirectoryInfo(d).EnumerateDirectories())
.ToDictionary(d => d.Name, d => d.FullName);
}
protected static string FindSampleOrTestSitePath(string projectName)

View File

@ -318,11 +318,11 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
{
var appElement = MountTestComponent<ExternalContentPackage>();
// NuGet packages can use Blazor's JS interop features to provide
// NuGet packages can use JS interop features to provide
// .NET code access to browser APIs
var showPromptButton = appElement.FindElements(By.TagName("button")).First();
showPromptButton.Click();
var modal = new WebDriverWait(Browser, TimeSpan.FromSeconds(3))
.Until(SwitchToAlert);
modal.SendKeys("Some value from test");
@ -330,14 +330,14 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
var promptResult = appElement.FindElement(By.TagName("strong"));
WaitAssert.Equal("Some value from test", () => promptResult.Text);
// NuGet packages can also embed entire Blazor components (themselves
// NuGet packages can also embed entire components (themselves
// authored as Razor files), including static content. The CSS value
// here is in a .css file, so if it's correct we know that static content
// file was loaded.
var specialStyleDiv = appElement.FindElement(By.ClassName("special-style"));
Assert.Equal("50px", specialStyleDiv.GetCssValue("padding"));
// The external Blazor components are fully functional, not just static HTML
// The external components are fully functional, not just static HTML
var externalComponentButton = specialStyleDiv.FindElement(By.TagName("button"));
Assert.Equal("Click me", externalComponentButton.Text);
externalComponentButton.Click();

View File

@ -1,12 +1,10 @@
// 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.Runtime.InteropServices;
using Microsoft.AspNetCore.Blazor.Http;
using Microsoft.AspNetCore.Blazor.Services;
using Microsoft.AspNetCore.Components.Builder;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Runtime.InteropServices;
namespace BasicTestApp
{

View File

@ -2,4 +2,4 @@
Configuring this stuff here is temporary. Later we'll move the app config
into Startup.cs, and it won't be necessary to specify AppAssembly.
-->
<Router AppAssembly=typeof(ComponentsApp.App.Startup).Assembly />
<Router AppAssembly=typeof(ComponentsApp.App.App).Assembly />

View File

@ -5,9 +5,6 @@
</div>
<div class="main">
@*<div class="top-row px-4">
<a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a>
</div>*@
<div class="content px-4">
@Body

View File

@ -1,20 +0,0 @@
// 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 Microsoft.AspNetCore.Components.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace ComponentsApp.App
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IComponentsApplicationBuilder app)
{
app.AddComponent<App>("app");
}
}
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
@ -6,6 +6,7 @@
<ItemGroup>
<Reference Include="Microsoft.AspNetCore" />
<Reference Include="Microsoft.AspNetCore.Blazor.Server" />
<Reference Include="Microsoft.AspNetCore.Cors" />
<Reference Include="Microsoft.AspNetCore.Mvc" />
<Reference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" />

View File

@ -478,18 +478,18 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
// Act
var response = await Client.GetStringAsync("Home/GetAssemblyPartData");
var assemblyParts = JsonConvert.DeserializeObject<IList<string>>(response);
var expected = new[]
{
"BasicWebSite",
"Microsoft.AspNetCore.Components.Server",
"Microsoft.AspNetCore.SpaServices",
"Microsoft.AspNetCore.SpaServices.Extensions",
"Microsoft.AspNetCore.Mvc.TagHelpers",
"Microsoft.AspNetCore.Mvc.Razor",
};
// Assert
Assert.Equal(expected, assemblyParts);
//
// We don't keep track the explicit list of assemblies that show up here
// because this can change as we work on the product. All we care about is
// that BasicWebSite is first, and that everything after it is a Microsoft.
Assert.True(assemblyParts.Count > 2);
Assert.Equal("BasicWebSite", assemblyParts[0]);
for (var i = 1; i < assemblyParts.Count; i++)
{
Assert.StartsWith("Microsoft.", assemblyParts[i]);
}
}
[Fact]