2017-09-07 19 views
14

मैं पृष्ठभूमि कार्यकर्ता के लिए कॉलबैक यूआरएल बनाने के लिए एक UrlHelper बनाने पर काम कर रहा हूं, जिसका अर्थ यह है कि यह सामान्य अनुरोध का हिस्सा नहीं है जहां मैं इसे DI के माध्यम से पूछ सकता हूं।एएसपी.Net कोर 2.0: अनुरोध के बिना UrlHelper बनाना

ASP.Net 5 में मैं सिर्फ एक HttpRequest बना सकते हैं और यह एक ही HttpConfiguration मैं अपने ऐप बनाने के लिए उपयोग दे, लेकिन ASP.Net कोर 2.0 में UrlHelper एक पूर्ण ActionContext जो एक सा शिल्प के लिए कठिन है पर निर्भर करता है।

मेरे पास एक कामकाजी प्रोटोटाइप है, लेकिन यह एप्लिकेशन स्टार्टअप प्रक्रिया से रूट डेटा को धुंधला करने के लिए एक बुरा हैक का उपयोग कर रहा है। क्या ऐसा करने के लिए इससे अच्छा तरीका है?

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 
} 
+0

यह एक भयानक विचार हो सकता है, लेकिन आप केवल नहीं बचा सकता * किसी * एक अनुरोध ताकि आप पृष्ठभूमि धागे से इसे का उपयोग जारी रख सकते हैं के दौरान बनाया UrlHelper? तो, आप उस धागे को शुरू करेंगे * बाद में पहला अनुरोध किया गया है? – poke

+0

क्या आपके पास यह जांचने का मौका था? https://stackoverflow.com/questions/37322076/injection-of-iurlhelper-in-asp-net-core-1-0-rc2 –

+0

@poke, जो शायद काम करेगा, लेकिन इसमें स्पष्ट कमीएं हैं, इसलिए मैं चाहता हूं केवल अंतिम उपाय के रूप में उपयोग करें। – Stylpe

उत्तर

1

स्रोतों को ब्राउज़ करना ऐसा लगता है कि कोई कम हैकी समाधान नहीं है।

UseMvc() विधि में आईआरओटर ऑब्जेक्ट बनाया जा रहा है passed to the RouterMiddleware, जो stores it in a private field है और केवल अनुरोधों को उजागर करता है। तो प्रतिबिंब आपका एकमात्र अन्य विकल्प होगा, जो स्पष्ट रूप से चलने से बाहर है।

हालांकि, यदि आपको IUrlHelper.Content() का उपयोग करके केवल स्थिर पथ उत्पन्न करने की आवश्यकता है, तो आपको default implementation won't use it के रूप में राउटर की आवश्यकता नहीं होगी। इस मामले में आप इस तरह सहायक बना सकते हैं:

var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); 
var urlHelper = new UrlHelper(actionContext); 
+0

यह वही निष्कर्ष है जो मुझे मिला, जो मेरे प्रश्न में कामकाज का कारण बनता है। और सामग्री() के बारे में अच्छी बात है, लेकिन हम एक नामित नियंत्रक कार्रवाई से लिंक करना चाहते हैं। यह पुष्टि करने के लिए धन्यवाद :) मेरा अगला कदम शायद यह आसान बनाने के लिए गिथब पर एक मुद्दा तैयार करने का प्रयास करेगा। – Stylpe