aspnetboilerplate: Throwing EntityNotFoundException from AppService causes InvalidOperationException

Version Info

  • Abp: 4.1.0
  • .NET Core: netcoreapp2.1 and netcoreapp2.2 (tested both)
  • Microsoft.AspNetCore.Server.Kestrel: 2.2.0

Steps to Reproduce:

  1. Download the .NET Core Angular SPA sample (Make sure that the “One solution” option is checked)
  2. Run the Migrations etc
  3. Call the User’s Get Api with Id >= 2 (/api/services/app/User/Get) <-- The only place where EntityNotFoundException gets thrown from the AppService layer

Expected Result (when called from SwaggerUI)

{
  "result": null,
  "targetUrl": null,
  "success": false,
  "error": {
    "code": 0,
    "message": "There is no entity User with id = 2!",
    "details": null,
    "validationErrors": null
  },
  "unAuthorizedRequest": false,
  "__abp": true
}

Actual Result (command window logs)

INFO  2019-01-30 09:52:17,439 [14   ] ore.Mvc.Internal.ControllerActionInvoker - Executed action CompanyTest.Project.Users.UserAppService.Get (CompanyTest.Project.Application) in 2457.0942ms
ERROR 2019-01-30 09:52:18,424 [14   ] Microsoft.AspNetCore.Server.Kestrel      - Connection id "0HLK6GSE37A0J", Request id "0HLK6GSE37A0J:00000005": An unhandled exception was thrown by the application.
System.InvalidOperationException: StatusCode cannot be set because the response has already started.
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAlreadyStartedException(String value)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.set_StatusCode(Int32 value)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode(Int32 value)
   at Microsoft.AspNetCore.Http.Internal.DefaultHttpResponse.set_StatusCode(Int32 value)
   at Microsoft.AspNetCore.Builder.Internal.ApplicationBuilder.<>c.<Build>b__16_0(HttpContext context)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIIndexMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at CompanyTest.Project.Web.Host.Startup.Startup.<>c.<<Configure>b__4_1>d.MoveNext() in D:\Dev\asp.net core\CompanyTest.Project\4.4.0\src\CompanyTest.Project.Web.Host\Startup\Startup.cs:line 100

Potential Fix Not sure if this is an actual fix or not, but in Startup.cs, only call the next() action in the middle-ware pipeline if the Response hasn’t started yet:

app.Use(async (context, next) =>        
{
    await next();
    if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value))
    {
        context.Request.Path = "/index.html";
        if (!context.Response.HasStarted) // <--- FIX?
            await next();
    }
});

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 16 (9 by maintainers)

Most upvoted comments

I understand what you mean, I will try again.