HttpContext.Current is null during custom RawDeserializeFn execution

We are making a POST call for bulk updating records using the endpoint:
POST http://localhost/API/json/Reply/Record[]

Request Body:
[
{
“Uri”: 185,
“Fields”: {
“testcustom”: “12345”
},
“RecordTitle”: “testadd3”,
“RecordRecordType”: “additionalfield”
},
{
“Uri”: 186,
“Fields”: {
“testcustom”: “678”
},
“RecordTitle”: “testadd4”,
“RecordRecordType”: “additionalfield”
}
]

Error Response:
{
“ResponseStatus”: {
“ErrorCode”: “SerializationException”,
“Message”: “Failed to set property ‘Fields’ with ‘{\r\n "testcustom": "12345"\r\n}’”,
“Errors”:
}
}

Details:

The error occurs during execution of the following custom deserialization logic:

 JsConfig<FieldDictionary>.RawDeserializeFn = r =>
		{
			//     ITrimAppHost trimAppHost = ServiceStack.WebHost.Endpoints.AppHostBase.Instance as ITrimAppHost;

			if(HttpContext.Current is null)
			{
				//After servicestack recent upgrade, the deserialization process running in async mode, since our code runs synchronously
				//if the thread doesn't hold the HttpContext value, let's update it here.
				HttpContext.Current = _httpContext;
			}
			var fields = new FieldDictionary();
			JsonObject jobject = jsvJsonParse(r);

			foreach (string key in jobject.Keys)
			{
				if (!AppHostConfig.Instance.UserFields.ContainsKey(key))
				{
					AppHostConfig.Instance.refreshUserFields();
				}

				if (AppHostConfig.Instance.UserFields.ContainsKey(key))
				{
					string json = jobject.Child(key);
					JsonObject jjobject = jsvJsonParse(json);
					try
					{
						json = jjobject.Child("Value");
					}
					catch { }
					fields.Add(key, AppHostConfig.Instance.UserFields[key](json));
				}
			}
			return fields;
		};

During deserialization, HttpContext.Current is found to be null, and this leads to a NullReferenceException when calling:

var httpReq = new AspNetRequest(System.Web.HttpContext.Current.ToHttpContextBase());

Why is HttpContext.Current null during deserialization in this context, and how can we reliably access the current HttpContext during custom RawDeserializeFn execution?

Would appreciate your guidance on how to best handle this

It’s going to be null if it’s accessed outside the context of a Request Context.

When it is null you don’t have access to the Request Context, there’s isn’t really anything to do other that rewriting it so it doesn’t need access to the Request Context singleton.

It’s not clear why you even need it during deserialization? Why can’t this be done after it’s deserialized, e.g. from within your Service?

Our current challenge is that the custom logic for deserializing FieldDictionary calls AppHostConfig.Instance.refreshUserFields(), which internally depends on HttpContext.Current (via authenticateTrustedUser). That’s why we were trying to “restore” the context.

We understand that RawDeserializeFn is executed outside of the normal request context and that HttpContext.Current is therefore null. However, this dependency has existed in our implementation from the beginning.

As a workaround, we tried the following:

public static partial class TrimUtils
{
    public static HttpContext _httpContext;
}

protected void Application_BeginRequest(object src, EventArgs e)
{
    TrimUtils._httpContext = HttpContext.Current;
}

Later, inside our custom RawDeserializeFn, if HttpContext.Current is null, we temporarily restore it from _httpContext for deserialization

if (HttpContext.Current == null)
    HttpContext.Current = _httpContext;

This approach works in practice, as it restores the missing context for the deserializer.

Question: Is this workaround safe and supported in ServiceStack, or do you strongly recommend against it? If it’s unsafe, is there a minimal alternative we can adopt without a full rewrite?

It’s nothing to do with ServiceStack but I’d recommend against accessing the Request Context Singleton from within inside serialization callbacks.

Whatever your deserialization routine is I’d do it after it’s deserialized, e.g:

public static Model DeserializeModel(string json, IRequest req)
{
    var dto = json.FromJson<Model>();
    var httpCtx = ((HttpRequest) req.OriginalRequest).HttpContext;
    // do whatever modifications that needs the HttpContext here...
    return dto;
}

This doesn’t rely on a Request Context Singleton so it will never be null.

If you need this to deserialize an API Request DTO I’d make the same modifications from within a Service implementation or you can use a Custom Request DTO Binder.