NullReferenceException "Object reference not set to an instance of an object." When using API Keys with concurrent requests
Description
Environment
Attachments
- 04 Aug 2022, 06:35 am
- 02 Feb 2022, 03:41 am
is cloned by
is duplicated by
Activity
Mike Sheen 26 February 2024 at 04:47
This is no longer an issue, from the cloned issue https://jiwa.atlassian.net/browse/DEV-9153 :
Changes made:
Modified Manager to implement IDisposable - so using a using statement when creating a manager will log off its SQL connection and clean itself up. So the REST API plugin version 7.2.1.33 or later requires 7.2.1 SR15 or later.
Modified all services which were using GetManager() extension method to use a using statement.
Modified GetManager() extension to create a manager and logon instead of retrieving from a static collection. This means requests which required a manager in their service will perform a logon at the time of the request, instead of trying to keep a manager per session.
Modified credentials and API Key auth to generate a HashSet of permissions and store that in the session. A global request filter examines this HashSet to see if the authenticated user has permission for the request - this works for AutoQuery requests as well.
Extended the session object by re-introducing JiwaAuthUserSession which inherits the ServiceStack session. This object adds a couple of new fields: APIKey_Type, APIKey_PrincipalID, CredentialsPassword, StaffID and AllowedRoutePermissions
Debtor API Key request filters and responses now look at the JiwaAuthUserSession properties APIKey_Type and APIKey_PrincipalID to perform their function of restricting requests and responses.
Removed all references to jiwa-stateful - stateful requests are no longer implemented or supported.
Changes required by 3rd party plugins which add custom routes:
if they used this line in their service code:
JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
they should now wrap their code in using which gets the Manager from the Request:
using(JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.Request.GetManager())
{
// code in here
}
Mike Sheen 19 September 2023 at 00:04
@Stuart Barnes - Think what your mentioning should be a separate improvement issue as this issue passes with what it claims to do.
Stuart Barnes 25 January 2023 at 01:56
This has been failed because we are adding the staff id to be stored in the session at login, getting the current user will be fixed at the same time.
Mike Sheen 3 January 2023 at 06:55
Done.
Mike Sheen 20 December 2022 at 05:28Edited
See cloned issue https://jiwa.atlassian.net/browse/DEV-9153 for what we need to do.
A complication here is how we make caching integrate with the changes made.
Caching support was easier than expected.
If using an API Key, sometimes if one request is serviced before another with the same key has finished, you may get this error.
The following C# console application will quickly replicate the issue - this can be replicated on demo data - just create an API key for the Admin staff member, and then configure and start the service.
Disable all plugins except the REST API plugin.
Then start the app - error occurs within a minute or two with my testing.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ServiceStack; namespace DEV_9152 { internal class Program { static async Task Main(string[] args) { Task<int> t1 = ReadGRN(1); Task<int> t2 = ReadGRN(2); await Task.WhenAll(t1, t2); Console.ReadLine(); } static async Task<int> ReadGRN(int taskNo) { int count = 0; while (true) { count++; Console.WriteLine("Task {0} iteration {1} ReadStart", taskNo, count); using (var client = new JsonServiceClient("http://localhost")) { client.RequestFilter = httpReq => { httpReq.AddBearerToken("sGZs7Cb72kc-ysxJZfKOZ5YyRu9mTrBbG64FcHtHhJk"); }; await client.GetAsync<JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote>(new JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNoteGETRequest() { GRNID = "29B31D7C54F74F929EEB" }); Console.WriteLine("Task {0} iteration {1} ReadEnd", taskNo, count); } } return count; } } }
Error text indicates it is related to the CustomFieldCollection.Read()
However, in my tests I had disabled all plugins except the REST API, so no custom fields were enabled.