diff --git a/samples/StandaloneApp/Index.cshtml b/samples/StandaloneApp/Index.cshtml new file mode 100644 index 0000000000..f731b5af5a --- /dev/null +++ b/samples/StandaloneApp/Index.cshtml @@ -0,0 +1,3 @@ +@inherits Microsoft.Blazor.Components.BlazorComponent +

Hello, world!

+Hello from the Razor component. diff --git a/samples/StandaloneApp/Program.cs b/samples/StandaloneApp/Program.cs index e5000876a7..4d441d31f5 100644 --- a/samples/StandaloneApp/Program.cs +++ b/samples/StandaloneApp/Program.cs @@ -4,7 +4,6 @@ using Microsoft.Blazor.Browser.Rendering; using Microsoft.Blazor.Components; using Microsoft.Blazor.RenderTree; -using System; namespace StandaloneApp { diff --git a/src/Microsoft.Blazor/Components/BlazorComponent.cs b/src/Microsoft.Blazor/Components/BlazorComponent.cs new file mode 100644 index 0000000000..b8cf2b560f --- /dev/null +++ b/src/Microsoft.Blazor/Components/BlazorComponent.cs @@ -0,0 +1,38 @@ +// 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.Blazor.RenderTree; +using System; +using System.Threading.Tasks; + +namespace Microsoft.Blazor.Components +{ + /// + /// Optional base class for Blazor components. Alternatively, Blazor components may + /// implement directly. + /// + public abstract class BlazorComponent : IComponent + { + /// + public virtual void BuildRenderTree(RenderTreeBuilder builder) + { + // This is virtual rather than abstract so that 'code behind' classes don't have to + // be marked abstract. + // Developers can either override this method in derived classes, or can use Razor + // syntax to define a derived class and have the compiler generate the method. + } + + // At present, if you have a .cshtml file in a project with , + // Visual Studio will run design-time builds for it, codegenning a class that attempts to override + // this method. Therefore the virtual method must be defined, even though it won't be used at runtime, + // because otherwise VS will display a design-time error in its 'Error List' pane. + // TODO: Track down what triggers the design-time build for .cshtml files and how to stop it, then + // this method can be removed. + /// + /// Not used. Do not invoke this method. + /// + /// Always throws an exception. + public virtual Task ExecuteAsync() + => throw new NotImplementedException($"Blazor components do not implement {nameof(ExecuteAsync)}."); + } +} diff --git a/src/Microsoft.Blazor/Components/RazorToolingWorkaround.cs b/src/Microsoft.Blazor/Components/RazorToolingWorkaround.cs new file mode 100644 index 0000000000..fd6207f0d5 --- /dev/null +++ b/src/Microsoft.Blazor/Components/RazorToolingWorkaround.cs @@ -0,0 +1,43 @@ +// 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. + +/* + * Currently if you have a .cshtml file in a project with , + * Visual Studio will run design-time builds for the .cshtml file that assume certain ASP.NET MVC + * APIs exist. Since those namespaces and types wouldn't normally exist for Blazor client apps, + * this leads to spurious errors in the Errors List pane, even though there aren't actually any + * errors on build. As a workaround, we define here a minimal set of namespaces/types that satisfy + * the design-time build. + * + * TODO: Track down what is triggering the unwanted design-time build and find out how to disable it. + * Then this file can be removed entirely. + */ + +using System; + +namespace Microsoft.AspNetCore.Mvc +{ + public interface IUrlHelper { } + public interface IViewComponentHelper { } +} + +namespace Microsoft.AspNetCore.Mvc.Razor +{ + public class RazorPage { } + + namespace Internal + { + public class RazorInjectAttributeAttribute : Attribute { } + } +} + +namespace Microsoft.AspNetCore.Mvc.Rendering +{ + public interface IJsonHelper { } + public interface IHtmlHelper { } +} + +namespace Microsoft.AspNetCore.Mvc.ViewFeatures +{ + public interface IModelExpressionProvider { } +}