我正在努力为后台工作者创建一个urlhelper创建回调URL,这意味着它不是正常请求的一部分,我可以通过DI来要求它。
在ASP.NET 5中,我可以创建一个httprequest,并给它与我用来构建应用程序的httpConfiguration相同,但是在ASP.NET CORE 2.0中,urlhelper依赖于完整的动作依赖于一个完整的ActionContext,这更难制作。/p>
我有一个有效的原型,但是它使用了一个讨厌的黑客将路由数据从应用程序启动过程中走私出来。有更好的方法吗?
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
}
浏览源似乎也没有黑客解决方案。
在usemvc()方法中,构建的IRouter对象传递给Routermiddleware,该对象将其存储在私有字段中,并仅将其暴露于请求。因此,反思将是您唯一的其他选择,显然是在运行中。
但是,如果您只需要使用iurlhelper.content()仅生成静态路径,则不需要路由器,因为默认实现将不使用它。在这种情况下,您可以创建这样的助手:
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
var urlHelper = new UrlHelper(actionContext);
使用ASP.NET Core 2.2今天发布,他们添加了一个Linkgenerator类,听起来像是可以解决此问题(测试看起来很有希望)。我渴望尝试一下,但是由于目前我不积极地在需要的项目上工作,因此必须等一下。但是我足够乐观地将其标记为新答案。