How to add a xml in web.config? - c#

I have some complex data which is used for application configuration in xml format. I want to keep this xml string in web.config. Is it possible to add a big xml string in web.config and get it in code everywhere?

If you don't want to write a configuration section handler, you could just put your XML in a custom configuration section that is mapped to IgnoreSectionHandler:
<configuration>
<configSections>
<section
name="myCustomElement"
type="System.Configuration.IgnoreSectionHandler"
allowLocation="false" />
</configSections>
...
<myCustomElement>
... complex XML ...
</myCustomElement>
...
</configuration>
You can then read it using any XML API, e.g. XmlDocument, XDocument, XmlReader classes. E.g.:
XmlDocument doc = new XmlDocument();
doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
XmlElement node = doc.SelectSingleNode("/configuration/myCustomElement") as XmlElement;
... etc ...

There are several ways of achieving what you want (an XML fragment that is globally and statically accessible to your application code):
The web.config is already an XML file. You can write a custom configuration section (as described here) in order to fetch the data from your custom XML.
You can encode the XML data (all < to <, > to &gt, & to &, " to &quote;)
You can put the XML data in a <![CDATA[]]> section
Don't use web.config for this, but a Settings file as #Yuck commented
That last option is the best one, in terms of ease of development and usage.

The configuration sections in web.config support long strings, but the string has to be a single line of text so they can fit into an attribute:
<add name="" value="... some very long text can go in here..." />
The string also can't contain quotes or line breaks or other XML markup characters. The data is basically XML and it has to be appropriately encoded.
For example, if you have XML like this:
<root>
<value>10</value>
</root>
it would have to be stored in a configuration value like this:
<add key="Value" value="<root>
<value>10</value>
</root>" />
Which kind of defeats the purpose of a configuration element.
You might be better off storing the configuration value in a separate file on the file system and read it from there into a string or XmlDocument etc.

Related

how do I read from a file and update it in c#

I need to make changes to a web.config, so I need to read up until the point where I need to make the change, make the change and then write my update out to the file.
So let's say the file contained:
<add key="Version_PSM" value="2.2.0"/>
<add key="Version_MLF" value="2.0.3"/>
And I needed to update the version pf Version_PSM to "2.1". What's the best way to do this? I've tried opening a FileStream and then creating a StreamReader and a StreamWriter using it, but that doesn't work. As I read lines from the file looking for the key I want to update the Writer stays in position at the beginning of the file, so when I write it doesn't overwrite what I've just read - it writes it to the top of the file. So first I tried something like this:
// Repeat in a loop until I find what I'm looking for...
string readLine = sr.ReadLine();
sw.WriteLine(readline);
which advances the position of the writer, but duplicates what's in the file. I need to position the writer to overwrite the text that I want to update and leave everything else as-is.
So I tried just:
readLine = sr.ReadLine();
sw.WriteLine();
but that just writes blanks to the file.
There's gotta be an easy answer here that I'm just missing!
Since you need to change values during installation, you could use LINQ to XML to solve your problem (using System.Xml.Linq;). Typically a web.config file looks like
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings>
<add key="Version_PSM" value="2.2.0" />
<add key="Version_MLF" value="2.0.3" />
</appSettings>
</configuration>
You are able to access and edit nodes based on their names and attributes. After you changed some values you can save the changes. In the following example we are changing the value of the Version_PSM setting. As you can see dealing with the namespace correctly is a bit trick in this case.
//Specify path
string webConfigFile = #"\web.config";
//Load the document and get the default configuration namespace
XDocument doc = XDocument.Load(webConfigFile);
XNamespace netConfigNamespace = doc.Root.GetDefaultNamespace();
//Get and edit the settings
IEnumerable<XElement> settings = doc.Descendants(netConfigNamespace + "appSettings").Elements();
XElement versionPsmNode = settings.FirstOrDefault(a => a.Attribute("key").Value == "Version_PSM");
versionPsmNode?.Attribute("value").SetValue("New value");
//Save the document with the correct namespace
doc.Root.Name = netConfigNamespace + doc.Root.Name.LocalName;
doc.Save(webConfigFile);

is it possible to get a value for an xml file from an xml file

Hi I don't think this is possible but I have a value that needs to be used in multiple xml Config files for a Sitecore site. The problem is that the client only wants to update the value in one place.
for example if I have a file with a node with a value of
<settingexample name="ExampleGroup"/>
can I replace ExampleGroup with something that might link it to a settings xml file with the following setting
<setting name="ExampleProject.UserDomain" value="ExampleGroup"/>
That way all the xml nodes will match if I change it in a single place.
You could use <sc.variable> like Sitecore does for the data folder.
Declare the variable:
<sc.variable name="dataFolder" value="/data" />
And then use it:
<setting name="DebugFolder" value="$(dataFolder)/debug" />

How to search through XML to find bad nodes

I have a large XML file (68Mb), I am using SQL Server Business Intelligence Studio 2008 to extract the XML data into a database. There is an error in the XML file some where that prevents it from executing. Possibly a missing tag or something like that. The file is so large I cant manually sort through it looking for the error.
Below is a sample of the the XML schema used.
How can I use XPath to sort through the XML in VS 2012 using C#?
An example would be great!
-<PhoneNumberList>
<PhoneNumber value="1234567890" type="Phone"/>
</PhoneNumberList>
-<YearsOfServiceList>
<YearsOfService experienceInMonths="24" description="SuperAdmin" objectCode="049"/>
</YearsOfServiceList>
</Person>
-<Person dob="1960-01-09T00:00:00" lastName="Smith" middleName="Will" firstName="John" id="9999-9999-9999">
-<SiteList>
-<Site id="2014" siteLongName="HA" siteCode="1255" systemCode="999">
-<StaffPositionList>
<StaffPosition id="73" staffPosition="Administrator"/>
</StaffPositionList>
</Site>
</SiteList>
-<ProgramList>
<Program id="1234" siteLongName="ABC" siteCode="0000" systemCode="205"/>
<Program id="5678" siteLongName="DEF" siteCode="0000" systemCode="357"/>
</ProgramList>
-<TypeList>
<Type Description="Leader" certificateType="D"/>
<Type Description="Professional" certificateType="P"/>
</TypeList>
-<EmailList>
<Email value="jsmith#somesite.com" type="Email"/>
</EmailList>
-<PhoneNumberList>
<PhoneNumber value="1234567890" type="Phone"/>
</PhoneNumberList>
-<YearsOfServiceList>
<YearsOfService experienceInMonths="24" description="SuperAdmin" objectCode="049"/>
</YearsOfServiceList>
</Person>
</PersonList>
</GetPersonDetail>
If you want to do it in code then create an XSD file describing a valid format for the data, embed it as a resource in your app and then use code like this
var errors = new List<string>();
var schemaSet = new XmlSchemaSet();
schemaSet.Add("", XmlReader.Create(new StringReader(Properties.Resources.NameOfXSDResource)));
document.Validate(schemaSet, (sender, args) =>
{
errors.Add(args.Message);
}
);
This will give you a list of validation errors.
You don't need to search "by hand" if you use a competent text editor. NotePad++'s XML plugin, for instance, can determine if your XML as a whole is well-formed or valid, and both instances will provide separate error messages.
If you don't have a schema and the file is well-formed, you can use the CLR's System.XML namespace to read in the document and then iterate through its nodes using LINQ-to-XML, which would allow you to very finely control which nodes go where. With LINQ, you could either create a new XML file with only the valid entries, procedurally correct the invalid entries as you determine where they are, or even just write to your SQL server database directly.
Your troubleshooting process should be something as follows:
Is the XML well-formed? I..e, does it comport to the fundamental rules of XML?
Is the XML valid? I.e., does it have the elements and attributes you expect?
Is your import query accurate?
For things like this I usually have luck checking and fixing the data in Notepad++. Install the XmlTools plugin and that has a menu for checking the xml syntax and tags.
Also, those dashes will give you problems, it's best to save out the xml file directly without copying by hand.
A 68MB XML file is no problem for XML editors such as XMLBlueprint 64-bit (http://www.xmlblueprint.com/) or Stylus Studio (http://www.stylusstudio.com/). Just check the well-formedness of your xml file (F7 in XMLBlueprint) and the editor will display the errors.

umbraco.library get nodename but string utf-8 show wrong

I get nodename like this:
string text = umbraco.presentation.nodeFactory.Node.GetCurrent().Name;
but it shows like this:
BETON KÖÅÂÂK
How can I solve it?
GetCurrent().Name should return a string
(http://our.umbraco.org/wiki/reference/api-cheatsheet/working-with-nodefactory)
So if your string looks like that either your encoding is not set to utf-8 or your App_Data\umbraco.config file is corrupt.
The NodeFactory methods are basically a facade in front of the umbraco.config file - so have a look in that file to see if it is corrupted. The umbraco.config file is an xml file so also check that the first line is:
<?xml version="1.0" encoding="utf-8"?>
Secondly check your web.config for the encoding:
<system.web>
<globalization requestEncoding="UTF-8" responseEncoding="UTF-8"/>
Thirdly check all your Umbraco \config*.config files (which are all xml files) and make sure that the first line is:
<?xml version="1.0" encoding="utf-8"?>

Programmatic XML Diff / Merge in C#

At this moment, I am managing a piece of software that has multiple XML configuration files. When a new version of software is released, sometimes the base config files change, we currently have the software call KDiff on startup. If it detects a change, it prompts the user to choose the changes.
The problem with this approach is that KDiff is a line comparing program and not aware of the ways of XML (like Nodes, etc.)
Ideally, I would like to programmatically work with a library in C# (since we're a MS shop) that can Diff two XML files: a Source XML and a Current Working XML.
And then Merge the two together using a few simple rules:
If the Current Working XML has a node that the Source XML does not, remove it.
If the Source XML has a node that the Current Working XML does not, add it.
If both have the same node and the values differ, favor the Source XML's value, unless it the Source XML's value is set to "UseExistingValue".
For example, here's the "Source" XML:
<Configuration>
<Items>
<Item Id="1" Position="true">
<Location X="UseExistingValue" Y="UseExistingValue" Z="UseExistingValue" />
<Something/>
<SomethingElse/>
</Item>
</Items>
</Configuration>
And here's the "Current Working" XML:
<Configuration>
<Items>
<Item Id="1" Position="false">
<Location X="123" Y="234" Z="345" />
<Another/>
<Something/>
</Item>
</Items>
</Configuration>
And the merged version would look like:
<Configuration>
<Items>
<Item Id="1" Position="true">
<Location X="123" Y="234" Z="345" />
<Something/>
<SomethingElse/>
</Item>
</Items>
</Configuration>
I've looked at the MS XML Diff and Patch Tool and it definitely merges the files together, but doesn't allow for the programmatic rules that I want to define.
XMLUnit for Java devs seems promising, but the .NET version of it seems underdeveloped, which is unfortunate.
Anyone have any suggestions for either scriptable XML Diff/Merge tools and/or .NET libraries (paid or free)?
Thanks.
After a couple days of messing around, I found a solution that I think works for me. Maybe it could work for other people as well.
The MS XML Diff and Patch tool was a viable option. When you Diff first file against the second file it creates an XML "DiffGram" listing what changes it detected between the two XML files.
To take care of all 3 rules that I listed above, I Diff'd the two files in one direction, then opened the DiffGram file using Linq-to-XML and Removed all the "Add" and "Remove" lines.
XNamespace xd = "http://schemas.microsoft.com/xmltools/2002/xmldiff";
var doc = XDocument.Load(_diffGramFile);
doc.Root.DescendantsAndSelf(xd + "add").Remove();
doc.Root.DescendantsAndSelf(xd + "remove").Remove();
Then I patched up (merged) this edited diffgram against the first file and created a partially merged temporary file. This takes care of Rules 1 and 2.
Next, I Diff'd the partially merged file against the first file used. Then opened the new DiffGram and removed all Change references to "UseExistingValue".
var newdoc = XDocument.Load(_diffGramFile);
newdoc.Root.DescendantsAndSelf(xd + "change")
.Where(x => x.Value == "UseExistingValue").Remove();
And merged this edited DiffGram against the partially merged file which takes care of Rule 3. Saving this out to XML then produces the final XML merged according to the rules defined above.
Hopefully this can help out other people.
HINT: After installing the XmlDiffPatch library, the XmlDiffPatch DLL can be found in C:\Windows\assembly\GAC\XmlDiffPatch\1.0.8.28__b03f5f7f11d50a3a\XmlDiffPatch.dll

Categories