Web Connection
MessageBox() call in (wwServer) OnLoad template
Gravatar is a globally recognized avatar based on your email address. MessageBox() call in (wwServer) OnLoad template
  Mike McDonald
  All
  Feb 23, 2019 @ 07:29pm

Rick -

In my project's main 'base' PRG (the one which subclasses wwServer), I had the following in the OnLoad function..

*** Add persistent SQL Server Connection
#IF WWC_USE_SQL_SYSTEMFILES
    THIS.AddProperty("oSQL", CREATE("wwSQL"))
    IF !THIS.oSQL.Connect(THIS.oConfig.cSQLConnectString)
	   MESSAGEBOX("Couldn't connect to SQL Service. Check your SQL Connect string in the INI file.",48,"Web Connection")
	   CANCEL
    ENDIF
#ENDIF

I believe this originated from the templates\appmain.prg file when I created my project with the Management Console. In my testing, this can result in an HTML error which includes User-interface operation not allowed at this time (when running in non-debug, unattended COM mode).

I replaced the MessageBox() command with THIS.Trace(message), and that logs the SQL connection issue to the wcTraceLog.txt file, and then I got a different message in the HTML response..

The Com server threw an exception during the server method call:
The operation completed successfully. (Exception from HRESULT: 0x00000000 (S_OK))

If you also replace the CANCEL command with something like `ERROR "Couldn't connect to SQL Server", then the HTML response makes more sense.



The reason I'm having an SQL connection issue seems to be due to which 'user' is applied to the WC server when I hit the site. If I run the app from VFP, everything is fine, but if I build an EXE and have it load from the admin.aspx page or by an incoming hit, then things aren't right.

In file mode, it doesn't seem like the WC app has proper rights to the Temp folder (IIS creates the request file but it doesn't get picked up). In Task Manager, the (WC).exe is running under SYSTEM, and that account seems to have the proper rights in the temp folder. I have checked the paths and haven't changed them from the defaults, and it works fine when starting the app from VFP.

In COM mode, the request is hitting the app but I'm getting the SQL connection issue, even though running the WC app straight from VFP works fine, with the same connection string. When running from VFP, the SQL connection string seems to ignore the UID and PSW and connects regardless, maybe with the logged-in Administrator user via Windows Authentication?

I also can't access the \admin\admin.aspx page locally - only from a different computer. I set the folder to DENY the IUSR account, and I get the authentication prompt locally and remotely. When I enter my Administrator credentials on my remote computer, everything is fine, but the same credentials don't work from a browser running on the server itself - I get a 401.1 Unauthorized response from IIS.

Anyway, I mainly wanted to let you know about the MessageBox() statement in the OnLoad() function, which should be adjusted to prevent the 'User-interface' error. If you have any ideas about my other 'user' issues, I'd appreciate any clues you might have.

- Mike McDonald

Gravatar is a globally recognized avatar based on your email address. re: MessageBox() call in (wwServer) OnLoad template
  Rick Strahl
  Mike McDonald
  Feb 24, 2019 @ 12:25am

Yeah that's not right 😃

*** Add persistent SQL Server Connection
#IF WWC_USE_SQL_SYSTEMFILES
    THIS.AddProperty("oSQL", CREATE("wwSQL"))
    IF !THIS.oSQL.Connect(THIS.oConfig.cSQLConnectString)
	    ERROR "Couldn't connect to SQL Service. Check your SQL Connect string in the application startup INI file." 
    ENDIF
#ENDIF

This should work more universally, although the experience in development will be a bit less friendly as you get an error dialog.

In COM in production this should show the startup load error page.

Gravatar is a globally recognized avatar based on your email address. re: MessageBox() call in (wwServer) OnLoad template
  Mike McDonald
  Rick Strahl
  Feb 25, 2019 @ 12:40pm

Rick -

For some reason, if Trace() isn't called within (myProject)::OnLoad() where the SQL connection fails, then that error doesn't present itself in any way, at least in unattended / production mode. When running from VFP in debug mode, it stops on the ERROR call as expected, but a SQL connection issue is more likely to happen when moving to a live server.

Checking wwServer.prg it looks like the OnError() should call to LogError() and that function calls Trace(). It also immediately calls LogRequest() which won't work because the SQL connection isn't right and so it can't write to the SQL request log. From my testing, it looks like it may not be getting to LogError() for whatever reason?

This is running with Server.lDebugMode = .F. and having started up the executable from the Admin.aspx > Web Connection Module Administration page. Both file-based and COM modes will start up the executable (I'm not seeing any UI either way, but the exe shows up in Task Manager).

However, any hit to the site will only eventually get a Timeout response and no indication on the page or on the server about the SQL error. I'm only testing with the .NET handler, not using wc.dll at all. Nothing shows up in wcTraceLog.txt, unless I add a Trace() call in my OnLoad() code, right before the ERROR command.

- Mike McDonald

Gravatar is a globally recognized avatar based on your email address. re: MessageBox() call in (wwServer) OnLoad template
  Rick Strahl
  Mike McDonald
  Feb 25, 2019 @ 01:24pm

It should... Any error in OnLoad() should result in an error page - it should also be logged.

OnLoad() is fired internally from OnLoadInternal() which basically wraps the call, captures exceptions and then calls OnError(loException) to force it to display the error and log it.

HIDDEN FUNCTION OnLoadInternal

IF THIS.lDebugMode 
   THIS.OnLoad()
ELSE
	TRY   
	   IF !FILE("wwipstuff.dll")
	   	  ERROR "Can't find wwipstuff.dll. " +CHR(13) + CHR(13) +;
	   	        "Please make sure that all the DLLs from the Web Connection install folder " +CHR(13) +;
	   	        "are copied to your `deploy` folder: " + CHR(13) + CHR(13) +;
	   	        "COPY c:\wconnect\*.dll .\" + CHR(13) + CHR(13) 
	   ENDIF
	   
  	   THIS.OnLoad()	   
	CATCH TO loException
	    *** Flag for 
		this.lStartupError = .T.
		
	    *** Capture error and write it out to error log
        IF EMPTY(loException.Details)
           loException.Details = "Code inside of Server OnLoad() failed"
        ELSE
           loException.Tag = "Code inside of Server OnLoad() failed"
        ENDIF

        *** Base error handling	    
	    this.OnError(loException)    
	FINALLY
		IF THIS.lUnattendedComMode AND this.lComObject
		   SYS(2335,1) 
		ENDIF
	ENDTRY
ENDIF

*** Create Empty Request object that we'll reuse
THIS.oRequest = CREATE(THIS.cRequestClass)

THIS.lInStartup = .F.

ENDFUNC

I'm not sure what you're saying. The code in the template was wrong - the code I posted is my fix which will be updated in the templates going forward.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: MessageBox() call in (wwServer) OnLoad template
  Mike McDonald
  Rick Strahl
  Feb 25, 2019 @ 06:08pm

Rick -

The code in the template was wrong - the code I posted is my fix which will be updated in the templates going forward.

I made the same change in my server's OnLoad function, removing the MessageBox() and calling ERROR instead. However, if I don't include a Trace() call before the ERROR call right at that spot (in my OnLoad() code), then the SQL error doesn't show up anywhere. The request ends up with a timeout response.

I checked the OnLoadInternal() source and I agree that it looks like it should call the OnError() handler, which should fire the Trace() and (attempt to) log to wwRequestLog. I understand the wwRequestLog record won't get added (because WWC_USE_SQL_SYSTEMFILES is .T. and the problem is with the SQL connection).

But when I build my executable and test this out in non-debug, unattended mode, the wcTraceLog.txt file doesn't get any SQL message added, and any page hit will time out instead of giving an error response.

- Mike McDonald

Gravatar is a globally recognized avatar based on your email address. re: MessageBox() call in (wwServer) OnLoad template
  Rick Strahl
  Mike McDonald
  Feb 25, 2019 @ 06:48pm

Hmmm... The default connection timeout in FoxPro for Sql Connections is 15 seconds. Are you seeing it hang that long or are you not waiting that long for the request to be timing out?

You can try putting SQLSETPROP(0,"ConnectTimeout",3) or something like that to make the timeout much shorter and fail fast to avoid any timeout issues in Web Connection. This should fail in 3 seconds.

While looking at this I added an .nTimeout property to wwSql that does this in a more OO way.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: MessageBox() call in (wwServer) OnLoad template
  Mike McDonald
  Rick Strahl
  Feb 26, 2019 @ 10:18am

Rick -

OK, I finally figured out that my issue was because the Server.lDebugMode flag was actually set to .T. instead of .F., and with that corrected, I do get the error page quickly returned noting the SQL connection issue. Sorry for the run-around here.

In my main project's subclass of wwServer, I had initialized the lDebugMode property to .F. (right under DEFINE CLASS...) but it turns out that gets overwritten by the configuration settings. Even though DebugMode wasn't in the project's INI file, the wwServerConfig class defaults lDebugMode to .T.

I suggest adding the DebugMode setting to the default INI file which is created when setting up a new project.

- Mike McDonald

Gravatar is a globally recognized avatar based on your email address. re: MessageBox() call in (wwServer) OnLoad template
  Rick Strahl
  Mike McDonald
  Feb 26, 2019 @ 05:09pm

I suggest adding the DebugMode setting to the default INI file which is created when setting up a new project.

Good idea...

+++ Rick ---

© 1996-2019