简体   繁体   中英

ASP.Net Core RouteBuilder and Dependency Injection

I'm experimenting with routing in ASP.NET Core 2.0. I have a class that wraps the System.DateTime.UtcNow functionality (for simpler Unit Testing)

public interface IDateTimeWrapper
{
    DateTime UtcNow();
}

public sealed class DateTimeWrapper : IDateTimeWrapper
{
    public DateTime UtcNow()
    {
        return DateTime.UtcNow;
    }
}

This is used by a class that has a single method Execute which writes the result of the DateTimeWrapper to the HttpResponse

public class WhatIsTheTimeHandler
{
    private readonly IDateTimeWrapper _dateTimeWrapper;

    public WhatIsTheTimeHandler(
        IDateTimeWrapper dateTimeWrapper)
    {
        this._dateTimeWrapper = dateTimeWrapper;
    }

    public async Task Execute(Microsoft.AspNetCore.Http.HttpContext httpContext)
    {
        httpContext.Response.StatusCode = 200;            
        await httpContext.Response.WriteAsync(this._dateTimeWrapper.UtcNow().ToString());
    }
}

In Startup I want any requests going to /whatisthetime/ to be handled by the WhatIsTheTimeHandler (see the !!! comment).

public sealed class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder();

        builder.SetBasePath(env.ContentRootPath);
        builder.AddJsonFile("appsettings.json", false, true);
        // we must lowercase the json file path due to linux file name case sensitivity
        builder.AddJsonFile($"appsettings.{env.EnvironmentName.ToLower()}.json", false, true);
        builder.AddEnvironmentVariables();

        this.Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; set; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRouting();

        services.AddScoped<IDateTimeWrapper, DateTimeWrapper>();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        var routeBuilder = new Microsoft.AspNetCore.Routing.RouteBuilder(app);

        // !!!
        // I want to do something like
        // routeBuilder.MapGet("whatisthetime", WhatIsTheTimeHandler.Execute);

        var routes = routeBuilder.Build();
        app.UseRouter(routes);
    }
}

I can't do what I want above because WhatIsTheTimeHandler.Execute is an instance method. Ie the error:

An object reference is required for the non-static field, method or property 'WhatIsTheTimeHandler.Execute(HttpContext)' Cannot access non-static method in static context).

If I make it static then I won't be able to use the _dateTimeWrapper instance member.

Any ideas?

ASP.NET Core routing maps routes to delegates. ASP.NET MVC Core routing maps routes to objects (commonly referred to as controllers). So the latter is probably the better solution to your particularly needs.

However, to make your current solution work you would need to add the handler as a service:

services.AddScoped<WhatIsTheTimeHandler>();

then invoke this from within the route, eg:

routeBuilder.MapGet("whatisthetime", async (context) => {
    await context.RequestServices.GetRequiredService<WhatIsTheTimeHandler>().Execute(context);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM