dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.38k stars 10k forks source link

UseDeveloperExceptionPage() doesn't work if exception is thrown after starting to write response #2593

Closed aspnet-hello closed 6 years ago

aspnet-hello commented 6 years ago

From @mikeharder on Thursday, May 5, 2016 4:41:03 PM

The following user code shows the exception page as expected:

app.UseDeveloperExceptionPage();
app.Run(async (context) =>
{
    throw new Exception();
    await context.Response.WriteAsync("hello");
});

However, the following user code just gets an incomplete response and no exception page:

app.UseDeveloperExceptionPage();
app.Run(async (context) =>
{
    await context.Response.WriteAsync("hello");
    throw new Exception();
});

In ASP.NET 4.6, I believe we buffer responses (at least by default), so developers get a nice error page almost anywhere an exception is thrown. We may want to do the same in ASP.NET Core, perhaps only when running in debug mode or only when UseDeveloperExceptionPage() has been called.

Copied from original issue: aspnet/Diagnostics#281

aspnet-hello commented 6 years ago

From @Tratcher on Friday, May 6, 2016 10:59:03 AM

This is by design. Buffering by default breaks a number of scenarios. Buffering only in Development (or when the middleware was present) would make your app function very differently, such that it would likely break when published.

aspnet-hello commented 6 years ago

From @cnblogs-dudu on Tuesday, December 27, 2016 5:53:53 AM

Hit the issue when an exception is being thrown at var cookieValue = Options.TicketDataFormat.Protect(ticket, GetTlsTokenBinding()); in Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler.FinishResponseAsync().

aspnet-hello commented 6 years ago

From @Tratcher on Tuesday, December 27, 2016 6:52:31 AM

@cnblogs-dudu that's a weird place for an exception. What was it?

aspnet-hello commented 6 years ago

From @cnblogs-dudu on Tuesday, December 27, 2016 7:35:29 AM

@Tratcher use the following TicketDataFormat:

public class FormsAuthTicketDataFormat : ISecureDataFormat<AuthenticationTicket>
{
    private string _authenticationScheme;

    public FormsAuthTicketDataFormat(string authenticationScheme)
    {
        _authenticationScheme = authenticationScheme;
    }

    public string Protect(AuthenticationTicket data)
    {
        throw new NotImplementedException();
    }

    public string Protect(AuthenticationTicket data, string purpose)
    {
        throw new NotImplementedException();
    }

    public AuthenticationTicket Unprotect(string protectedText)
    {
        throw new NotImplementedException();
    }

    public AuthenticationTicket Unprotect(string protectedText, string purpose)
    {
        //Get FormsAuthenticationTicket from asp.net web api
        var formsAuthTicket = GetFormsAuthTicket(protectedText);
        var name = formsAuthTicket.Name;
        DateTime issueDate = formsAuthTicket.IssueDate;
        DateTime expiration = formsAuthTicket.Expiration;

        //Create AuthenticationTicket
        var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, name) }, "Basic");
        var claimsPrincipal = new System.Security.Claims.ClaimsPrincipal(claimsIdentity);

        var authProperties = new Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties
        {
            IssuedUtc = issueDate,
            ExpiresUtc = expiration
        };
        var ticket = new AuthenticationTicket(claimsPrincipal, authProperties, _authenticationScheme);
        return ticket;
    }
}
aspnet-hello commented 6 years ago

From @Tratcher on Tuesday, January 3, 2017 10:37:48 AM

So it's throwing NotImplementedException?

aspnet-hello commented 6 years ago

From @cnblogs-dudu on Tuesday, January 3, 2017 7:24:40 PM

@Tratcher yes, the NotImplementedException was printed in console and the DeveloperExceptionPage was not shown.

System.NotImplementedException: The method or operation is not implemented.
   at FormAuthTicketService.Protect(AuthenticationTicket data, String purpose) in /data/identity/src/CNBlogs.Identity.Application.Services/FormAuthTicketService.cs:line 27
   at Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler.<FinishResponseAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.<FinishResponseOnce>d__55.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.<OnStartingCallback>d__54.MoveNext()

But now i can't reproduce the NotImplementedException.