UseLegacyPathHandling is not loaded properly from app.config runtime element - asp.net-4.5

I'm trying to use the new long path support at my app. In order to use it, without forcing clients to have the newest .NET 4.6.2 version instelled on their machines, one should only add those elements to his app.config (see the link for more info https://blogs.msdn.microsoft.com/dotnet/2016/08/02/announcing-net-framework-4-6-2/) :
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
</startup>
<runtime>
<AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false" />
</runtime>
When I use it in my execution project it works perfectly. The problem is in my testing projects (which use Nunit). I've added app.config to my test project in the same way I've added it to the execution project.
Using the ConfigurationManager class I've managed to ensure that app config indeed loaded (in short: using an app setting which i was able to retrieve in a unit test).
Using ConfigurationManager.GetSection("runtime"), I even managed to ensure the runtime element has been loaded properly (_rawXml value is the same as in app.config).
But (!) for some reason the app config runtime element is not influencing the UseLegacyPathHandling variable and therefore all of my calls with long path fail.
I guess the problem is somehow relates to the fact that testing projects become dll's that are loaded using the Nunit engine, which is the execution entry point.
I'm facing the exact same problem in another project I have, which is a dll loaded by Office Word application. I believe the problem is the same in both cases and derived from the fact that the projects are not meant to be an execution entry point.
It's important to understand that I've no access to the executions their self (Word Office or Nunit) and therefore I can't configure them myself.
Is there an option to somehow make the AppContextSwitchOverrides get loaded from scratch dynamically? Other ideas will be most welcome.

I've been having the same issue, and have noted the same lack of loading of that particular setting.
So far, what I've got is that the caching of settings is at least partly to blame.
If you check out how it's implemented, disabling the cache has no effect on future calls to values (i.e. if caching is enabled and something is accessed during that time, then it will always be cached).
https://referencesource.microsoft.com/#mscorlib/system/AppContext/AppContext.cs
This doesn't seem to be an issue for most of the settings, but for some reason the UseLegacyPathHandling and BlockLongPaths settings are getting cached by the time I can first step into the code.
At this time, I don't have a good answer, but if you need something in the interim, I've got a highly suspect temporary fix for you. Using reflection, you can fix the setting in the assembly init. It writes to private variables by name, and uses the specific value of 0 to invalidate the cache, so it's a very delicate fix and not appropriate for a long term solution.
That being said, if you need something that 'just works' for the time being, you can check the settings, and apply the hack as needed.
Here's a simple example code. This would be a method you'll need in your test class.
[AssemblyInitialize]
public static void AssemblyInit(TestContext context)
{
// Check to see if we're using legacy paths
bool stillUsingLegacyPaths;
if (AppContext.TryGetSwitch("Switch.System.IO.UseLegacyPathHandling", out stillUsingLegacyPaths) && stillUsingLegacyPaths)
{
// Here's where we trash the private cached field to get this to ACTUALLY work.
var switchType = Type.GetType("System.AppContextSwitches"); // <- internal class, bad idea.
if (switchType != null)
{
AppContext.SetSwitch("Switch.System.IO.UseLegacyPathHandling", false); // <- Should disable legacy path handling
// Get the private field that is used for caching the path handling value (bad idea).
var legacyField = switchType.GetField("_useLegacyPathHandling", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
legacyField?.SetValue(null, (Int32)0); // <- caching uses 0 to indicate no value, -1 for false, 1 for true.
// Ensure the value is set. This changes the backing field, but we're stuck with the cached value for now.
AppContext.TryGetSwitch("Switch.System.IO.UseLegacyPathHandling", out stillUsingLegacyPaths);
TestAssert.False(stillUsingLegacyPaths, "Testing will fail if we are using legacy path handling.");
}
}
}

Related

Changing the ASPNETCORE_ENVIRONMENT value from Code

I want to change the ASPNETCORE_ENVIRONMENT value from code while initializing the application. This is done with
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", [newValue]);
and happens very early on startup of the application, prior to any calls to Use[XY].
If I check the value with Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") throughout the lifetime of the application, it returns the desired value.
However, the Environment-Tag helper always uses the initial value which was set at the application's very startup (the old value).
While googling, I found a lot of posts on how to change the "ASPNETCORE_ENVIRONMENT" value from outside of the application, but none on how it is done from within the application.
The background of this question is, that we have the information about which stage the application runs, saved within the database and we want to use this information.
Update
It seems, that I have found the solution, will post it, if it is reliable.
Asp.net Core initializes at the application’s start the IWebHostEnvironment implementing instance and registers it as a singleton. This interface has a read/write property EnvironmentName, which is then used throughout the application’s lifetime as the “environment” value.
Hence the solution was:
var webHostEnvironment = [ServiceCollection].GetRequiredService<IWebHostEnvironment>();
webHostEnvironment.EnvironmentName=[my value];
Important is surely, that the assignment is as early as possible, so that in the Configure-method of the application, it is already set to its target value.
I tested some scenarios and up to now, I haven’t found any problems.

Why is Mage_Persistent breaking /api/wsdl?soap

I get the following error within Magento CE 1.6.1.0
Warning: session_start() [<a href='function.session-start'>function.session-start</a>]: Cannot send session cookie - headers already sent by (output started at /home/dev/env/var/www/user/dev/wdcastaging/lib/Zend/Controller/Response/Abstract.php:586) in /home/dev/env/var/www/user/dev/wdcastaging/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php on line 119
when accessing /api/soap/?wsdl
Apparently, a session_start() is being attempted after the entire contents of the WSDL file have already been output, resulting in the error.
Why is magento attempting to start a session after outputting all the datums? I'm glad you asked. So it looks like controller_front_send_response_after is being hooked by Mage_Persistent in order to call synchronizePersistentInfo(), which in turn ends up getting that session_start() to fire.
The interesting thing is that this wasn't always happening, initially the WSDL loaded just fine for me, initially I racked my brains to try and see what customization may have been made to our install to cause this, but the tracing I've done seems to indicate that this is all happening entirely inside of core.
We have also experienced a tiny bit of (completely unrelated) strangeness with Mage_Persistent which makes me a little more willing to throw my hands up at this point and SO it.
I've done a bit of searching on SO and have found some questions related to the whole "headers already sent" thing in general, but not this specific case.
Any thoughts?
Oh, and the temporary workaround I have in place is simply disabling Mage_Persistent via the persistent/options/enable config data. I also did a little bit of digging as to whether it might be possible to observe an event in order to disable this module only for the WSDL controller (since that seems to be the only one having problems), but it looks like that module relies exclusively on this config flag to determine it's enabled status.
UPDATE: Bug has been reported: http://www.magentocommerce.com/bug-tracking/issue?issue=13370
I'd report this is a bug to the Magento team. The Magento API controllers all route through standard Magento action controller objects, and all these objects inherit from the Mage_Api_Controller_Action class. This class has a preDispatch method
class Mage_Api_Controller_Action extends Mage_Core_Controller_Front_Action
{
public function preDispatch()
{
$this->getLayout()->setArea('adminhtml');
Mage::app()->setCurrentStore('admin');
$this->setFlag('', self::FLAG_NO_START_SESSION, 1); // Do not start standart session
parent::preDispatch();
return $this;
}
//...
}
which includes setting a flag to ensure normal session handling doesn't start for API methods.
$this->setFlag('', self::FLAG_NO_START_SESSION, 1);
So, it sounds like there's code in synchronizePersistentInf that assumes the existence of a session object, and when it uses it the session is initialized, resulting in the error you've seen. Normally, this isn't a problem as every other controller has initialized a session at this point, but the API controllers explicitly turns it off.
As far as fixes go, your best bet (and probably the quick answer you'll get from Magento support) will be to disable the persistant cart feature for the default configuration setting, but then enable it for specific stores that need it. This will let carts
Coming up with a fix on your own is going to be uncharted territory, and I can't think of a way to do it that isn't terribly hacky/unstable. The most straight forward way would be a class rewrite on the synchronizePersistentInf that calls it's parent method unless you've detected this is an API request.
This answer is not meant to replace the existing answer. But I wanted to drop some code in here in case someone runs into this issue, and comments don't really allow for code formatting.
I went with a simple local code pool override of Mage_Persistent_Model_Observer_Session to exit out of the function for any URL routes that are within /api/*
Not expecting this fix to need to be very long-lived or upgrade-friendly, b/c I'm expecting them to fix this in the next release or so.
public function synchronizePersistentInfo(Varien_Event_Observer $observer)
{
...
if ($request->getRouteName() == 'api') {
return;
}
...
}

How to update the JSF2.0 (Primefaces) tooltips dynamically without server restart

I need to update the JSF2.0 (Primefaces) tooltips dynamically without server restart.
Meaning need to find a way where tooltips (atm from properties file) of the a running application can be changed without requiring a server restart.
We are running websphere and deploying a non exploded EAR (can probably convince to deploy exploded war)
Any Ideas or tips please. Thanks you
The value attribute of the p:toolTip component must be an EL expression or a literal text. Usually, one would reference a resource bundle declared using the var attribute of the f:loadBundle tag, in the EL expression for the tooltip.
The underlying resource bundle declared using the basename attribute could be backed by a property file itself (in which case you need to place the property file in the appropriate directory on the classpath), or for that matter it could be a custom ResourceBundle implementation that could read from a properties file (located outside the container), or a database or any store for that matter.
You could therefore change your existing EL expression from the existing one defined as:
<f:loadBundle var="msg" basename="propfile_location" />
to
<f:loadBundle var="msg" basename="fully qualified class name of the ResourceBundle class" />
In simpler words, you will need to roll your own ResourceBundle class(es) to support the various locales. Needless to state, but you will need to override the ResourceBundle.getObject(java.lang.String) method, as it is invoked by the ResourceBundleELResolver implementation when evaluating the EL expressions referencing ResourceBundles.
Additionally, you will need to ensure that the ResourceBundle.getObject(java.lang.String) implementation of your ResourceBundle will always re-fetch and return the value corresponding to the provided key. Failure to ensure this would mean that the initial value fetched by the resource bundle may be returned on subsequent invocations, especially if you are caching the initial value. You are likely to encounter this behavior even if you deploy an exploded WAR file where you can modify the property file contents without a redeployment of the application, and that is why it is important to use a custom ResourceBundle implementation that does not cache values.

Best way to use groovy scripts in an application

I'm trying to use groovy scripts in my application. The problem is that GroovyScriptEngine#run always compiles the script, even if it was compiled in previous runs and hadn't changed since. Even if I set a physical output folder to save compilation results in the configuration.
What is the best way of working around this? The optimum for me is that I'm able to send the script with a folder containing precompiled results and no compilation is done (unless the script is modified of course)
Grails 1.3.5 is using Groovy 1.7.5. In that Groovy version, GroovyScriptEngine.run(..) calls the following methods: createScript(String, Binding) --> loadScriptByName(String) --> isSourceNewer(ScriptCacheEntry).
isSourceNewer(ScriptCacheEntry) is defined as (unfortunately, I didn't find a matching source file on the web):
protected boolean isSourceNewer(ScriptCacheEntry entry)
throws ResourceException {
// ...
for (String scriptName : entry.dependencies) {
// ...
return true; // without any further condition!
}
return false;
}
Which implements the (queer) logic "if a script has dependencies, it is newer than the cached script (and needs to be re-compiled)". That's not what the code is supposed to do; it's supposed to decide by modification time.
In newer versions of GroovyScriptEngine, this has been corrected (there've been massive changes to the logic), but for now, you'd need to subclass GroovyScriptEngine and overwrite isSourceNewer(ScriptCacheEntry) to fix the logic yourself.
Edit: The bug has been reported and fixed in Groovy 1.7.6. - So try using Groovy 1.7.6 in your Grails lib folder.
The solution (hack) I used at last was to stream out the scriptCache variable using xstream and to read it back and set it in the object
Not sure if this helps you, but you can alter GroovyScriptEngine's behaviour using CompilerConfiguration (see GroovyScriptEngine.setConfig). There's an option CompilerConfiguration.setRecompileGroovySource, which can be used to set whether the sources will be reloaded and recompiled if they change. You can read more about CompilerConfiguration here (page 282).

Do i *have* to use ObservableCollection in Silverlight WCF client?

When accessing Silverlight in WCF you get proxies generated with ObservableCollection
Thats fine when you're databinding, but a little clumsy when you're just calling a method. For instance the following service method :
[OperationContract]
public SearchOrdersMsgOut SearchOrders(ShippingStatusType[] shippingStatuses,
string[] orderId)
{
}
gets generated with ObservableCollection. What! They're just parameters. Why would I ever want to 'observe' them?
I'm fine if I have to do this - but it seems like there should be a way to force simple array structures when I know I'm never databinding - especially on input messages.
I'd much rather do this :
searchCriteria.PaymentStatus = new [] { PaymentStatusType.PaymentFailed, PaymentStatusType.Unpaid };
than this :
searchCriteria.PaymentStatus = new ObservableCollection<PaymentStatusType> { PaymentStatusType.PaymentFailed, PaymentStatusType.Unpaid };
Is there a way?
PS. I do actually use a SearchCriteria object for my search criteria - but I simplified for this example wondering if parameters were handled differently.
You can do this service-wide, but not on a per-method basis. In the Add Service Reference dialog box, click on "Advanced", and choose "System.Array" for the Collection type. But I'm not aware of any way to do it method-by-method, i.e., use array for some methods and ObservableCollection for others.
OK here's a bizarre twist after having got used to using ObservableCollection for my silverlight clients.
I tried to return a Linq2XSD object from my WCF service - and then suddenly low and behold it changed all the ObservableCollection<T> properties into simple arrays [].
I thought it was something specific to Linq2XSD - so I tried just adding a simple XTypedElement property to the service definition:
public XTypedElement[] PipelineLogs { get; set; }
This triggers [] instead of ObservableCollection<T> in the generated proxy - where normally string[] would become ObservableCollection<string>.
Don't ask me why!
I've since removed it because I actually prefer ObservableCollection<T>. I just thought the observation might interest someone with a similar problem - especially if anyone can explain why its doing it!
Ended having the OPPOSITE problem when VS2010 RC had a bug preventing it from generating ObservableCollections.
Fortunately there are two workarounds:
Option 1:
Believe the best option – this is to update the “Reference.svcmap” file for the impacted service reference. In Solution Explorer, select “show all files” and expand the impacted reference node. There you will find the “Reference.svcmap” file, double click to open into the editor. For the observablecollection mapping, you should see currently something like this:
<CollectionMapping TypeName="System.Collections.ObjectModel.ObservableCollection`1" Category="List" />
Change TypeName value to include the Silverlight assembly “System.Windows” – like below :
<CollectionMapping TypeName="System.Collections.ObjectModel.ObservableCollection`1, System.Windows" Category="List" />
Option 2: Generate your
Reference.vb/.cs service reference
proxy code files outside of VS by
using directly SLSvcUtil.exe. Example
of running the tool via command-line
where it will address the
observablecollection issue code
generation issue: "C:\Program Files
(x86)\Microsoft
SDKs\Silverlight\v3.0\Tools\SlSvcUtil.exe”
/r:"C:\Program Files (x86)\Microsoft
Silverlight\3.0.40818.0\System.Windows.dll"
/ct:System.Collections.ObjectModel.ObservableCollection`1
http:///Service1.svc
This will by default generate a C#
version of your service reference
proxy code. If you need to generate a
VB version, you can pass a
“/Language:VB” switch.
Another thing to check (if you want ObservableCollection<T> but you're getting T[]) - is the Reference.svcmap file
Make sure that you have included 'System.Windows' in the typename.
<CollectionMapping TypeName="System.Collections.ObjectModel.ObservableCollection`1, System.Windows" Category="List" />
and not
<CollectionMapping TypeName="System.Collections.ObjectModel.ObservableCollection`1" Category="List" />
I'm guessing perhaps it can't find the Dll and defaults to []