Meeting the needs of your business from a distance

Root Element is Missing in web.config file

by Mark Shiffer 25. April 2010 02:22

While I was updating my blog recently with the latest version I ran into a perplexing error "Root Element is Missing" when trying to hit the blog after the upgrade. The web.config file looked fine, the permissions were set right on all of the folders for both IIS and file permissions. It turns out that when I copied the website up to my host about 3 files came up empty, one of them being the Web.sitemap file. Evidently, when that file is empty and the web.config file is setup for sitemaps it can trigger this error. After getting the proper files up on the host everything was resolved.

Tags:

Issues | Websites

Install Windows Service Manually

by mark shiffer 19. October 2009 17:46

Forgot this one recently, because I don’t use it very often. So I’m putting it here for future, hopefully quicker, reference.

To install a service manually in windows the instsrv.exe program should be used which allows you to specify the service name and the path to the service executable. More information is available here.

Tags:

Issues

Odd Conditional Operator Scenario

by mark shiffer 23. September 2009 13:42

Okay, without cheating, what do you think the message box will display in the following code:

   1: bool convertToInt = true;
   2: decimal test = 5;
   3:  
   4: object result = convertToInt ? Convert.ToInt32(test) : test;
   5:  
   6: MessageBox.Show(result.GetType().ToString());

Three choices come to mind: System.Int32, System.Decimal and System.Object.

The result is actually System.Decimal. I ran into this little oddity recently in code and it sent me for a bit of a loop. Reading the C# language specification sheds some light on exactly what the conditional operator is doing though:

7.13 Conditional operator

The second and third operands of the ?: operator control the type of the conditional expression. Let X and Y be the types of the second and third operands. Then,
•    If X and Y are the same type, then this is the type of the conditional expression.
•    Otherwise, if an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.
•    Otherwise, if an implicit conversion (§6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
•    Otherwise, no expression type can be determined, and a compile-time error occurs.

Since an implicit conversion from Int32 to Decimal exists, the compiler is choosing Decimal as the type for the expression.

Tags:

Programming | Issues

Override WCF Client Settings From Custom Config File

by mark shiffer 25. August 2009 14:35

Recently I needed to bring up a client for a WCF service where my assembly was being hosted in an external 3rd party application. Normally, the happy path for WCF is to read the configuration from the hosting application’s config file. In this case, the host did not have one, and I did not want to force it to have one. So, I needed a way to setup the WCF client with my own config file and not the host’s.

There are plenty of ways to configure a WCF client, but I found that the most straight forward solution for my issue was to create my own ChannelFactory<T> that could read a supplied configuration file. I ran across some code on MSDN and modified it slightly and the end-result is below.

   1: using System;
   2: using System.ServiceModel.Configuration;
   3: using System.Reflection;
   4: using System.Security.Cryptography.X509Certificates;
   5: using System.ServiceModel;
   6: using System.ServiceModel.Description;
   7: using System.ServiceModel.Channels;
   8: using System.Configuration;
   9:  
  10: namespace MAS.Interface.Client
  11: {
  12:     public class ManualChannelFactory<T> : ChannelFactory<T>
  13:     {
  14:         string configurationPath;
  15:         Uri overrideEndPoint;
  16:  
  17:         /// <summary>
  18:         /// custom client channel constructor which 
  19:         /// specifies an external configuration file
  20:         /// </summary>
  21:         /// <param name="configurationPath"></param>
  22:         public ManualChannelFactory(string configurationPath)
  23:             : base(typeof(T))
  24:         {
  25:             this.configurationPath = configurationPath;
  26:             base.InitializeEndpoint((string)null, null);
  27:         }
  28:  
  29:         /// <summary>
  30:         /// Initializes a new instance of the <see cref="ManualChannelFactory&lt;T&gt;"/> class.
  31:         /// </summary>
  32:         /// <param name="configurationPath">The configuration path.</param>
  33:         /// <param name="overrideEndPoint">The override end point.</param>
  34:         public ManualChannelFactory(string configurationPath, Uri overrideEndPoint)
  35:             : base(typeof(T))
  36:         {
  37:             this.configurationPath = configurationPath;
  38:             this.overrideEndPoint = overrideEndPoint;
  39:             base.InitializeEndpoint((string)null, null);
  40:         }
  41:  
  42:         /// <summary>
  43:         /// overrides the CreateDescription() method of the channel factory
  44:         /// to apply a new configuration file
  45:         /// </summary>
  46:         /// <returns></returns>
  47:         protected override ServiceEndpoint CreateDescription()
  48:         {
  49:             ServiceEndpoint serviceEndpoint = base.CreateDescription();
  50:  
  51:             ExeConfigurationFileMap executionFileMap = new ExeConfigurationFileMap();
  52:             executionFileMap.ExeConfigFilename = configurationPath;
  53:  
  54:             System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(executionFileMap, ConfigurationUserLevel.None);
  55:             ServiceModelSectionGroup serviceModeGroup = ServiceModelSectionGroup.GetSectionGroup(config);
  56:  
  57:             ChannelEndpointElement selectedEndpoint = null;
  58:  
  59:             foreach (ChannelEndpointElement endpoint in serviceModeGroup.Client.Endpoints)
  60:             {
  61:                 if (endpoint.Contract == serviceEndpoint.Contract.ConfigurationName)
  62:                 {
  63:                     selectedEndpoint = endpoint;
  64:                     break;
  65:                 }
  66:             }
  67:  
  68:             if (selectedEndpoint != null)
  69:             {
  70:                 if (serviceEndpoint.Binding == null)
  71:                 {
  72:                     serviceEndpoint.Binding = CreateBinding(selectedEndpoint.Binding, serviceModeGroup);
  73:                 }
  74:  
  75:                 if (serviceEndpoint.Address == null)
  76:                 {
  77:                     if (overrideEndPoint == null)
  78:                     {
  79:                         serviceEndpoint.Address = new EndpointAddress(selectedEndpoint.Address, GetIdentity(selectedEndpoint.Identity), selectedEndpoint.Headers.Headers);
  80:                     }
  81:                     else
  82:                     {
  83:                         serviceEndpoint.Address = new EndpointAddress(overrideEndPoint, GetIdentity(selectedEndpoint.Identity), selectedEndpoint.Headers.Headers);
  84:                     }
  85:                 }
  86:  
  87:                 if (serviceEndpoint.Behaviors.Count == 0 && !String.IsNullOrEmpty(selectedEndpoint.BehaviorConfiguration))
  88:                 {
  89:                     AddBehaviors(selectedEndpoint.BehaviorConfiguration, serviceEndpoint, serviceModeGroup);
  90:                 }
  91:  
  92:                 serviceEndpoint.Name = selectedEndpoint.Contract;
  93:             }
  94:  
  95:             return serviceEndpoint;
  96:         }
  97:  
  98:         /// <summary>
  99:         /// Configures the binding for the selected endpoint
 100:         /// </summary>
 101:         /// <param name="bindingName"></param>
 102:         /// <param name="group"></param>
 103:         /// <returns></returns>
 104:         private Binding CreateBinding(string bindingName, ServiceModelSectionGroup group)
 105:         {
 106:             BindingCollectionElement bindingElementCollection = group.Bindings[bindingName];
 107:             if (bindingElementCollection.ConfiguredBindings.Count > 0)
 108:             {
 109:                 IBindingConfigurationElement be = bindingElementCollection.ConfiguredBindings[0];
 110:  
 111:                 Binding binding = GetBinding(be);
 112:                 if (be != null)
 113:                 {
 114:                     be.ApplyConfiguration(binding);
 115:                 }
 116:  
 117:                 return binding;
 118:             }
 119:  
 120:             return null;
 121:         }
 122:  
 123:         /// <summary>
 124:         /// Adds the configured behavior to the selected endpoint
 125:         /// </summary>
 126:         /// <param name="behaviorConfiguration"></param>
 127:         /// <param name="serviceEndpoint"></param>
 128:         /// <param name="group"></param>
 129:         private void AddBehaviors(string behaviorConfiguration, ServiceEndpoint serviceEndpoint, ServiceModelSectionGroup group)
 130:         {
 131:             EndpointBehaviorElement behaviorElement = group.Behaviors.EndpointBehaviors[behaviorConfiguration];
 132:             for (int i = 0; i < behaviorElement.Count; i++)
 133:             {
 134:                 BehaviorExtensionElement behaviorExtension = behaviorElement[i];
 135:                 object extension = behaviorExtension.GetType().InvokeMember("CreateBehavior",
 136:                 BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
 137:                 null, behaviorExtension, null);
 138:                 if (extension != null)
 139:                 {
 140:                     serviceEndpoint.Behaviors.Add((IEndpointBehavior)extension);
 141:                 }
 142:             }
 143:         }
 144:  
 145:         /// <summary>
 146:         /// Gets the endpoint identity from the configuration file
 147:         /// </summary>
 148:         /// <param name="element"></param>
 149:         /// <returns></returns>
 150:         private EndpointIdentity GetIdentity(IdentityElement element)
 151:         {
 152:             EndpointIdentity identity = null;
 153:             PropertyInformationCollection properties = element.ElementInformation.Properties;
 154:             if (properties["userPrincipalName"].ValueOrigin != PropertyValueOrigin.Default)
 155:             {
 156:                 return EndpointIdentity.CreateUpnIdentity(element.UserPrincipalName.Value);
 157:             }
 158:             if (properties["servicePrincipalName"].ValueOrigin != PropertyValueOrigin.Default)
 159:             {
 160:                 return EndpointIdentity.CreateSpnIdentity(element.ServicePrincipalName.Value);
 161:             }
 162:             if (properties["dns"].ValueOrigin != PropertyValueOrigin.Default)
 163:             {
 164:                 return EndpointIdentity.CreateDnsIdentity(element.Dns.Value);
 165:             }
 166:             if (properties["rsa"].ValueOrigin != PropertyValueOrigin.Default)
 167:             {
 168:                 return EndpointIdentity.CreateRsaIdentity(element.Rsa.Value);
 169:             }
 170:             if (properties["certificate"].ValueOrigin != PropertyValueOrigin.Default)
 171:             {
 172:                 X509Certificate2Collection supportingCertificates = new X509Certificate2Collection();
 173:                 supportingCertificates.Import(Convert.FromBase64String(element.Certificate.EncodedValue));
 174:                 if (supportingCertificates.Count == 0)
 175:                 {
 176:                     throw new InvalidOperationException("UnableToLoadCertificateIdentity");
 177:                 }
 178:                 X509Certificate2 primaryCertificate = supportingCertificates[0];
 179:                 supportingCertificates.RemoveAt(0);
 180:                 return EndpointIdentity.CreateX509CertificateIdentity(primaryCertificate, supportingCertificates);
 181:             }
 182:  
 183:             return identity;
 184:         }
 185:  
 186:         /// <summary>
 187:         /// Helper method to create the right binding depending on the configuration element
 188:         /// </summary>
 189:         /// <param name="configurationElement"></param>
 190:         /// <returns></returns>
 191:         private Binding GetBinding(IBindingConfigurationElement configurationElement)
 192:         {
 193:             if (configurationElement is CustomBindingElement)
 194:                 return new CustomBinding();
 195:             else if (configurationElement is BasicHttpBindingElement)
 196:                 return new BasicHttpBinding();
 197:             else if (configurationElement is NetMsmqBindingElement)
 198:                 return new NetMsmqBinding();
 199:             else if (configurationElement is NetNamedPipeBindingElement)
 200:                 return new NetNamedPipeBinding();
 201:             else if (configurationElement is NetPeerTcpBindingElement)
 202:                 return new NetPeerTcpBinding();
 203:             else if (configurationElement is NetTcpBindingElement)
 204:                 return new NetTcpBinding();
 205:             else if (configurationElement is WSDualHttpBindingElement)
 206:                 return new WSDualHttpBinding();
 207:             else if (configurationElement is WSHttpBindingElement)
 208:                 return new WSHttpBinding();
 209:             else if (configurationElement is WSFederationHttpBindingElement)
 210:                 return new WSFederationHttpBinding();
 211:  
 212:             return null;
 213:         }
 214:     }
 215: }

Many thanks to Paraesthesia and MSDN.

Tags:

Issues | Programming

An error occurred while validating. HRESULT = 80004005

by Mark Shiffer 18. August 2009 16:20

While building a solution containing a setup project (vdproj) recently, I received the error: “An error occurred while validating. HRESULT = ‘80004005’. Turns out this was simply because one of the project references of the assemblies in the solution was not contained as a project in the solution. After adding the referenced project to the solution, the solution built without an issue.

Simple fix to an odd and confusing error message.

Tags:

Issues | Programming

WCF, Datasets and XML Data, An Imperfect Combination

by Mark Shiffer 3. August 2009 21:16

I recently came across an odd issue and figured I would detail it here in case it will help anyone else down the line. I have a WCF service using wsHttp binding that when called returns a custom data contract that includes a .NET DataSet as one of its data member properties. This worked great for 99% of the calls that I made to the service, but I came across one call that took 40 minutes to return! The data being returned amounted to 4MB, which is large, but does not warrant the time it was taking. Under WSE, this same contract returned in 4 seconds.

It is not suggested to return .NET classes as part of a service contract as it hampers interoperability. However, when you need to shove a great deal of relational data from the service down to the client, you either use a DataSet and its built-in XML serializer or come up with your own serialization and deserialization schemes to accomplish the same thing. I opted for the former. The XML representation might not be great, but it works and it can be interpreted by non-.NET clients if need be.

So my question was, why does this particular contract take so long to return? Is it the size, the DataSet serialization/deserialization, or something else all together. When I started investigating, one of the first things that I noticed was that message tracing showed that the contract took 3 seconds to execute on the server. Fiddler showed me that the response message was making it back to the client in the expected time. So, the 40 minutes was being taken up almost entirely on the client side, presumably while deserializing the DataSet. After a great deal of messing around with other encoding schemes I found that I could send large responses in binary form and as a Base-64 string without issue.

The kicker was when I found that I could even send a large DataSet without issue. Wait a second, that is what was causing the original issue wasn’t it? Turns out, the contract in question returned a one row, one column result where the value was a very large XML text blob. After further testing, I found that WCF and wsHttp performance degrades exponentially when a DataSet that contains an XML string column in it grows.

Lesson learned. I have the ability to manipulate this particular call to return a more formal response without the need for the XML blob. So that will solve my issue for now.

Tags:

Issues

Why Samsung Sucks! At Least, Why Samsung Sucks at Hard Drives

by Mark Shiffer 7. July 2009 13:41

In general I have been a big fan of Samsung electronics over the years. I have a Samsung plasma at home and 2 Samsung LCD monitors that are great. My problems started with Samsung when I purchased two internal SATA II hard drives from NewEgg in November of 2008. I use the hard drives with a Thermaltake hot swap drive bay for my rolling backup system at home. Everything worked great until April of 2009 when one of those two hard drives failed.

Not a big deal; hard drives fail, that’s why I have redundancy built into my backup plan. The fact that it failed after only 6 months is a bit concerning, but occasionally you get bad drives, and that is why there are warranties. Here’s where my problem begins: this particular hard drive has financially sensitive information on it. So I don’t want to blindly ship it off somewhere for RMA and never see the drive again. I would constantly be wondering in the back of my mind whether some random guy/gal got hold of the data on the drive and used it maliciously.

So, I called Samsung support and spoke with them about the issue. To my shock, the support representative acted as though this issue had never come up before! No one has ever had concerns over the security of their data when submitting their hard drive for RMA? Are you kidding me? He forwarded me to Total Tech Solutions, Samsung’s vendor who handles hard drive RMAs. Now as if Samsung’s response wasn’t bad enough, Total Tech Solutions was even more of a joke. The person I spoke with there gave no illusions of data security what-so-ever. His response to my inquiry was that the hard drives are received, checked and then immediately shipped to Korea. No way to have the drive shipped back to me, no way to secure the data, no way to do anything but to trust random people halfway around the world. Are you kidding me?

So, I called Samsung support a second time, described the scenario to another representative. The person then referred to the support manager present at the time, but wouldn’t let me speak to them. The response was that they could not help me. I tried to suggest several alternative means by which I could RMA the drive and still have some assurance of data security (take it to a local repair shop or Samsung dealer, have the drive shipped back to me after inspection, just trust the customer that the drive has failed and send a new one). No go. So I’m out a hard drive and the Samsung warranty is useless. I asked if there was anyone there who I could appeal to and was told flat out ‘no’! Seriously, are you kidding me?

My next step was to track down, Jon Kang, the president of Samsung Semiconductor, on LinkedIn. I sent him a message, but have not heard back. I don’t really expect to hear back given the track record that Samsung has shown me above.

So there is my sad story. I’ve learned my lesson. Never buy Samsung hard drives, and I might extend that to never buy Samsung products in general, but we’ll see. Secondly, I’ve learned that I should encrypt my backups even if they are supposed to be leaving my possession.

Tags:

Issues

Replacing Notepad on Vista

by Mark Shiffer 31. March 2009 14:36

I finally decided to give up on the built-in Windows Notepad (I know, I know, a long time coming). I decided to go with Notepad2, but quickly ran into a couple of issues with replacing the built-in notepad so that Notepad2 would come up in its place. Here’s what had to happen:

  1. Go to Windows\Notepad.exe, right click..Properties.
  2. Go to Security tab, click Advanced.
  3. Go to Owner tab..click Edit and select Administrators in “Change Owner to”. Click ok.
  4. Go to Permissions tab..click Edit and select Administrators..click Edit..check Allow/Full Control. Click ok.
  5. Repeat steps 1-4 for Windows\System32\Notepad.exe.
  6. Rename both Windows\Notepad.exe and Windows\System32\Notepad.exe to Notepad_Original.exe.
  7. Rename your desired notepad replace executable to Notepad.exe and copy the file to both Windows and Windows\System32.
  8. Ah, you thought you were done? No, no, no, now we need to take care of the pesky “The publisher could not be verified” dialog box that appears every time that you try to run Notepad.exe now.
  9. Run gpedit.msc.
  10. Go to User Configuration\Administrative Templates\Windows Components\Attachment Manager.
  11. Double-click “Inclusion list for moderate risk file types.
  12. On the setting tab, ensure that the Enabled radio button is checked.
  13. In the list of ‘moderate risk extensions’ type in notepad.exe. This is case-sensitive, so be sure that you have the correct name. A second option here is to just include all executables using *.exe.
    1. This policy setting allows you to configure the list of moderate risk file types. If the attachment is in the list of moderate risk file types and is from the restricted or Internet zone, Windows prompts the user before accessing the file. This inclusion list overrides the list of potentially high risk file types built into Windows and it takes precedence over the Low risk inclusion list but has a lower precedence than the High risk inclusion list (where an extension is listed in more than one inclusion list.)

Tags:

Issues | Tools

Blog Framework Update

by Mark Shiffer 29. March 2009 17:47

I updated my blogging framework this weekend. So, if anyone happens to notice any oddities I would appreciate it if you could let me know. I had to jump through a few hoops to get it to work again as it had been a while since I last updated and I have several customizations to the framework that I had to reapply, not to mention making sure all of the data stayed in tact.

Tags:

Issues

Default Gateway Address Missing

by Mark Shiffer 24. March 2009 02:34

I recently upgraded my DNS and DHCP server from Windows 2003 to Windows 2008. I pretty painless upgrade and I thought all of my settings and installed programs stayed in tact, but that was not the case.

First, I found that Cobian Backup would not run after the upgrade, so I had to uninstall and reinstall that. No big deal, then I noticed that as my IP leases were expiring my computers on the network were no longer receiving the default gateway address. They were getting IP addresses just fine, which gave them internal network access, but they could not reach the internet without the gateway address.

I checked the DHCP setting on the server and noticed that the 003 Router option was no longer set. Apparently that did not come over as part of the upgrade. In case this trips anyone else up, the setting can be found under Server Manager..Roles..DHCP Server..[your server]..IPv4..Server Options. Right click select Configure Options, then check 003 Router and add the IP address of your router.

Tags:

Issues

Copyright © 2001-2012 MS Consulting, Inc. All Rights Reserved.