寻找一种方法让 类 自动将自己注册为端点

Looking for a way to have classes auto register themselves as an Endpoint

我正在将围绕通用处理程序构建的 .NET Framework 4.8 Web 应用程序转换为 .NET Core 3.1 Web 应用程序。

我正在为我的每个自定义页面 class 寻找一种方法,以便能够在启动阶段将自己自动注册为端点。现在它是一个我想简化的手动过程。

这就是我目前正在使用的内容。

using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.FileProviders;

namespace App
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseStaticFiles();
            app.UseStaticFiles(StaticFolder("/Resources"));
            app.UseStaticFiles(StaticFolder("/Clients"));

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", Page<Default>);

                endpoints.MapGet("/Login.ashx", Page<Login>);
                endpoints.MapPost("/LoginPostBack.ashx", Page<LoginPostBack>);
                endpoints.MapGet("/Logout.ashx", Page<Logout>);
                endpoints.MapPost("/LogoutPostBack.ashx", Page<LogoutPostBack>);

                endpoints.MapGet("/Clients/", Page<Clients.Default>);
                endpoints.MapPost("/Clients/", Page<Clients.DefaultPostBack>);
                endpoints.MapGet("/Clients/Add.ashx", Page<Clients.Add>);
                endpoints.MapPost("/Clients/AddPostBack.ashx", Page<Clients.AddPostBack>);
                endpoints.MapGet("/Clients/Modify.ashx", Page<Clients.Modify>);
                endpoints.MapPost("/Clients/ModifyPostBack.ashx", Page<Clients.ModifyPostBack>);
                endpoints.MapGet("/Clients/Delete.ashx", Page<Clients.Delete>);
                endpoints.MapPost("/Clients/DeletePostBack.ashx", Page<Clients.DeletePostBack>);
            });
        }

        private async Task Page<T>(HttpContext context) where T : new()
        {
            T page = new T();
            await ((IPage)page).ProcessRequest(context);
        }

        private StaticFileOptions StaticFolder(string path)
        {
            return new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), path.Substring(1))),
                RequestPath = path
            };
        }
    }
}

下面是自定义页面的示例 class:

using System.Web;

namespace App
{
    public class Default : FormPage
    {
        protected override void PreProcess()
        {
            Page.Icon = "far fa-home";
            Page.Title = "Home";
        }

        protected override void Process()
        {
            Write(@"<div class=""row mb-4"">");

            Write(@"<div class=""col-12"">");
            Write(@"<h5>Home</h5>");
            Write(@"</div>");

            Write(@"</div>");
        }
    }
}

这里的问题是您试图维护以 ashx 结尾的 URL,即使这在 ASP.NET Core 中没有任何意义。 Razor Pages 有关于 URL 结构的默认约定,除了 ashx.

之外,这与这里的 URL 几乎一致

如果您只是想维护现有的 URL 结构(没有 404),正确的做法是创建永久重定向,例如Login.ashxLogin。然后,默认的基于约定的路由就可以正常工作,如果有人确实去了旧的 URL,他们只会被重定向到新的。

我用反射解决了它:

app.UseEndpoints(endpoints =>
{
    foreach (Type pageType in Assembly.GetExecutingAssembly().DefinedTypes)
        if (typeof(IPage).IsAssignableFrom(pageType))
        {
            IPage pageInstance = (IPage)Activator.CreateInstance(pageType);

            MethodInfo pageMethod = typeof(Startup).GetMethod("Page");
            MethodInfo delegateMethod = pageMethod.MakeGenericMethod(pageType);
            RequestDelegate requestDelegate = (RequestDelegate)RequestDelegate.CreateDelegate(typeof(RequestDelegate), this, delegateMethod);

            endpoints.MapGet(pageInstance.Endpoint, requestDelegate);
        }
});