How to debug the server (kestrel) of aspnet core - asp.net-core

I ran my head against a issue where i have no idea how to continue.
In short my problem is that the request finishes the aspnet core pipeline as everything being okay. But the content never reach the browser.
Testing in postman where it it tells me there was an error connecting. But when debugger is enabled i can step all the way through the aspnet core pipeline and nothing is faulting. Their build in logger also tells me a 200 is returned.
Adding
app.Use(async (ctx, next) =>
{
ctx.Response.OnCompleted(c =>
{
return Task.CompletedTask;
},null);
also trigger the on completed, so all indicates that the aspnet pipeline runs that it works. All integration tests also work with the in mem test server.
When i invoke it from the browser, the loading spinner just keeps running and the request never comes up in the network tab, so nothing to help me figure out why this fails.
What can I do to find out why its not working. Can i get some debugger/logging on the kestrel server to see if it writes out exceptions?

Related

PATCH request losing body on IIS but not on localhost

I have a web API, where I'm trying to support a PATCH request with a JSON Patch body to make changes to an object on the server.
I am using ASP Core with .Net 6, hosting using IIS on my web host.
This is the controller method:
public class BaseDataController<TEntity, TDetail, TNew> : ControllerBase
where TEntity : class, IIdentifiable
{
[HttpPatch("{id}")]
public virtual async Task<ActionResult<TDetail>> Patch(Guid id, [FromBody] JsonPatchDocument<TEntity> patch)
{
var item = await MainService.GetAsync(id);
if (item == null)
{
ControllerLogger.ItemNotFound();
return NotFound();
}
patch.ApplyTo(item, ModelState);
ValidationHelper.ValidatePatch(item, ModelState);
if (!ModelState.IsValid)
return BadRequest(ModelState);
await MainService.UpdateAsync(item);
return this.GuardResult(Mapper, item);
}
}
When I try to use this on my local machine, it works just fine. When I deploy to my web server, and make an identical request, I get a validation error and a 400 status code:
{"errors":{"":["A non-empty request body is required."],"patch":["The patch field is required."]}}
If I change HttpPatch to HttpPost and update the web request accordingly, it works fine.
Can anyone suggest what might be going wrong here? I'm assuming the server is baulking at the PATCH verb, but I can't work out how to make it happy. Googling is coming up with a load of WebDAV things, but the error codes don't match and ASP is clearly receiving the request (proven from the logs) when the description of the WebDAV issues suggests it wouldn't.
My working theory is that IIS is seeing the PATCH verb and doing something to the request body that ASP Core doesn't like, but I can't work out why or where to look to turn that sort of thing off.
When I try to use this on my local machine, it works just fine. When I
deploy to my web server, and make an identical request, I get a
validation error and a 400 status code: If I change HttpPatch to HttpPost and update the web request accordingly, it works fine
Well, your scenario is pretty obvious in context of IIS as you may know Http verb PATCH is not enabled as default accepted http verb on IIS Request Restrictions As you can see below:
Solution:
To resolve above incident, you outght to configure Request Restrictions on IIS and need to include ,PATCH so that it will allow http PATCH verb. On top of that, after that, please restart your application pool. You can follow below steps to implement that:
Step: 1
Select your app on IIS and then click on Handler Mappings Just as following
Step: 2
Select (Double click) ExtensionlessUrlHandler-Integrated-4.0
Step: 3
Click on Request Restrictions
Step: 4
Select VERB then include PATCH by comma seperated value as ,PATCH and click OK finally restart your application pool.
Note: For more details you can have a look on our official document here.

ASP.NET Core FindByEmailAsync is not responding and getting error 500

Using ASP.NET Core with the Identity framework.
I have a project running on Azure, with a SQL Server database, a web site and an API.
Suddenly, today when trying to login to the system (from the app that calls the API), it is stuck for around 15 seconds and then I get an error http 500.
I try to run the API function that authenticate the user from the local env. and was able to reproduce the bug.
The first line of the function is :
var user = await _userManager.FindByEmailAsync(model.Username);
This is the line the program is stuck till getting error message 500.
I don't even know how to approach this, I try to add a line that retrieves one of the user details, just to make sure the API can still talk to the database and it works fine.
How can check what is wrong with it? If I had the implementation of this function, maybe I can debug it.
Any suggestions?

Angular with OData batch request fails on IIS

I am using Odata with .Net Core web api. For client side i am usin angular 13. OData batch request works fine in localhost. After published on iis with 'ng-build' i am getting a cors error from odata batch request. I already allow origins. What am i missing?
I am not sure but think it was really related with cors.
I only added this code block in to "Configure" method in startup.cs and problem solved.
app.Use((context, next) => {
context.Response.Headers["Access-Control-Allow-Origin"] = "*";
return next.Invoke();
});
But before the batch, i didn't need this code block i have added. All request works fine (except batch) without the code block i have added. I am trying to understand this part.

How to republish an ASP.NET Core 5 web application in IIS. Changes not taking effect

I've published an ASP.NET Core 5 Web API to IIS (using VS 2019 webdeploy), and it is running fine. Now I've made some minor changes and republished.
The changes take affect on my local machine using IIS Express, but I do not see them when I publish to my IIS server. I can see that the exe and dlls are updated, but the webapi behaviour does change.
Something as simple as setting the swaggerdoc title doesn't take affect.
Is there something else I need to do to refresh the app? I've tried recycling the app pool and doing an iisreset, but no luck. I've read that IIS is merely acting as a reverse proxy to Kestrel which is actually hosting the api. If so how do I recycle that?
As a test, I delete all the files in my web api directory. I browse to the web api and get the following error:
HTTP Error 500.31 - Failed to load ASP.NET Core runtime Common
solutions to this issue: The specified version of
Microsoft.NetCore.App or Microsoft.AspNetCore.App was not found.
Troubleshooting steps:
Check the system event log for error messages
Enable logging the application process' stdout messages Attach a
debugger to the application process and inspect For more information
visit: https://go.microsoft.com/fwlink/?LinkID=2028526
I then re-publish the web api and browse to it, but it still has the old behavior. I'm really confused, because I know the published dll for my service is correct.
If I use ILSpy I can see the following code:
public void ConfigureServices(IServiceCollection services)
{
IConfigurationSection appSettingsSection = Configuration.GetSection("ApplicationSettings");
ApplicationSettings appSettings = appSettingsSection.Get<ApplicationSettings>();
services.AddSingleton(appSettingsSection.Get<ApplicationSettings>());
services.AddControllers()
.AddXmlSerializerFormatters()
.AddJsonOptions(delegate(JsonOptions o)
{
o.JsonSerializerOptions.PropertyNamingPolicy = null;
o.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
});
services.AddSwaggerGen(delegate(SwaggerGenOptions c)
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "My Demo Service (" + appSettings.Environment + ")",
Version = "v1"
});
});
}
When I browse to the swagger page of my API on my local dev box the title matches code, and the property naming is what I want. When I browse to it on the server, the title of the swagger page is the old value, and the property naming policy is camel case, so I'm pretty sure I'm publishing the new version of my web api, but it's not being executed when I make http requests to the api. Something must be cached somewhere.

Suspected bug in Microsoft Identity Platform with ASP.NET Core 3.1 Razor Pages

I am developing an application to be hosted in the Azure App Services environment which consists of a front-end Web App, a back-end Web API and a SQL Database (using Azure SQL). The front-end Web App is a Razor Pages app. We are trying to use the Microsoft Identity Platform (via Microsoft.Identity.Web and Microsoft.Identity.Web.UI libraries) to acquire an access token for the API when needed.
It works perfectly well the first time, but once a token has been acquired and cached - if the application is restarted it fails with this error:
IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. See https://aka.ms/ms-id-web/ca_incremental-consent.
No account or login hint was passed to the AcquireTokenSilent call.
Startup configuration is (I've tried various variants of this):
public void ConfigureServices(IServiceCollection services)
{
services.AddDistributedMemoryCache();
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
options.HandleSameSiteCookieCompatibility();
});
services.AddOptions();
services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
.EnableTokenAcquisitionToCallDownstreamApi(new string[] { Configuration["Api:Scopes"] })
.AddInMemoryTokenCaches();
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();
services.AddRazorPages().AddRazorRuntimeCompilation().AddMvcOptions(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
services.AddMvc();
//Other stuff...
}
I have tried for many days trying to find either a resolution workaround for this. I can catch the
error, but there is no action we can take programmatically that seems to clear the problem (the ITokenAcquisition interface does not offer the option to force an interactive login).
I have found that it is ONLY a problem in a Razor Pages application - a controller-based MVC Web App with almost identical startup code does not exhibit the problem.
I have also found that, by creating a controller-based test MVC Web App and configuring it with the same client id, tenant id etc. as the app we're having problems with, then starting it up (within the Visual Studio development environment) as soon as the main app gets the problem, I can clear the error condition reliably every time. However this is obviously not a viable long-term solution.
I have searched for this problem on every major technical forum and seen a number of similar sorts of issues raised, but none provides a solution to this precise problem.
To replicate:
Create an ASP.NET Core 3.1 Web API.
Create an ASP.NET Core 3.1 Razor Pages Web App that calls the API.
Register both with Azure Active Directory and configure the App to request a token to access the API (as per various MS documents).
Run - if everything is set up correctly the login screen will appear and all will work correctly.
Stop the Web App, wait a couple of minutes and re-start. The error above will now appear.
I have raised a Microsoft support request for it - has anybody else come across this and found a solution for it?
I have finally got to the bottom of this, largely thanks to this: https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/issues/216#issuecomment-560150172
To summarise - for anyone else having this issue:
On the first invocation of the web app you are not signed in, and so get redirected to the Microsoft Identity Platform login, which logs you in and issues an access token.
The access token is stored in the In-Memory token cache through the callback.
All then works as expected because the token is in the cache.
When you stop, and then re-start the web app within a reasonably short time, it uses the authentication cookies to pick up the still-current login, and so it does not access the Identity Platform and you do NOT get an access token.
When you ask for a token the cache is empty - so it throws the MsalUiRequiredException.
What isn't really made clear in any of the documentation is that this is supposed to happen - and that exception is picked up by the "AuthorizeForScopes" attribute but only if you allow the exception to fall all the way through and don't try to handle it.
The other issue is that in a Razor Pages app the normal AuthorizeForScopes attribute has to go above the model class definition for every page - and if you miss one it may trigger the above problem.
The solution proposed by "jasonshave" in the linked article solves that problem by replacing the attribute with a filter - so it will apply to all pages.
Maybe I'm a bit old-school, but the idea of using an unhandled exception as part of a planned program control flow doesn't sit right with me - at the very least it should be made clear that that's the intention. Anyway - problem now solved.