Skip to content

Commit

Permalink
Fix AspNetCore UseExceptionHandler applied on postbacks
Browse files Browse the repository at this point in the history
AspNetCore reexecutes the same request with the original POST
method. If a DotVVM page is handling the error, we assumed that
we need to execute a postback in the Error page. The request body
was usually already consumed, and even if wasn't a matching command
wasnt found.

resolves #1700
  • Loading branch information
exyi committed Sep 29, 2023
1 parent b3dcbc7 commit 09c8f3c
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 8 deletions.
1 change: 1 addition & 0 deletions src/Framework/Framework/Hosting/HostingConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace DotVVM.Framework.Hosting
public class HostingConstants
{
public const string DotvvmRequestContextKey = "dotvvm.requestContext";
public const string DotvvmIsErrorHandlingKey = "dotvvm.isErrorHandling";

public const string GlobalizeCultureUrlPath = "dotvvmGlobalizeCulture";
public const string GlobalizeCultureUrlIdParameter = "id";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DotVVM.Framework.Configuration;
using DotVVM.Framework.Hosting.ErrorPages;
using DotVVM.Framework.Hosting.Middlewares;
using DotVVM.Framework.ResourceManagement;
using DotVVM.Framework.Utils;
using DotVVM.Framework.ViewModel.Serialization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
Expand Down Expand Up @@ -40,8 +42,13 @@ public DotvvmMiddleware(RequestDelegate next, DotvvmConfiguration configuration,
/// </summary>
public async Task Invoke(HttpContext context)
{
// create the context
var dotvvmContext = CreateDotvvmContext(context);
// If we are handling an error, assume that the request is Navigate, otherwise we are attempting to execute postbacks from a different page
var assumedRequestType =
#if NET6_0_OR_GREATER
context.Features[typeof(Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature)] is {} ? DotvvmRequestType.Navigate :
#endif
(DotvvmRequestType?)null;
var dotvvmContext = CreateDotvvmContext(context, assumedRequestType);
context.RequestServices.GetRequiredService<DotvvmRequestContextStorage>().Context = dotvvmContext;
context.Items[HostingConstants.DotvvmRequestContextKey] = dotvvmContext;

Expand Down Expand Up @@ -75,6 +82,11 @@ public async Task Invoke(HttpContext context)
await dotvvmErrorPageRenderer.RenderErrorResponse(dotvvmContext.HttpContext, ex);
return;
}
catch (Exception)
{
// context.Items[HostingConstants.DotvvmIsErrorHandlingKey] = BoxingUtils.True;
throw;
}

await next(context);
}
Expand All @@ -101,14 +113,13 @@ public static IHttpContext ConvertHttpContext(HttpContext context)
return httpContext;
}

protected DotvvmRequestContext CreateDotvvmContext(HttpContext context)
{
return new DotvvmRequestContext(
protected DotvvmRequestContext CreateDotvvmContext(HttpContext context, DotvvmRequestType? requestType = null) =>
new DotvvmRequestContext(
ConvertHttpContext(context),
Configuration,
context.RequestServices
context.RequestServices,
requestType
);
}

public static bool IsInCurrentVirtualDirectory(IHttpContext context, ref string url)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public override Task Init()
ExceptionType = "View called without IExceptionHandlerFeature";
return base.Init();
}
ExceptionType = exceptionInfo.Error.GetType().Name;
ExceptionType = exceptionInfo.Error.GetBaseException().GetType().Name;
RequestId = aspcontext.TraceIdentifier;
RequestPath = exceptionInfo.Path;
return base.Init();
Expand Down

0 comments on commit 09c8f3c

Please sign in to comment.