10/30/11

Invalid Expanded Name LINQ to XML

In the System.Xml.Linq API, the concatenation of the namespace and a local element name creates the expanded name. When an invalid expanded name exception is raised, it can occur when a LINQ to XML query uses an element attribute, and the attribute name that is used is an empty string. For example, with an Xml like this:

<Items>
<item id=”1”>one</item>
<item id=”2”>two</item>
<item>three with no id attribute</item>
</Items>

If you query the document with the following syntax: (get all the items with the attribute id)

var nodes = (from item in Xml.Descendants()
             where item.Attribute(NodeId) != null
             select item).ToList<XElement>();


If the NodeId string variable has no value, the exception of the invalid expanded name will be raised. To address this, we should check that the string is not empty before executing the LINQ query. We can also rewrite the query to something like this:

var nodes = (from item in Xml.Descendants()
             where (!String.IsNullOrEmpty(NodeId) && item.Attribute(NodeId) != null)
             select item).ToList<XElement>();


The IsNUllOrEmpty call prevents the execution of the attribute call when NodeId is empty.

I hope this helps.

10/28/11

How to Clone XDocument

The XDocument class does not implement the ICloneable interface, so there is no Clone method to call. There is however a constructor that allow us to do this. The constructor takes an instance of XDocument and creates a new instance with the same XML structure. This can be done with the following code:

string xmlString = "<items><item/><item/></items>";
..

TextReader tr = new StringReader(xmlString);      
XDocument originalDoc = XDocument.Load(tr);
XDocument cloneDoc = new XDocument(originalDoc);

cloneDoc is a new instance that has the same XML document. Any changes to the cloneDoc does not affect the originalDoc XML document.

I hope this helps.

7/25/11

LINQ to Entity Inner and Left Joins

In SQL, we can joins tables using inner and left joins as follows:
Inner Join: the following query returns only the products that have a valid category id.
Select prod.id, prod.name, cat.name
From product prod
Inner join category cat on prod.catid = cat.catid
Left  Outer Join: the following query returns all the products even if there is no valid category id
Select prod.id, prod.name, cat.name
From product prod
Left outer join category cat on prod.catid = cat.catid
If you are using the Entity framework and you are trying to join entities in your code, you can rewrite the queries using entity SQL as follows:
Inner Join:

This looks basically the same as a normal SQL inner join. The join is between product and category on the catid field. If no category exists, no data would return.
var list = from proc in en.Product
                join cat in en.Category on proc.catid equals cat.catid
                 select new{
                                id = prod.id,
                            name=prod.name,
                                category=cat.name
                 }
Left Outer Join:
The following example does a group join between product and category. This is essentially the left join. The into expression returns data even if the category table is empty. To access the properties of the category table, we must now select from the enumerable result by adding the from cl in catList.DefaultIfEmpty() statement.
var list = from proc in en.Product
                join cat in en.Category on proc.catid equals cat.catid into catList
               from cl in catList.DefaultIfEmpty()
                select new{
                                id = prod.id,
                            name=prod.name,
                                category=cl.name
                 }
I hope it helps.

6/29/11

Microsoft LightSwitch – Clinic Sample SQLExpress Database Errors

If you are working on the Microsoft LightSwitch sample, and you have SQL Express 2005 or you do not have a SQL Express instance at all, you will face a couple of problems running the sample.

The first problem is that the sample was implemented with version of Microsoft SQL Express 2008. If you have the SQL Express 2005 version you will get the following incompatibility error:

The database cannot be opened because it is version 655. This server supports version 612 and earlier. A downgrade path is not supported.

To address this, you will need to upgrade that instance to SQL Express 2008. The latest at the time of this blog is the R2 version. Make sure to keep the SQLExpress instance name, otherwise you will face the next problem.

The LightSwitch sample projects have the SQL express instance name hardcoded in the project file. If you have a different instance name, and you try to update the data source to your instance name, you will soon discover that this does not work. When you compile the project you will continue to get the following error:

An error occurred while establishing a connection to SQL Server instance '.\SQLEXPRESS'

To address this error, you should edit the project file which has the extension lsproj and look for the property SqlExpressInstanceName. You should replace the SQLExpress instance name for the instance name from your environment.

Once you have made those changes, the sample application should run without a problem.

Hope it helps.

og-bit.com

6/21/11

WCF - Could not find a base address that matches scheme

This error indicates that there is no base address handling the request on that particular scheme (http/https) and base address (url).  For example, your WCF web service based address in the web.config may be this:

  • http://mysite.com/myservice.svc    (WCF allows a single based address per scheme http/https)



IIS may be configured to support multiple base addresses like these:

  • http://mysite.com
  • http://www.mysite.com
If you try to load the url http://www.mysite.com/myservice.svc IIS resolves the address, but the WCF setting is in conflict, and an error is shown. Using the web.config, we can add a setting to filter the IIS base address that does not mapped to the WCF based address (add the setting in the system.serviceModel node).

<serviceHostingEnvironment>
       <baseAddressPrefixFilters>
       <add prefix="http://www.mysite.com" />
      </baseAddressPrefixFilters>
</serviceHostingEnvironment>

This should eliminate the conflict, and the request should go to base address defined by the web.config. In addition, a common mistake is that the baseAddressPrefixFilters may be set to the same base address of the WCF service. This filters out the base address and causes the “Could not find base address error”. Following our previous scenario, if you add the setting below, the error will be recreated.

<serviceHostingEnvironment>
 <baseAddressPrefixFilters>
   <add prefix="http://mysite.com" /> (filters The wcf base address – error is shown)
   <add prefix="http://www.mysite.com"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>

I hope this helps.

6/14/11

TFS – How to Record Support Hours on an Iteration

In project management, there is always a need to record how much work is being done to troubleshoot and/or identify issues for a particular release.  To address this, we could set up a team project with the following settings:

Area and Iteration Path:
Create an area path specifically for support issues. For example, the area path could read the following:
Area Path
   Description
Support\Stage
Use this for the staging environment
Support\Production
Use this for the production environment

This allows us to track supporting tasks done in either the staging or production environment.
The iteration path should be set to your software iteration. For example, if in stage you are running version 2.13.0, and you need to create a support task to troubleshoot something in stage. You set the area path to stage and the iteration to version 2.13.0. The same can be applied when a task needs to be created on a production release. This allows us to track the number of tasks in each environment and for each release/iteration

Task Detail:
When you create a task, the task should be created with this additional information:
Property
   Value
   Description
Discipline
Analysis
This depends on the template you are using on TFS. You may create another entry that reads Support.
Type
Corrective or Mitigation
On stage you may use Corrective to correct problems before production. On production , you can use Mitigation because you need to minimize the impact of the problem
(Details tab)  Schedule Estimate
hours
The estimated hours
(Details tab)  Schedule Remaining work
hours
The work still remaining. This is important to update because a tasks may not be completed the same day, but you need to report the number of hours left.
(Details tab)  Completed  work
hours
The hours completed in the tasks

 It is important to add the completed work and remaining work to the correct Area and iteration path. This would be the only way that the reports can accurately show how much support effort is being done and in what iteration. This can lead to a better understanding of the development process and identify possible issues.
I hope this is useful.

og-bit.com

6/9/11

WCF Security token in the message could not be validated when using Custom authentication

The security token error is usually generated from a SecurityTokenValidation exception during the Username and password validation process.   This error is usually displayed as follows:

[MessageSecurityException: An unsecured or incorrectly secured fault was received from the other party. This fault may have been sent in response to an improperly secured request. See the inner FaultException for the fault code and detail.]

og-bit.com
The inner exception displays this error:

At least one security token in the message could not be validated.

This error does not tell us much about the problem, but we know there is a security problem. A way to troubleshoot this is to first enable logging on the web service. We enable the logging of the messages at the transport level by adding the following diagnostics settings in your web.config file inside the system.serviceModel node.
<system.serviceModel>
<diagnostics>
<messageLogging maxMessagesToLog="25000" logEntireMessage="true" logMessagesAtServiceLevel="false"  logMalformedMessages="true" logMessagesAtTransportLevel="true">
<filters><clear/></filters>
</messageLogging>
</diagnostics>
We now need to create a file that we can open with Microsoft Trace viewer by adding this setting under the system.diagnostic node: (notice the name and location of the log file)
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Warning, ActivityTracing" propagateActivity="true" >
<listeners> <add name="xml" /></listeners>
</source>
<source name="System.ServiceModel.MessageLogging" switchValue="Warning">
   <listeners><add name="xml" /></listeners>
</source>
</sources>
<sharedListeners>
   <add name="xml" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\Temp\myService.svclog" />
</sharedListeners>
You can now deploy the web.config changes in your test environment and send a couple of request. If you do this on production, make sure to remove the settings after recreating the problem. Once you have recreated the problem, look for the log file (see initializeData attribute) and open it with trace viewer. We are looking for items highlighted in red under the Activity tab (left pane). Select one of those messages and on the right-top pane look for a message that reads "Throwing an exception". Select that message and inspect the details under the XML tab(see image below). There, we can find a detail stack dump of what is really causing the problem. You can look carefully for the class name in your project, and you would probably be able to identify exactly what may have gone wrong.
I hope this helps.



og-bit.com

6/7/11

WCF Service IIS specified authentication schemes error

If after deploying your WCF service, you are getting this error:
InvalidOperationException: IIS specified authentication schemes 'IntegratedWindowsAuthentication, Anonymous', but the binding only supports specification of exactly one authentication scheme.


You are probably using an activation host factory that does not agree with the IIS settings. The error means that the IIS application configuration has been set to support multiple authentication schemes, but when the service is trying to get activated it does not know which authentication scheme to use (ambiguous). There is a good chance that your development environment is configured differently which may explain why the error was not generated during your unit test.

To solve this problem, we first need to identify the IIS settings on the server where the application is getting the error. Open IIS manager, select the web application node and select the authentication icon (IIS7, use directory security tab for IIS6). Most of the time, production environments will be configured to support the following schemes:

Anonymous and Windows authentication.








We should now match those settings in the development environment and try to recreate the error.  Once the error is recreated in the development environment, we need to identify why our service does not support the multiple authentication schemes. Open the SVC file and look for the Factory property.  This factory property makes it easy to auto configure our services when there are no configuration settings in the web.config.  This error is commonly created when the host factory is set to use WebScriptServiceHostFactory which adds an ASP.Net AJAX end point to the service. This dynamic endpoint is the one being used for the web service, and it is causing your application to generate the error.

<%@ ServiceHost Language="C#" Debug="true" Service="Web.MyService" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory"%>

To address this problem, change the factory to use the ServiceHostFactory which supports multiple authentication schemes or just remove the factory attribute all together. By removing the factory attribute, the service uses the information from the web.config.

<%@ ServiceHost Language="C#" Debug="true" Service="Web.MyService" Factory="System.ServiceModel.Activation.ServiceHostFactory"%>

I hope this helps.

og-bit.com

6/2/11

LINQ to SQL Using Where in

In SQL, you can compare against multiple values by using the IN operator. A normal select statement with the IN operator looks as follows:

select * from AuditLog
where log_id in (1111,2222,3333)
What if we need to use LINQ to SQL to accomplish the same? The approach is to use an array and use the Contains method to compare against the columns values. This is what the SQL statement listed above looks in LINQ:
int[] ids = { 1111, 2222, 3333 };

from log in dbcontext.AuditLog
where ids.Contains(log.log_id)
select log
We first declare an integer array with the values we are looking for. We then use the Contains method to compare the values. If you add a SQL trace, you will be able to see how this LINQ statement is translated into a SQL statement that uses the IN operator.
*Note:  dbcontext is the data context class that is created when a dbml file is added to the project. This is what generates the LINQ classes that are used for the database access.
I hope this is useful.

og-bit.com

5/30/11

LINQ to SQL with NOLOCK

If your project uses LINQ to SQL for your database access, you may want to use NOLOCK to set the isolation level to ReadUncommitted on your select statements. This prevents the database engine from issuing locks on the tables that we are trying to select data from which helps increase concurrency and performance.


The area of concern is that LINQ does not understand query hints. The way this works with LINQ is by running your select statements under the context of a transaction scope as follows:



string type = string.Empty;
og-bit.com

using (DataContext ctx = new DataContext(ConnectionString))
{
  using (var tx = new System.Transactions.TransactionScope(TransactionScopeOption.Required,
         new TransactionOptions() { IsolationLevel = IsolationLevel.ReadUncommitted }))
  {
         var row = (from record in ctx.Log
                    where record.Id == 99999
                    select record).FirstOrDefault();
         type = row.Type;
  }
}

The code here creates a transaction scope and sets the isolation level to ReadUncommitted (NOLOCK). The select statement runs under the scope of the transaction, and it returns the value from a query. The using clause ensures that both the transactions as well as the data context are disposed once the code goes out of scope.


There is also the preferable option to use stored procedures to eliminate the need to use transaction scope. In the store procedure, you have the flexibility to use query hints.


I hope this helps.

og-bit.com

5/25/11

The HTTP request is unauthorized with client authentication scheme 'Basic'

There are several examples on the internet that focus on implementing a custom username password validator for a WCF service. Most of those samples are written using self-hosted applications and work as designed. There is a problem however when the same approach needs to be implemented using an IIS hosted site with Basic authentication enabled. If you have implemented a custom user name password validator for non-windows credentials and with the following settings:

<basicHttpBinding>
  <binding name="basicHttp" closeTimeout="00:01:00" openTimeout="00:01:00"/>
       <security mode="TransportCredentialOnly">
          <transport clientCredentialType="Basic" proxyCredentialType="None" realm="" />
        </security>
  </binding>
</basicHttpBinding>

You probably came across this error:
The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Negotiate,NTLM,Basic realm="localhost"'
This error indicates that the user credentials provided on the request are not valid for this realm (localhost). IIS is expecting to get a user that it can find on the local machine or domain. If you provide an existent local or active directory credential, the error will no longer be raised. However, you probably did not want to add Windows accounts for your custom authentication in the first place. In addition, even if you are using a local account, you can notice that the custom validator Validate method is never called. This is expected because IIS has already done the validation.
To get this to work on IIS, you can try the following settings:
<basicHttpBinding>
  <binding name="basicHttp" closeTimeout="00:01:00" openTimeout="00:01:00"/>
       <security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" algorithmSuite="Default" />
        </security>
  </binding>
</basicHttpBinding>

We are changing the security mode to use transport with message credential which expects a message credential type. We set the credential type to UserName. This setting however requires for you to install a certificate on your local IIS and use HTTPS instead of HTTP, so make sure to change the endpoint address in both client and server config files to use HTTPS.  For your development environment a Self-Signed certificate will be sufficient.
I hope this small article is able to help.

og-bit.com

5/19/11

WCF Service operations can’t be loaded due to mixing of message contract types and primitive types

When debugging your WCF Service, you may encounter the following error:
The operation could not be loaded because it has a parameter or return type of type System.ServiceModel.Channels.Message or a type that has MessageContractAttribute and other parameters of different types. When using System.ServiceModel.Channels.Message or types with MessageContractAttribute, the method must not use any other types of parameters
This basically means that a particular operation is using a combination of message contract types and primitive types in any of the following combinations:
  • MixType1: Contract type and primitive types as operation parameters
  • MixType2: Contract type as a parameter and primitive type as return type
  • MixType3: Primitive type as a parameter and Contract type as return type
Any of the scenarios listed above would generate the error. Let’s take a look at a ServiceContract that can generate this problem.
[ServiceContract]
public interface IRegisterMixed
{
        [OperationContract]
        Confirmation Register(string firstName, string lastName);

        [OperationContract]
        string RegisterComplex(Person person);
}

These are the message contract types:

[MessageContract]
public class Person
{
        public string FirstName { set; get; }
        public string LastName { set; get; }       
}

[MessageContract]
public class Confirmation
{
        public string AccountId { set; get; }       
}

The service contract generates the error because both operations are mixing contract types with primitive types. The Register operation has the operation parameters as primitive types and the return type as a contract type (MixType3). The RegisterComplex operation has a contract type as parameter and a primitive type as return type (MixType2).

A way to address this would be to modify the service contract as follows:

[ServiceContract]
public interface IRegisterOK
    {
        [OperationContract]
        string Register(string firstname, string lastname);
      
        [OperationContract]
        Confirmation RegisterComplex(Person person);
}

As you can see, both operations are consistently using either primitive types or contract types for both operation and return parameters.

I hope this tip would be useful when designing your next WCF Service operations.

og-bit.com

5/14/11

WCF Service Project Properties is missing the WCF Options Tab

If your WCF Library project does not auto start the WCF Service host when trying to start the project in debug mode, the project file has some missing elements. A way to check this is to right click on the project name (Visual Studio) and look for the WCF Options tabs on the left side of the window.  If you do not see the tab, this means that the library project for some reason was not created as a WCF library.   
A quick way to resolve this is to create a new WCF Service Library project and copy all the files over. If you do not want to do this, you can manually modify the project file and add the missing elements as follows:
·         Right click the project name and select Open Folder in Windows explorer
·         Look for your project file which should end with a .csproj extension and open the file with your favorite editor or just notepad.
·         In the first PropertyGroup element do the following:
o   Look for the ProductVersion element. Update the product version to match the following: 
<ProductVersion>8.0.50727</ProductVersion>

o   Below the AssemblyName element, add the following elements:
<ProjectTypeGuids>{3D9AD99F-2412-4246-B90B-4EAA41C64699};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<StartArguments>/client:"WcfTestClient.exe"</StartArguments>

o   Scroll to the end of the file, and below the Import  element add the following extension:
<ProjectExtensions>
    <VisualStudio>
      <FlavorProperties GUID="{3D9AD99F-2412-4246-B90B-4EAA41C64699}">
        <WcfProjectProperties>
          <AutoStart>True</AutoStart>
        </WcfProjectProperties>
      </FlavorProperties>
    </VisualStudio>
  </ProjectExtensions>

o   Save the file and select yes when Visual Studio prompts to reload the project.
The changes update the project type from a basic library project to a WCF Service library. You can now do project properties and should see the WCF Options tab. The Start WCF service host option should be checked. You can now run the project in debug mode, and the WCF Service Host should start.
I hope this save you some time and thanks for reading.

og-bit.com