Problem Definition
This article describes how to configure a WIAPIDEMO site to use a local configuration file for creating ICA files.
Environment
Troubleshooting Methodology
We decided to perform a code review and code comparison between the WIAPIDEMO site and a configured Web Interface site.
Resolution
1. Unzip the WIAPIDEMO site and verify that you are able to open it using Visual Studio 2003.
2. In Visual Studio, modify the “static private readonly ServiceAddress xmlServiceAddress = new ServiceAddress("mpsserver", 80);” line in the Global.asax.cs file to point to the correct server and port used by the XML Service in the MetaFrame environment.
3. Build the code to verify that the WIAPIDEMO site works “as is” with the server address change.
4. Add the “key” elements in Code Section 1 to the “Appsetting” node in the web.config file for the WIAPIDEMO site.
5. Modify the “RESOURCE-ROOT:DTD” “key” to point to the “conf” folder instead of the “dtds” folder. See Code Section 2.
6. Rename the “dtds” folder in the “wiapidemo” folder to “conf”
7. Configure a Web Interface 4.0 site using the Access Suite Console.
8. Add the following files to the “conf” folder from the configured Web Interface site’s “conf” folder:
9. Modify the global.asas.cs file with the code in Code Section 3.
<add key="BOOTSTRAP_RESOURCE_PATH" value="/bootstrap.conf" />
<add key="RESOURCE-ROOT:Config" value="\conf" />
<add key="LOG:EVENT_SOURCE" value="Name to View In Event Viewer" />
From <add key="RESOURCE-ROOT:DTD" value="\dtd" />
To <add key="RESOURCE-ROOT:DTD" value="\conf" />
Add the following using statements:
// Added references
using com.citrix.wi.config; // ReloadHandler
using com.citrix.wi.aspnetenvironment; // WIASPNetStaticAdaptor
using com.citrix.authentication.web; // AuthenticationFilter
using com.citrix.wing; // MessageType
using java.util; // Locale
Replace the code in the “Application_Start” method to:
protected void Application_Start(Object sender, EventArgs e)
{
// Variable to store configuration file name
string configName = "WebInterface.conf"; // name is relative to the
// RESOURCE-ROOT:Config appSetting in the web.config
// Created adapter
WIASPNetStaticAdaptor staticEnvAdaptor = new WIASPNetStaticAdaptor( this );
// This is the class that reads in the configuration
ConfigurationProvider configProvider =
new LocalConfigurationProvider (
staticEnvAdaptor,
new WIReloadHandler(staticEnvAdaptor),
configName,
Locale.US
);
if (configProvider != null)
{
// this call is used to indicate the server where the shared config is located
// we are not using it but it still must be set
configProvider.setSiteInfo("local","local");
// The configuration file is parsed here
WIConfiguration wiConfig = configProvider.getWIConfiguration();
// Create a WebPNBuilder instance.
WebPNBuilder builder = WebPNBuilder.getInstance();
// store the WebPNBuilder object
staticEnvAdaptor.setApplicationAttribute ( "WebPNBuilder" , builder );
// for the WebPN we need a WING configuration class
com.citrix.wing.config.Configuration wingConfig = new com.citrix.wing.config.Configuration();
// copy the data from the WI config to WING config
wingConfig.setGlobalConfig(wiConfig.getGlobalConfig());
wingConfig.setMPSFarmConfigs(wiConfig.getMPSFarmConfigs());
wingConfig.setDMZRoutingPolicy(wiConfig.getDMZRoutingPolicy());
wingConfig.setClientProxyPolicy(wiConfig.getClientProxyPolicy());
// Create a WebPN instance from the configuration.
// I think this is where the configuration information is stored into the user context
WebPN webPN = builder.createWebPN(wingConfig, staticEnvAdaptor);
// store the WebPN object
staticEnvAdaptor.setApplicationAttribute ( "WebPN" , webPN );
}
}
Add the code for the WIReloadHandler right after the Application_Start method:
// create a reload handler class
private class WIReloadHandler : ReloadHandler
{
// Create the needed variables
private WIASPNetStaticAdaptor staticEnvAdaptor;
public WIReloadHandler(WIASPNetStaticAdaptor staticEnvAdaptor)
{
this.staticEnvAdaptor = staticEnvAdaptor;
}
public void reloadConfiguration(ConfigurationProvider configProvider)
{
// Ask the config provider for the initial configuration.
WIConfiguration wiConfig = configProvider.getWIConfiguration();
if( wiConfig == null )
{
return;
}
// The WI configuration has loaded successfully.
// Set the configuration in the WIASPNetStaticAdaptor
// so that the configured log settings can take effect.
this.staticEnvAdaptor.setDiagnosticLoggerConfiguration(
wiConfig.getDiagnosticLoggerConfiguration ()
);
com.citrix.wing.config.Configuration wingConfig = new com.citrix.wing.config.Configuration();
wingConfig.setGlobalConfig(wiConfig.getGlobalConfig());
wingConfig.setMPSFarmConfigs(wiConfig.getMPSFarmConfigs());
wingConfig.setDMZRoutingPolicy(wiConfig.getDMZRoutingPolicy());
wingConfig.setClientProxyPolicy(wiConfig.getClientProxyPolicy());
try
{
// Get the builder
WebPNBuilder builder = WebPNBuilder.getInstance ( );
// Create a WebPN instance from the configuration.
//
// WebPN instances allow you to perform activities outside of a user
// context, such as checking access tokens (credentials) are valid.
WebPN webPN = builder.createWebPN(wingConfig, staticEnvAdaptor);
staticEnvAdaptor.setApplicationAttribute("WebPN", webPN);
// Notify the authentication layer of any authentication configuration changes
// This must be done after any customization has been done to the configuration
// ie. the configuration is now immutable
staticEnvAdaptor.setApplicationAttribute (
AuthenticationFilter.CONFIG_OBJECT_KEY, wiConfig.getAuthenticationConfiguration ()
);
staticEnvAdaptor.setApplicationAttribute (
AuthenticationFilter.CONFIG_TIMESTAMP_KEY,
DateTime.Now.Ticks );
}
catch( com.citrix.wing.config.ConfigurationException ce )
{
// Log the configuration error and a stack trace.
staticEnvAdaptor.getDiagnosticLogger ( ).log (
MessageType.ERROR,
ce.getLocalizableMessage ( ),
ce
);
}
}
}