What does add key value means in web.config file - web-services

HI all i am trying to figure out the values and their meanings in web.config files, there are two lines which are not making sense to me if you can elaborate on this please.
<add key="Imp.Import.shops.FileLocation" value="C:\_imp\" />
<add key="Imp.Import.shops.ArchiveLocation" value="C:\_imp\_archive\" />

It just allows for many entries for a section, the key must be unique. It's typically used when there is code written to look for that exact entry, for example the appSettings section of the web/app .config files are for general use. For those values to be loaded and used you must add code to look for a specific key so there is an implied contract between adding an item in the appSettings and adding code to actually use it.
To read the setting value:
Add a reference to System.Configuration.ConfigurationManager
Code:
var archiveLocation = ConfigurationManager.AppSettings["Imp.Import.shops.ArchiveLocation"];
If you didn't write the system then you can safely assume there is code written that needs to read these settings, the key identifies the setting by name.

Related

Pre-Processing C++ file using MSBuild and Visual Studio 2012+

I have a series of standard cpp files and each of these files contain a file-specific #include statement. However, the content of those included files must be populated by a pre-processing tool prior to invoking the standard C++ compiler.
The tricky part is that I want this to be fully integrated into Visual Studio using MSBuild. Therefore, when I bring up Visual Studio's Property Window on a cpp file, I want to see all the standard C++ compiler options and, ideally, some Custom Properties controlling the pre-processor tool. As a OOP analogy, I want my build tool to inherit everything from the standard CL MSBuild Rule, and add some Custom Properties & Build Steps to it.
I have successfully done this through an extremely laborious process of basically creating a Custom MSBuild Rule and Copy/Paste most of the C++ Options into my Custom Rule. Finally, I then pass along the million C++ Options to the standard C++ compiler through the CommandLineTemplate entry in my MSBuild .props file. It's ridiculously complicated and the C++ options don't automatically get updated as I update Visual Studio.
I can find plenty of examples of Custom MSBuild Rules, but I haven't been able to find one where it piggybacks onto an existing one.
Not a lot of love for MSBuild, I take it...
Anyway, after years of going back and forth on that one, I finally found something, soon after I posted my question. The key was to search for "extending" existing Rule which, apparently, I hadn't tried before.
Usually, when you create a Build Customization in VS, you end up with 3 files:
MyCustomBuild.xml:
Contains the Properties & Switches, as shown on the VS's Property Sheet.
MyCustomBuild.props:
Contains default values for those Properties. They can be made conditional through the use of the Condition attribute.
MyCustomBuild.targers:
Contains a line to load up your xml and the Target/Task entries.
So the first part was to extend the existing C/C++ Properties as shown in Visual Studio. I found this link, which finally gave me something to work with:
https://github.com/Microsoft/VSProjectSystem/blob/master/doc/extensibility/extending_rules.md
Here's the xml bit.
<Rule
Name="RuleToExend"
DisplayName="File Properties"
PageTemplate="generic"
Description="File Properties"
OverrideMode="Extend"
xmlns="http://schemas.microsoft.com/build/2009/properties">
<!-- Add new properties, data source, categories, etc -->
</Rule>
Name attribute:
The Name attribute must match the rule being extended. In this case, I wanted to extend the CL rule, so I set that attribute = "CL".
DisplayName attribute:
This is optional. When provided, it will overwrite the tool's name seen on the Property Sheet. In this case, the tool name shown is "C/C++". I can change it to show "My C/C++" by setting this attribute.
PageTemplate attribute:
If this attribute is provided, it must match the overwritten rule's value. In this case, it would be "tool". Just leaving it out seems to work fine. I suspect this could be needed if 2 rules had the same name, but a different template. You could use this to clarify which one you wanted to extend.
Description attribute:
Optional. I don't know where that even shows up within the VS GUI. Maybe it's just for documenting the xml file.
OverrideMode attribute:
This is an important one! It can be set to either "Extend" or "Replace". In my case, I chose "Extend".
xmlns attribute:
Required. Doesn't work properly if not present.
As the link suggest, you can then provide the properties, data source and categories. Keep in mind that categories are usually displayed in the order they appear in the xml file. Since I was extending an existing Rule, my custom categories would all show up after the standard C/C++ categories. Given that my tool is for pre-processing the files, I would have preferred having my custom options at the top of the Property Sheet. But I couldn't find way around that.
Note that you do NOT need the ItemType/FileExtension or ContenType Properties, typically found for custom Rules.
So once I entered all of that, my custom pre-processing options showed up alongside the standard C/C++ properties on the Property Sheet. Note that all these new properties would be attached to the "ClCompile" Item list, with all the other C/C++ properties.
The next step was to update the .props file. I'm not going to get into it since it's pretty much standard when create these custom build Rules. Just know that you need to set them using the "ClCompile" Item, as mentioned above.
The final step was to get the .targets file to do what I wanted.
The first part was to "import" (not really an import entry) the custom Rule through the typical entry:
<ItemGroup>
<PropertyPageSchema Include="$(MSBuildThisFileDirectory)MyCustomBuild.xml" />
</ItemGroup>
Then I needed to pre-process every source file. Ideally, it would have been nicer to pre-process a file and then compile it - one file a time. I could have done this by overwriting the "ClCompile" target within my own .targets file. This Target is defined under the "Microsoft.CppCommon.targets" file (location under "C:\Program Files (x86)" varies, depending on the VS version). I basically could have Cut & Pasted the whole Target into my file, then add my pre-processing task code before the "CL" Task. I also would have needed to convert the Target into a Target Batch, by adding an "Outputs=%(ClCompile.Identity)" attribute to the "ClCompile" Target. Without this, my pre-processing task would have ran on all files before moving on to the "CL" task, bringing me back to square one. Finally, I would have needed to deal with Pre-Compiled Header files, since they need to be compiled first.
All of this was just too much of a pain. So I selected the simpler option of defining a Target which looks like this:
<Target Name="MyPreProcessingTarget"
Condition="'#(ClCompile)' != ''"
Outputs ="%(ClCompile.Identity)"
DependsOnTargets="_SelectedFiles"
BeforeTargets="ClCompile">
There are a number of attributes defined but the most important one is the BeforeTargets="ClCompile" attribute. This is what forces this target to execute before the cpp files are compiled.
I also chose to do a Target Batch processing here [Outputs ="%(ClCompile.Identity)"] because it was just easier to do what I wanted to do, if I assumed to have 1 file being processed at a time, in my Target.
The attribute DependsOnTargets="_SelectedFiles" is used to know if a GUI user has some selected file within VS Solution Explorer. If so, the files will be stored in the #(SelectedFiles) Item List (generated by the "_SelectedFiles" Target). Typically, when selecting specific files within the Solution Explorer and choosing to compile them, VS will forcefully compile them even if they are up-to-date. I wanted to preserve that functionality for the automatically-generated pre-processed include files, and forcefully regenerate them as well, for those selected files. So I added this block:
<ItemGroup Condition="'#(SelectedFiles)' != ''">
<IncFilesToDelete Include="%(ClCompile.Filename)_pp.h"/>
</ItemGroup>
<Delete
Condition="'#(IncFilesToDelete)' != ''"
Files="%(IncFilesToDelete.FullPath)" />
Note that the automatically-generated include files are named SourceFileName_pp.h. By deleting those files, my pre-processing Task will forcefully re-generate them.
Next, I build a new Item list from the "ClCompile" Item list, but with the "_pp.h" versions of the files. I do so with the following code:
<ItemGroup>
<PPIncFiles
Condition="'#(ClCompile)' != '' and '%(ClCompile.ExcludedFromBuild)' != 'true'"
Include="%(ClCompile.Filename)_pp.h" />
</ItemGroup>
The final part is a little uglier.
In order to run my pre-processing exe, I use the standard "Exec" Task. But I obviously only want to run it if the source file is newer than the generated file. I do so by storing the well-known metadata "ModifiedTime" of the source file, and the generated file into a couple of dynamic Properties. But I can't use the ModifiedTime metadata directly, as it's not an comparable value. So I used the following code, which I have found on StackOverflow here:
Comparing DateTime stamps in Msbuild
<PropertyGroup>
<SourceFileDate>$([System.DateTime]::Parse('%(ClCompile.ModifiedTime)').Ticks)</SourceFileDate>
<PPIncFileDate Condition="!Exists(%(PPIncFiles.Identity))">0</PPIncFileDate>
<PPIncFileDate Condition="Exists(%PPIncFiles.Identity))">$([System.DateTime]::Parse('%(PPIncFiles.ModifiedTime)').Ticks)</PPIncFileDate>
</PropertyGroup>
Note that I can store the timestamps in Properties, given that the Item Lists only contain one Item per Target Pass, because of Target Batching.
Finally, I can invoke my pre-processor using the "Exec" Task, as follows:
<Exec
Condition="'#(PPIncFiles)' != '' and $(SourceFileDate) > $(PPIncFileDate)"
Command="pptool.exe [options] %(ClCompile.Identity)" />
Supplying the options was yet, another headache.
Typically, the switches as defined under the xml file are just passed to a "CommandLineTemplate" metadata under the .props file using [OptionName]. This will pass the "Switch" attribute of the Property defined under the xml file. But that implies defining your own TaskName item, made from a TaskFactory, under the .targets file. But in my case, I was just using the existing "Exec" Task, which doesn't know anything about my custom Properties. I didn't know how to retrieve the "Switch" attribute in this case, and what seems to be available is just whatever the "Name" attribute contains. Luckily, a Property has both a Name and a DisplayName. The DisplayName is what the GUI user sees. So I just copied the "Switch" value into the "Name" value, when defining the Properties under the xml file. I could then pass the option to the Exec Task using something like:
<Exec
Condition="'#(PPIncFiles)' != '' and $(SourceFileDate) > $(PPIncFileDate)"
Command="pptool.exe %(ClCompile.Option1) %(ClCompile.Option2)... %(ClCompile.Identity)" />
Where I defined all my Properties as "EnumProperty", with an "EnumValue" having Name="" for disabled options, and other EnumValue having Name="switch" for the others. Not very elegant, but I didn't know a way around this.
Finally, it is recommended that when automatically generating files, the .targets file should also include a way to clean them up when the user Cleans up the Project. That's pretty standard but I'll include it here for convenience.
<PropertyGroup>
<CleanDependsOn>$(CleanDependsOn);PPIncCleanTarget</CleanDependsOn>
</PropertyGroup>
<Target Name="PPIncCleanTarget" Condition ="'#(ClCompile)' != ''">
<ItemGroup>
<PPIncFilesToDelete Include="%(ClCompile.Filename)_pp.h" />
</ItemGroup>
<Delete Files="%(PPIncFilesToDelete.FullPath)" Condition="'#(PPIncFilesToDelete)' != ''"/>
</Target>

How to break caching on exist-db of included XSLs in Transform

I have a large set of XSLs that we recently went through and implemented a shared XSL template with common bits. We included an xsl:include in all the main XSLs now to pull these in. We had no issues at first until we started to make changes to the shared XSL.
For information, the whole system is web based, calling queries to dynamically format documents in the database given different XSLs through XSL FO and RenderX.
The main transform is:
let $fo := util:expand(transform:transform($articles, doc("/db/Customer/data/edit/xsl/Custbatch.xsl"), $parameters))
That XSL (Custbatch.xsl) has:
<xsl:include href="Custshared.v1.xsl"/>
If we make an edit to "Custshared.v1.xsl" is not reflected in the result because it is obvious that "Custshared.v1.xsl" is being cached and used. We know this because as you can see the name now includes "v1". If we make a change and change all the references say from v1 to v2, it all works. But this seems a bit ridiculous as that means we have to change the 18 XSLs that include this XSL or do something silly like restart the database.
So, what am I missing in the setup or controller.xql (which has the following on all not matched paths), to get things not to cache. I assume that is all internal so this setting likely does not matter. Is there some other setting in the config that does?
<dispatch xmlns="http://exist.sourceforge.net/NS/exist">
<cache-control cache="no"/>
</dispatch>
In reading the document here: http://exist-db.org/exist/apps/doc/xsl-transform.xml, it states:
"The stylesheet will be compiled into a template using the standard Java APIs (javax.xml.transform). The template is shared between all instances of the function and will only be reloaded if modified since its last invocation."
However, if I change an included XSL, it is not being used.
Update #1
I even went as far as creating a query that returns the XSL that is included, then I use:
<xsl:include href="http://localhost/get-include-xsl.xq"/>
This does work as formatting is not broken, but changing the underlying XSL yields the same result. So even that Xquery result is cached.
Update #2
And yes, through some simple test all is proven.
If I make any change to the root template (like add a meaningless space) and run, it does include the changes made in the include. If I only change the included XSL, no changes happen.
So lacking anything else, we could always write a Xquery that basically touches all the main templates after a change is made to the include template. Seems so wrong as a workaround.
Update #3
So the workaround we are currently using is that we have an unused "variable" in the XSL (version) and when we update the shared template, we execute that query which basically updates the value in that variable. At least it's only one XQuery and maybe we should attach to a trigger.
There is a setting in $exist-db-root$/conf.xml for the XSL transformer where you can turn off caching: <transformer class="net.sf.saxon.TransformerFactoryImpl" caching="no"> (The default is 'yes')

Sitecore media publishing to file system when not configured to do so

I have a SiteCore instance where the web.config values for media are as follows:
<setting name="Media.DisableFileMedia" value="false" />
<setting name="Media.UploadAsFiles" value="false" />
<setting name="Media.FileFolder" value="/App_Data/MediaFiles" />
<setting name="Media.UseItemPaths" value="true" />
So, this should mean that the item will be stored in the database and not the file system, correct? I ask because they are being stored on the file system, with a path that looks like this:
/App_Data/Replicated/MediaFiles/6/4/E/{64EC628B-9C94-4416-B9BD-5A90EA7D8971}220px-Liliumbulbiferumflowertop.jpg
Does anyone know why that would be? This is a small part of a larger puzzle I'm trying to understand.
I have learned that users can manually specify whether a file should be uploaded as files on the filesystem. I discovered that content editors on a site I have been developing were doing so out of habit based on past sites they had worked on. To prevent users from having this choice, you may set the Upload.UserSelectableDestination setting to false (default is true).
Media.DisableFileMedia is more to turn on or off the option of either storing the media item in SC or on the file system (in the actual SC UI)
Media.UploadAsFiles is used to indicate whether the media items are put in SC (if false) or on the file system (if true) - If you have DisableFileMedia set to true, then this is ignored and considered to be "true"
Media.FileFolder is obviously the location of where to put the files on the file system, should any the above be set to true.
Media.UseItemPaths actually has nothing to do with storing media items on the file system. It simply is a toggle between showing URLs like "~/media/[item id]" vs the full path of the media item.
I have met the same problem. After the 5 hours of investigation, i found that App_config\Include\ScalabilitySettings.config overrides the Media.FileFolder value. So disable the ScalabilitySettings.config and try again. It will store all file in the folder which was specified by the Media.FileFolder setting.
Answer for solving the problem:
disable App_config\Include\ScalabilitySettings.config or change value of Media.FileFolder in this config

Can YQL Open Data Tables make use of multiple URL fields that its XML scheme seems to support?

As I experiment more and more with making my own Open Data Tables for YQL I find what might be some gaps in the documentation. As I'm a hands-on learner and like to understand everything I use I probe these gaps to try to learn how everything works.
I've noticed that in the XML format for Open Data Tables, there is a <urls> "array" which usually contains just a single <url> element though sometimes there is no <url>. Here's the beginning of a typical ODT XML file:
<table xmlns="http://query.yahooapis.com/v1/schema/table.xsd" https="true">
<meta>
<author>Paul Donnelly</author>
<documentationURL>http://developer.netflix.com/docs/REST_API_Reference#0_52696</documentationURL>
</meta>
<bindings>
<select itemPath="" produces="XML">
<urls>
<url env="all">http://api.netflix.com/catalog/titles/</url>
</urls>
But I can't seem to find in the documentation whether it can ever contain more than one. I can't find any examples that do but when I try adding more than one everything works and no errors are thrown, though I also can't find any way to access the <url> elements beyond the first one.
Is there any use for the url/urls fields being an XML array? Is there any way to make use of more than one url here? Or is it just a quirk of the format that has no real reason?
Is there any use for the url/urls fields being an XML array?
Is there any way to make use of more than one url here?
The <url> elements can have an env attribute. This env attribute can contain all, prod, int, dev, stable, nightly, perf, qaperf, gamma or beta.
When the table is executed, the current environment (the YQL environment, not the more familiar environment file) is checked and the first matching <url> (if any) is used. If no matching env is found (and there is no all, which is pretty self-descriptive) then an error will be issued; for example, "Table not defined in this environment prod".
Note that for public-facing YQL, the environment is prod; only prod and all make sense to be used in your Open Data Tables.
Or is it just a quirk of the format that has no real reason?
Not at all.
I assume that this information is "missing" from the online documentation purely because it is only useful internally within Yahoo!, but equally it could just be another place where the docs are somewhat out-of-date.
Finally, none of the 1,100 or so Community Open Data Tables specify more than one <url>, and only a handful (55) make use of the env attribute (all using the value all).

Build validation rules for item DisplayName property

I'm working on a multi-language solution in Sitecore and want to use the DisplayName property of an item to represent the URL to allow for language-specific URLs.
I've set the useDisplayName web.config property to true as shown below
<linkManager defaultProvider="sitecore">
<providers>
<clear />
<add name="sitecore"
alwaysIncludeServerUrl="false"
encodeNames="true"
type="Sitecore.Links.LinkProvider, Sitecore.Kernel"
addAspxExtension="false"
shortenUrls="true"
languageEmbedding="asNeeded"
languageLocation="filePath"
useDisplayName="true" />
</providers>
</linkManager>
I've also been playing with the <encodeNameReplacements> section which can replace %20 with a hyphen in the URL to give nice clean URLs - this is done with the following for those who are interested:
<replace mode="on" find=" " replaceWith="-" />
All very good, except that Sitecore breaks if a user enters a hyphen within a DisplayName with the above setting turned on.... If I turn the above setting off, then I have to ensure that users enter nice hyphen separated values for the DisplayName otherwise we start seeing nasty %20s again in the URL...
So, is there a way to validate the DisplayName property to either disallow or allow hyphens being used?
Or, even better, is there a way to hook into whatever code is executed when the encodeNameReplacements thing happens? This would be ideal, as I could allow users to enter whatever they like for DisplayName, then just sanitise this value on the fly.
There is a solution for this, but it will require some coding and it's quite complex.
I have used this kind of solution in many projects before and it's the only way of solving this, that i'm aware of.
You don't want to really replace spaces with hyphens when saving the item, because it's not user friendly.
My solution works at runtime.
First get rid of the <replace> rule you added.
Then create your own LinkProvider (inherit from Sitecore's default provider).
Inside the LinkProvider create a method to "normalize" the item's displayname (e.g. replace spaces for hyphens), let's call this method NormalizeDisplayName(). Make it public and static cause you will need it later.
So now you have managed to let Sitecore replace all spaces with hyphens in links. The rest you can still configure using the default provider options (addAspxExtension="false" useDisplayName="true", etc)
Next up is the ItemResolver: Sitecore's default ItemResolver is not going to recognize the item path anymore so you are going to add your own ItemResolver to fix this.
Create a class that inherits from Sitecore.Pipelines.HttpRequest.HttpRequestProcessor and configure it to be used in the <httpRequestBegin> pipeline after the default ItemResolver.
Now, when the itemresolver is processed you will first split up the requested itempath (let's assume that "/category-name/subitem-name" was requested).
Starting from the siteroot (which can be pulled from Sitecore.Context.Site), loop through all children while normalizing their item names using your NormalizeDisplayName() method you created earlier, until you find one that matches the part of your item path.
So in this case, loop through the children of your Home item until you find one that matches normalized displayname "category-name". Then do the same thing for the children of that item until you find the item with normalized displayname "subitem-name".
This way you can resolve the requested item and it will also work if the original displayname already contained hyphens!
I'm sorry that I can't give you complete code examples as it's quite complex and is not limited to just the above things. You also need to think about redirecting if the URL is not properly formatted and make exceptions for master/core database to prevent Sitecore from breaking.
Hope this helps you!
If you see the source in .net reflector (Sitecore.Shell.Framework.Commands.SetDisplayName) there are no pipelines that runs.
You could make a Saving event, making the display name, as you want replacing hypen with a space
public void OnItemSaving(object sender, EventArgs args)
{
Item item = Event.ExtractParameter(args, 0) as Item;
item.Appearance.DisplayName = item.Appearance.DisplayName.Replace("-", " ");
}
Just a quick example of the event