Asp.net core site hangs after about 50 requests - asp.net-core

I use asp net core 2.0 and faced very strange behavior (at least I see it locally with IIS express). I open site page then press Refresh button about 50 times and site starts hanging, processing of request takes about 40 seconds. Then after about 5 minutes of idle I refresh page again and everything works fast. Next ~50 requests and again it hangs. I'm very confused with that and don't have ideas what is the reason and how to troubleshoot it. I removed all things from code and rest only base code and it's still reproducable.
My Startup class looks so:
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)
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
return services.BuildServiceProvider();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Use(async delegate(HttpContext context, Func<Task> next)
{
await next.Invoke();
});
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Controller actions don't do anything they just return View. In debugging I often see that it hangs on "await next.Invoke();" line (I've added this delegate only for debugging) but I'm not sure that problem is exactly in action executing.
Maybe anybody knows what can be a reason or how I can troubleshoot it?

Looks like the problem was solved in unexpected way - I updated Visual Studio and as I saw IIS was also updated together with it.

Related

Http Post in Orchard Core asp net core Web App returns bad request

I'm using Orchard core in asp net core web app project. I have a controller with two simple get and post Apis. As I'm using OrchardCore the Startup.cs file has different config and I dont use services.AddControllers() in configureServices.
Every thing is fine untill I'm using HttpGet. But when I want to have an Api with HttpPost postMan says badRequest. So I Added services.AddControllers() in Startup.cs and the post Api was fine in post Man but the orchard project says I have multipe Endpoints.
I used services.AddMvc().AddNewtonsoftJson(), and every thing was fine but the admin page didn't load and had error as below:
InvalidOperationException: The view 'Index' was not found. The
following locations were searched:
/Areas/OrchardCore.AdminDashboard/Views/Dashboard/Index.cshtml
/Areas/OrchardCore.AdminDashboard/Views/Shared/Index.cshtml
/Views/Shared/Index.cshtml /Pages/Shared/Index.cshtml
I wold appreciate it if you can help me how to call Post Api.
here is my code:
[HttpPost("post")]
public Task<string> post()
{
return Task.FromResult("hiPost");
}
[HttpGet("get")]
public Task<string> get()
{
return Task.FromResult("hiGet");
}
and this is my startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
//services.AddControllers();
services.AddOrchardCms();
services.AddMediatR(typeof(SelectedWebSiteBlogQueryHandler).Assembly);
services.AddAutoMapper(typeof(Startup));
services.AddCors();
services.AddMvc().AddNewtonsoftJson();
}
public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(o => o.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseOrchardCore();
}
}
You are probably missing an IgnoreAntiForgeryToken attribute on your controller.
AntiForgery is enabled by default by OrchardCore
For an ApiController in OrchardCore I would expect to see the controller decorated as follows.
[ApiController]
[Authorize(AuthenticationSchemes = "Api"), IgnoreAntiforgeryToken, AllowAnonymous]
However this depends if you are using the OpenId module to authenticate with, or simply need to post to a normal controller, without an AuthenticationScheme
Depending on what you are actually posting from in real life, it may be better to supply an anti forgery token as part of your post.

Blazor Server get current logged user when EF DbContext execute select data query

I build blazor server multi tenant application and I wants to use HasQueryFilter in entity framework DbContext for predefined filter with TenantId. Ofcourse I have connected User with tenant. I created CurrentTenatnProvider which has method GetCurrentTenatnId. In this mehtod i use AuthentificationStateProvider and call GetAuthenticationStateAsync(). Ofcourse i get the error ''GetAuthenticationStateAsync was called before SetAuthenticationState". I Cannot use IHttpContextAccessor because in Azure app I get null reference exception.
Is there any other possibility how to get CurrentUser in time when DbContext execute select data query?
I was thinking about cache CurrnetUser but there is problem with cache key.CurrentTenatnProvider service is registered as scoped service. There is Id attribute which is set in constructor. And then is used as cache key. But this approach does not working and I get the same error.
It si possible get signal-r connection identificator and use it as cache key?
I spended 2 days with test lots of combination and read lots of documentation but unfortunately I didn't find any solution. I will be very grateful for any advice.
I have done this a few ways but the simplest way I could find was retrieving my user from the database in the MainLayout.razor file during OnInitializedAsync() and passing it in a fixed cascading parameter <CascadingValue Name="CurrentUser" IsFixed="true" Value="UserId">. From there, I could reference it where needed in any child component.
finally I found solution! From my view it is bug! Problem is because services.AddDbContextFactory is registered as Singleton. I create my own implementation of IDbContext factory and register it as Scoped. After this change everything’s works perfect. When I change registration scope of DbContextFactory to singleton, I get the error: GetAuthenticationStateAsync was called before SetAuthenticationState.
My DbContextFactory
public class BlazorContextFactory<TContext> : IDbContextFactory<TContext> where TContext : DbContext
{
private readonly IServiceProvider provider;
public BlazorContextFactory(IServiceProvider provider)
{
this.provider = provider;
}
public TContext CreateDbContext()
{
if (provider == null)
{
throw new InvalidOperationException(
$"You must configure an instance of IServiceProvider");
}
return ActivatorUtilities.CreateInstance<TContext>(provider);
}
}
My StartUp
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.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<ApplicationDbContext>();
services.AddScoped<IDbContextFactory<ApplicationDbContext>, BlazorContextFactory<ApplicationDbContext>>();
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
services.AddSingleton<WeatherForecastService>();
}
// 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.UseDatabaseErrorPage();
}
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.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
I hope it's help other peoples! I spend 6 days with this problem :(

.NET Core 3.1 - Swagger not loadig

I am trying to implement Swagger in my WebApi. However, it is not working. The issue is that swagger.json loads forever. When I try to go to /swagger/v1/swagger.json, it loads forever and my CPU usages spikes to 100%.
This is my configuration:
public class Startup
{
...
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "ToDo API"
});
});
...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider services)
{
...
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
// Setup the endpoints.
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action}/{id?}");
endpoints.MapHub<HomeHub>("/homehub");
});
}
}
I of course already looked around on the internet, but could not find any solution. I do not get any errors, so what could be the issue?
Update:
I have tried generating the json file with the CLI, and same issue. It just loads and nothing happens. Besides taking 24gb of memory...
I believe that one of your controller or class causes this error. It looks like swagger tries to load something recursively.
I suggest you to use memory profiler (like dotMemory) to find out what is going on (what creates this memory leak)
Another workaround is to comment out all your controllers and enable them one by one until you find the erroneous code.
Also you may want to check this Answer

How to tell when a self-hosted ASP.NET Core application is ready to receive requests?

I need to launch worker processes that communicate using ASP.NET Core Web API. I need to know when I can start sending requests to that process. The only options I see so far are to have the worker call the parent process API when it has finished configuring or poll the worker with an "are you alive" request.
Is there any built in mechanism for this? Any better patterns or designs?
In general, after the application is started successfully, you will be able to send request.
For Application Start event, you could try IHostApplicationLifetime in .net core 3.0, if you are using previous version, you could try IApplicationLifetime which will be obsolete in future version.
Here is a demo which is used to register event while application is started.
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().AddNewtonsoftJson();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime hostApplicationLifetime)
{
hostApplicationLifetime.ApplicationStarted.Register(() => {
Console.WriteLine("Application is Started");
});
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.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}

ASP.NET Core 2.x OnConfiguring get connectionstring string from appsettings.json

Just started messing with ASP.NET Core, pretty impressive so far. In the code generated,(see below). I want to change the hardcoded connection string to get it from the appsettings.json file.
This is apparently impossible. I haven't found a single example that works (or even builds).
What's going on??
Please help
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
optionsBuilder.UseSqlServer("Server=xxxxxxx;Database=xxxxx;Trusted_Connection=True;");
}
}
The link provided solves the problem in one area but doesn't work here in OnConfiguring. What am I doing wrong ?
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.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
var connection = Configuration.GetConnectionString("ConnectionName");
services.AddDbContext<SurveyContext>(options => options.UseSqlServer(connection));
}
// 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("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
In the startup class of a .NET Core project you usually register this in the ConfigureServices function.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<YourContext>(options => options.UseSqlServer(connection));
}
When you are in the startup class of a .NET Core it is no problem to read the values from appsettings.json.
You could read more at Microsoft, i.e. here: https://learn.microsoft.com/en-us/ef/core/get-started/aspnetcore/existing-db
In the place where you want to access the appsettings.json,
JToken jAppSettings = JToken.Parse(
File.ReadAllText(Path.Combine(Environment.CurrentDirectory,
"appsettings.json")));
Now since you have the object, you can access its contents.
Let me know if it works.
When you use the Scaffold-DbContext, by default it hard codes your string into the DbContext class (so it works out of the box). You will need to register your DbContext in your startup class to proceed. To set this up, you can check the instructions in this answer.
Note that the Configuration property directly connects to your appsettings.json and several other locations. You can read more about it in this documentation. While you can always use the appsettings.json file, it is generally recommended to have your secure secrets in an external json file outside your source code. The best solution for this during development is using the secret manager. The easiest way to use this is right click on your project on visual studio and select "manage user secrets". This will open a json file that is already connected to your Configuration object.
Once this is set up, you need to use dependency injection to access your db context.
public class HomeController : Controller
{
public HomeController(SurveyContext context)
{
// you can set the context you get here as a property or field
// you can use visual studio's shortcut ctrl + . when the cursor is on "context"
// you can then use the context variable inside your actions
}
}
When you use using, it creates a new connection each time. Using injection makes sure only one connection is created per request no matter how many times it is used.