CORS headers missing if Exception is thrown in Request filter

When my service throws an exception, the browser fails to receive the content text as the CORS headers are missing. Regular responses are OK.

The issue is also reported here:

Any tips/hints welcome.

That question dates back to ServiceStack v3 from 2013.

I’m not able to repro this as CORS Headers are being added for Error Responses, e.g:

HTTP/1.1 500 Exception
Cache-Control: private
Content-Type: text/html; charset=utf-8
Vary: Accept
Server: Microsoft-IIS/10.0
X-Powered-By: ServiceStack/4.00 Win32NT/.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS
Access-Control-Allow-Headers: Content-Type
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sat, 12 Nov 2016 13:24:03 GMT
Content-Length: 11216

Please check you’re using the latest version of ServiceStack, if you are please provide a repro and include the raw HTTP Response Headers which you can get from Chrome WebInspector or Fiddler.

Thanks for the help.

I am integrating servicestack in pre-existing ASP.NET forms site. The issue occurred in a request attribute I am writing, that does an auth check by checking the ASP.NET forms authorization status.

I had two issues, code example and fix below

  1. The IIS error redirect and ASP.NET forms auth redirect, where causing a custom error page to return. I disabled this by setting suppress properties on the ASP.NET response object. See code below.

  2. When throwing an exception in the request filter attribute, servicestack actually suppresses the CORS headers. See https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/Host/Handlers/HttpAsyncTaskHandler.cs#L188. To verify, I moved the code from the attribute to a service GET handler. Throwing in the service resulted in the CORS headers. As a workaround, I add the headers in a finally block in the filter.

    public class CreateLoginContextAttribute : RequestFilterAttribute
    {
    public override void Execute(IRequest req, IResponse res, object requestDto)
    {
    try
    {
    var aspResponse = HttpContext.Current?.Response;
    if (aspResponse != null)
    {
    aspResponse.TrySkipIisCustomErrors = true;
    aspResponse.SuppressFormsAuthenticationRedirect = true;
    }
    var isActiveUser = false; // …
    if (!isActiveUser)
    throw new AuthenticationException(“Login required”);
    }
    catch
    {
    // CORS headers are not written by ss on exceptions thrown in request filter
    res.ApplyGlobalResponseHeaders();
    throw;
    }
    }
    }

Unless you’ve got custom error handling to handle and short-circuit the error, Exceptions thrown in Request Filter Attributes are already converted into a ErrorResponse DTO and written to the Response as a normal Response DTO where it will apply the CORS Global Response headers.

Here’s the Raw HTTP Response Headers from an Exception thrown in a Request Filter Attribute:

HTTP/1.1 500 Exception
Cache-Control: private
Content-Type: text/html; charset=utf-8
Vary: Accept
Server: Microsoft-IIS/10.0
X-Powered-By: ServiceStack/4.00 Win32NT/.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS
Access-Control-Allow-Headers: Content-Type
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sun, 13 Nov 2016 04:09:27 GMT
Content-Length: 11615
Request Headers

Where I’m seeing the CORS Headers returned for Exceptions in Request Filter Attributes applied either on the Service, Action or Request DTO.

They weren’t being applied to Exceptions thrown in a Global Request Filter which is now being applied from this commit which is available from v4.5.5 that’s now avaliable on MyGet.

Not sure if this will change will resolve your issue as this change doesn’t affect Exceptions thrown in a Request Filter, but if you still have an issue, I’ll need a small/stand-alone repro I can run locally to see the error.

Thanks for the tips.

I checked the global.asax handler and the host.ServiceExceptionHandlers I registered. They are not hit by a breakpoint, removing them also made no difference. I am on SS 4.5.0. The filter is on the Service class, not registered globally in the host. I plan to upgrade in a few weeks, if the issue remains, I will take some time to see if I can extract a proof of concept.

For now, with the catch/throw handler all is OK.

Thx
Ries