c# asp.net-core asp.net-core-2.0 urlhelper asp-net-core-mvc-2.0

c# - ASP.Net Core 2.0: crear UrlHelper sin solicitud



asp.net-core asp.net-core-2.0 (0)

Estoy trabajando en la creación de un UrlHelper para que un trabajador en segundo plano pueda crear URL de devolución de llamada, lo que significa que no es parte de una solicitud normal en la que podría solicitarla a través de DI.

En ASP.Net 5 podría simplemente crear una HttpRequest y darle la misma HttpConfiguration que usé para construir mi aplicación, pero en ASP.Net Core 2.0 el UrlHelper depende de un ActionContext completo que es un poco más difícil de crear.

Tengo un prototipo en funcionamiento, pero está utilizando un hack desagradable para contrabandear los datos de ruta fuera del proceso de inicio de la aplicación. ¿Hay una mejor manera de hacer esto?

public class Capture { public IRouter Router { get; set; } } public static class Ext { // Step 1: Inject smuggler when building web host public static IWebHostBuilder SniffRouteData(this IWebHostBuilder builder) { return builder.ConfigureServices(svc => svc.AddSingleton<Capture>()); } // Step 2: Swipe the route data in application startup public static IApplicationBuilder UseMvcAndSniffRoutes(this IApplicationBuilder app) { var capture = app.ApplicationServices.GetRequiredService<Capture>(); IRouteBuilder capturedRoutes = null; app.UseMvc(routeBuilder => capturedRoutes = routeBuilder); capture.Router = capturedRoutes?.Build(); return app; } // Step 3: Build the UrlHelper using the captured routes and webhost public static IUrlHelper GetStaticUrlHelper(this IWebHost host, string baseUri) => GetStaticUrlHelper(host, new Uri(baseUri)); public static IUrlHelper GetStaticUrlHelper(this IWebHost host, Uri baseUri) { HttpContext httpContext = new DefaultHttpContext() { RequestServices = host.Services, Request = { Scheme = baseUri.Scheme, Host = HostString.FromUriComponent(baseUri), PathBase = PathString.FromUriComponent(baseUri), }, }; var captured = host.Services.GetRequiredService<Capture>(); var actionContext = new ActionContext { HttpContext = httpContext, RouteData = new RouteData { Routers = { captured.Router }}, ActionDescriptor = new ActionDescriptor(), }; return new UrlHelper(actionContext); } } // Based on dotnet new webapi public class Program { public static void Main(string[] args) { BuildWebHost(args);//.Run(); } public static IWebHost BuildWebHost(string[] args) { var captured = new Capture(); var webhost = WebHost.CreateDefaultBuilder(args) .SniffRouteData() .UseStartup<Startup>() .Build(); var urlHelper = webhost.GetStaticUrlHelper("https://my.internal.service:48923/somepath"); Console.WriteLine("YO! " + urlHelper.Link(nameof(ValuesController), null)); return webhost; } } public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddMvc(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, Capture capture) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvcAndSniffRoutes(); } } [Route("api/[controller]", Name = nameof(ValuesController))] public class ValuesController : Controller { // GET api/values [HttpGet] public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } // etc }