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. I.e. 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, e.g.:
routeBuilder.MapGet("whatisthetime", async (context) => {
await context.RequestServices.GetRequiredService<WhatIsTheTimeHandler>().Execute(context);
});