Why is the presence of middleware preventing execution of an endpoint? - asp.net

I am a beginner at ASP.Net. Here is my startup.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using CAPSWebServer.CapsDataModels;
namespace CAPSWebServer
{
public class Startup
{
public IConfiguration Configuration { get; set; }
public Startup(IConfiguration config)
{
Configuration = config;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CapsDataContext>(opts =>
{
opts.UseNpgsql(Configuration["ConnectionStrings:CAPSConnection"]);
opts.EnableSensitiveDataLogging(true);
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseMiddleware<TestMiddleware>();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
}
}
And here is my TestMiddleware class:
using Microsoft.AspNetCore.Http;
using System.Linq;
using System.Threading.Tasks;
using CAPSWebServer.CapsDataModels;
namespace CAPSWebServer
{
public class TestMiddleware
{
private RequestDelegate nextDelegate;
public TestMiddleware(RequestDelegate next)
{
nextDelegate = next;
}
public async Task Invoke(HttpContext context, CapsDataContext dataContext)
{
if (context.Request.Path == "/test")
{
await context.Response.WriteAsync($"There are {dataContext.Charges.Count()} charges.\n");
await context.Response.WriteAsync($"There are {dataContext.Inventories.Count()} coils.\n");
}
}
}
}
This application is configured to listen on port 500 of my computer. When I run localhost:5000/test, I get the expected report of how many charges and coils I have in my database. But when I run localhost:5000 by itself, I get nothing. I think I should be getting "Hello, world". If I comment out out the call to UseMiddleware(), I get "Hello, world". Why does the middleware block the endpoint?
I am using Visual Studio 2019.

You need to call the
nextDelegate();
So that the next middleware down the line is executed.
The reason it works when the URL contains "/test" is because you are writing directly into the response stream.

Related

How can you add a Microsoft Graph client service as a MediatR service in .NET Core 3.1?

So I have a .NET Core web API with it's own local data context, and I'd like to add the ability to call Microsoft Graph as a downstream API.
However, when I try to add the necessary properties to call the Graph API, I get a build error:
Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: MediatR.IRequestHandler`2[Application.Users.Me+Query,Microsoft.Graph.User] Lifetime: Transient ImplementationType: Application.Users.Me+Handler': Unable to resolve service for type 'Microsoft.Graph.GraphServiceClient' while attempting to activate 'Application.Users.Me+Handler'.)
Here is my startup class:
using API.Middleware;
using Application.TestEntities;
using FluentValidation.AspNetCore;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Persistence;
using Microsoft.Identity.Web;
namespace API
{
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.AddDbContext<DataContext>(opt =>
{
opt.UseSqlite(Configuration.GetConnectionString("DefaultConnection"));
});
services.AddCors(opt =>
{
opt.AddPolicy("CorsPolicy", policy =>
{
policy.AllowAnyHeader().AllowAnyMethod().WithOrigins("http://localhost:3000");
});
});
services.AddMicrosoftIdentityWebApiAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
services.AddMediatR(typeof(List.Handler).Assembly);
services.AddControllers(opt =>
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
opt.Filters.Add(new AuthorizeFilter(policy));
})
.AddFluentValidation(cfg => cfg.RegisterValidatorsFromAssemblyContaining<Create>());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseMiddleware<ErrorHandlingMiddleware>();
if (env.IsDevelopment())
{
// app.UseDeveloperExceptionPage();
}
app.UseCors("CorsPolicy");
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
And my application handler for calling downstream:
using System.Threading;
using System.Threading.Tasks;
using MediatR;
using Microsoft.Graph;
using Microsoft.Identity.Web;
namespace Application.Users
{
public class Me
{
public class Query : IRequest<User> { }
public class Handler : IRequestHandler<Query, User>
{
private readonly ITokenAcquisition _tokenAcquisition;
private readonly GraphServiceClient _graphServiceClient;
public Handler(ITokenAcquisition tokenAcquisition, GraphServiceClient graphServiceClient)
{
_tokenAcquisition = tokenAcquisition;
_graphServiceClient = graphServiceClient;
}
public async Task<User> Handle(Query request, CancellationToken cancellationToken)
{
var user = await _graphServiceClient.Me.Request().GetAsync();
return user;
}
}
}
}
Hopefully I'm on the right track here, but please let me know if I'm not.
Right so this was a simple oversight on my part.
As per #franklores, you need to register Microsoft Graph in your startup class services:
services.AddMicrosoftIdentityWebApiAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
Adding the following to appsettings (scopes may differ):
"DownstreamAPI": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "user.read"
},
And be sure to install Microsoft.Identity.Web.MicrosoftGraph to enable the AddMicrosoftGraph() function.

Hyphens in route, works with link, doesn't work directly

I am trying to use hyphens in an URL route. In ASP.NET Core MVC. I setup a default MVC template.
The only thing I change is to add this first line:
[Route("hello-dude")]
public IActionResult Privacy()
{
return View();
}
Now, when I got to test the project, I click privacy and it shows the correct page and URL. (http://localhost:44386/hello-dude)
But when I go to the address bar and put that in manually, click enter, I get "site cannot be reached".
What is going on here?
Startup.Cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace WebApplication8
{
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.AddControllersWithViews();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}

Ocelot Caching : AddCacheManager Try specifying the type arguments explicitly error

New to Ocelot and .net core. I am trying to implement caching in .net core 3.0 microservice in Ocelot gateway. As per Ocelot guideline (https://ocelot.readthedocs.io/en/latest/features/caching.html)
As per second step, my startup.cs looks like:
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
namespace MS_APIGateway
{
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.AddOcelot().AddCacheManager(x => **// Getting error here**
{
x.WithDictionaryHandle();
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public async void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
//JWT
app.UseAuthentication();
//JWT
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
await app.UseOcelot();
}
}
}
The compiler is throwing error at AddCacheManager line and the error message is:
Error CS0411 The type arguments for method 'ServiceCollectionExtensions.AddCacheManager<T>(IServiceCollection, IConfiguration, string, Action<ConfigurationBuilder>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Please help. Thank you.
we have to add using Ocelot.Cache.CacheManager;

Missing startup.cs program.cs .Net Core Razor

I have a .Net Core 3 Web App using Razor pages. I was messing with solution explorer a few days ago and now I notice I'm missing startup.cs and program.cs. How can I restore them? I'm also getting this error: "Unable to run your project. The RunCommand property is not defined".
First I'd check to make sure your files are in the project directory before trying to rebuild them. If they are still in the directory you can add them to your solution using Visual Studio.
Right click the project > Add > Existing item...
If you don't have those files and can't find them, then recreate them. Here's the default code for them.
Startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace NOCng
{
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.AddRazorPages();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace NOCng
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

Issue on using AutoMapper in asp.net core

I am following a tutorial on asp.net core and angular. When I add the Automapper inside my Startup class it crashes the dotnet cli and couldn't render the page. This is how I use the Automapper in the Startup:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SpaServices.AngularCli;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using aspcoreangular.persistence;
using AutoMapper;
namespace aspcoreangular
{
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.AddAutoMapper();
services.AddDbContext<VegaDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Default")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
}
}
This is how I use it in the controller. But it doesn't get to this point
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using aspcoreangular.models;
using aspcoreangular.persistence;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace aspcoreangular.Controllers
{
public class MakesController : Controller
{
private readonly VegaDbContext context;
private readonly IMapper mapper;
protected MakesController(VegaDbContext context, IMapper mapper)
{
this.mapper = mapper;
this.context = context;
}
[HttpGet("/api/makes")]
public async Task<IEnumerable<Resources.MakeResource>> GetMakes()
{
var makes = await context.Makes.Include(m => m.Models).ToListAsync();
return mapper.Map<List<Make>, List<Resources.MakeResource>>(makes);
}
}
}
This is the image of the crash:
Can you please help me with this? Thank you.
This my MakeResouce class
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using aspcoreangular.models;
namespace aspcoreangular.Controllers.Resources
{
public class MakeResource
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<ModelResource> Models { get; set; }
public MakeResource()
{
Models = new Collection<ModelResource>();
}
}
}
and in my mappingprofile
using aspcoreangular.Controllers.Resources;
using aspcoreangular.models;
using AutoMapper;
namespace aspcoreangular.ClientApp.Mapping
{
public class MappingProfile : Profile
{
protected MappingProfile()
{
CreateMap<Make, MakeResource>();
CreateMap<Model, ModelResource>();
}
}
}
When AutoMapper maps source object to destination object before mapping itself it has to create an instance of the destination object and then Mapper can map properties using reflection.
And the error says: No parameterless constructor is defined for this object.
That means: AutoMapper kindly asks System.Activator class to create instance of the destination object for him. But System.Activator fails because it can't find public parameterless contructor in destination class (obviously, System.Activator can use constructor with parameters, but AutoMapper hadn't provided any parameters for constructor). And that is why the third line of the Error message comes from Activator.CreateInstance method.
So, to sum up, you should examine Resources.MakeResource class (as destination) for parameterless constructor.
PS. But I can't tell you on Why this exception crashes the whole Application

Resources