Answered by:
ServerApplicationContext + OWIN

Question
-
Hi,
Is it possible to use Lightswitch ServerApplicationContext with OWIN? Is it tested?
I have tested it on simple ApiController with method with one LS query. If more requests are handling in one time, sometimes occurs following error:
NullReferenceException in Microsoft.Lighswitch.Utilities.Internal.RuntimeUtilities.GetEntitySetModel
EntityType is null.This error occurs only sometimes, so I think it is thread problem - can be caused by OWIN? No async/await on calling path. VS2013.
Thanks
LS Forum
- Edited by polacho Friday, July 8, 2016 1:47 PM
Friday, July 8, 2016 1:19 PM
Answers
-
I tried it and could not get it to work reliably.
LightSwitch defiantly uses the old Forms Authentication not the new ASP.NET Identity.
http://HoloLensHelpWebsite.com
http://LightSwitchHelpWebsite.com
Unleash the Power - Get the LightSwitch HTML Client / SharePoint book
Friday, July 8, 2016 5:22 PM
All replies
-
I tried it and could not get it to work reliably.
LightSwitch defiantly uses the old Forms Authentication not the new ASP.NET Identity.
http://HoloLensHelpWebsite.com
http://LightSwitchHelpWebsite.com
Unleash the Power - Get the LightSwitch HTML Client / SharePoint book
Friday, July 8, 2016 5:22 PM -
What do you mean by 'reliably' please? Can you explain where's the problem?
With ASP.NET Identity in LS is not problem in project, but OWIN pipeline causes these errors, I think.
LS Forum
Sunday, July 10, 2016 4:08 PM -
What do you mean by 'reliably' please? Can you explain where's the problem?
With ASP.NET Identity in LS is not problem in project, but OWIN pipeline causes these errors, I think.
LS Forum
'Parts' of LightSwitch would work but then other things like saving and navigating did not :)
You're right that having ASP.NET Identity works and the project builds :)
Now my solution was to have a separate website log a person in using Azure AD and then the user clicks a button in the Azure AD app and I make a web service call to write a record in a custom table the LS app to programmatically log the user in when they navigated to a special page in the LS app and passed a special token.
This way the LS app stays with Windows Forms Authentication but my users use their Azure AD accounts "to get into" the LS application.
http://HoloLensHelpWebsite.com
http://LightSwitchHelpWebsite.com
Unleash the Power - Get the LightSwitch HTML Client / SharePoint book
Sunday, July 10, 2016 4:26 PM -
Thank's for explanation :)
I will try use old authentication.
LS Forum
Monday, July 11, 2016 7:32 AM -
I remove OWIN from project and implemented custom forms authentication. However problem with LS still occurs. I thought that problem is with async API of OWIN and WebAPI, but problem is maybe in LS. I ensured one thread in request with SAC code.
Then I try this simple code in Global.asax
protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) { using(ServerApplicationContext ctx = ServerApplicationContext.CreateContext()) { var x = ctx.Dataworkspace.ApplicationData.InvoiceOuts.GetQuery().Execute(); } }
Stop iisexpress server (important), build and debug.
And run multiple client requests in one time on this application (using console app).
For some first requests NullReferenceException in Microsoft.LightSwitch occured.
I think it's thread specific error in LS code.Workaround for this errors is following SACDispatcher class (If NullReferenceException occurs in LS, repeat SAC code)
public class ServerApplicationContextDispatcher { [ThreadStatic] private static ServerApplicationContextDispatcher instance = null; public static ServerApplicationContextDispatcher Instance { get { if(instance == null) { instance = new ServerApplicationContextDispatcher(); } return instance; } } private const int repeatThreshold = 2; private int invokeCounter; public void Invoke(Action<ServerApplicationContext> action) { InitializeCounter(); InvokeInner(action); } private void InitializeCounter() { invokeCounter = 1; } private void InvokeInner(Action<ServerApplicationContext> action) { try { using(ServerApplicationContext ctx = ServerApplicationContext.CreateContext()) { action(ctx); } } catch (Exception ex) { if (CanRepeatInvoke(ex)) { IncrementCounter(); Exception exception = RepeatInvokeWithExceptionHandling(action); if(exception != null) { throw new Exception(exception.Message, ex); } } else { throw; } } } private bool CanRepeatInvoke(Exception ex) { return IsNullReferenceExceptionInLightswitch(ex) && invokeCounter <= repeatThreshold; } private bool IsNullReferenceExceptionInLightswitch(Exception ex) { Exception current = ex; while (current.InnerException != null) { current = current.InnerException; } return current is NullReferenceException && current.Source == "Microsoft.LightSwitch"; } private void IncrementCounter() { invokeCounter++; } private Exception RepeatInvokeWithExceptionHandling(Action<ServerApplicationContext> action) { Exception exception = null; try { InvokeInner(action); } catch (Exception ex) { exception = ex; } return exception; } }
Usage:
ServerApplicationContextDispatcher.Instance.Invoke((ctx) => { var x = ctx.DataWorkspace.ApplicationData.InvoiceOuts.GetQuery().Execute(); });
LS Forum
- Edited by polacho Friday, July 15, 2016 6:37 AM
Friday, July 15, 2016 6:26 AM -
@Polacho - interesting, although each of your calls should be on a separate thread and in theory require a new context to be created, did you perhaps try the .GetContext() first before calling .CreateContext()? In normal LS usage one should always call .CreateContext() only if .GetContext() returns null - it has been a while since I've used this, but that is how it works from memory.
Regards, Xander. My Blog
Friday, July 15, 2016 7:52 AM -
Dispatcher expects that current SAC is null and that thread has no SAC already created. And if this case occurs, LS simply throws exception that context already exists. However this nullreference exception has no dependency on this behavior. There could be problem if thread changed during execution of SAC code (await), then some errors can occurs after await on new thread, but it's not my case. I have one thread before, during and after execution SAC code - but nullreferenceexception sometimes (if more threads on same SAC code) occurs in LS.
LS Forum
Friday, July 15, 2016 8:17 AM