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

4/25/11

WebClient Class with Cookies

The WebClient class can be used to automate the login to a web application. If the web application requires the client to enable cookies which is often the case when the application uses session state, the application returns an error to the client indicating that cookies must be enabled. The WebClient class can be extended to support cookies by overriding the GetWebRequest method and implementing a CookieContainer.  This allows the client to login to the application and maintain the cookie state for sub-sequent calls to the web application.
To demonstrate this, we should load Visual Studio (2008/2010) and create a new console application.  Add a new class and name it WebClientWithCookies. The class should look as follows:
class WebClientWithCookies: WebClient
{
        private CookieContainer _container = new CookieContainer();

        protected override WebRequest GetWebRequest(Uri address)
        {
            HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;
           
            if (request != null)
            {
request.Method = "Post";               
request.CookieContainer = _container;
            }
                       
            return request;        
        }
 }

The override in the class provides access to the HttpWebRequest reference which facilitates the access to the CookieContainer property. A new CookieContainer object is created and associated it to the request object. This allows the client to store the cookies from the web application in the CookieContainer property of the request. We also set the request method to use Post (this is not needed if the web application allows GET requests).
Now, open the Program class of the console application and update the code to look as follows:
class Program
{
        private static string _cookies=string.Empty;
        static void Main(string[] args)
        {
            string url = "replace with url here";
            Post(url);
            Console.WriteLine("Hit return to exit");
            Console.ReadLine();
        }

        static void client_OpenReadCompleted(object sender, System.Net.OpenReadCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                using (Stream stream = e.Result)
                {                   
                    using (StreamReader reader = new StreamReader(stream))
                    {
                        Console.WriteLine(reader.ReadToEnd());
                    }
                }
               
                WebClientWithCookies client = sender as WebClientWithCookies;
               
  if (client != null)
                {
                    _cookies = client.ResponseHeaders["Set-Cookie"];
                    Console.WriteLine(_cookies);
                }               
            }
            else
            {
                Console.WriteLine(e.Error.Message);
            }
        }
      

        private static void Post(string url)
        {
            using (WebClientWithCookies client = new WebClientWithCookies())
            {
              client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
              var uri = new Uri(url, UriKind.RelativeOrAbsolute);
              client.Headers.Add("Cookie",_cookies);
client.OpenReadAsync(uri);
            }           
        }
}

The post method instantiates a web client (with cookies support) object to post the request to the web application. You should also notice that we add a request header to include any cookies that we may had already been persisted. The call to the web application is made asynchronous, and the handler client_OpenReadCompleted handles the result of the request. If there are no errors, the handler reads the stream and displays the response on the console. The client reference is then used to read the response headers. Here we are using Set-Cookie header name which is used by ASP.Net applications. You may need to inspect the response headers using a tool like fiddler. The inspection can help you identify the key name for the cookie header from the system that you are using. The cookie in the response is saved in a variable. This is necessary because on any other sub-sequent calls to the web application, we need to send the cookie back to the server.  If the cookie is not sent back to the server, the web application will redirect back to the login page.
I hope this helps.

og-bit.com