Row Tests or Paramerterized Tests (MsTest) – Xml

In a previous post, I discussed Parameter Value Coverage (PVC). One of the easiest ways to add PVC to your test suite is to use Row Tests, sometimes called Parameterized Tests. Row test is the idea of writing a single unit test, but passing many different values in.

Different testing frameworks implement row tests differently.

MsTest uses an attribute called DataResourceAttribute. This supports anything from a csv, Excel file or xml, to a full-blown database.

For a single Unit Test, NUnit’s Row tests are far superior. However, for a larger test project, you will see that DataSourceAttribute with external data sources, scales nicely and compares to NUnits TestCaseSource. However, it is not as easy to get it right the first time. It needs a step by step tutorial.

Step 1 – Create a the Project

  1. In Visual Studio click File | New | Project.
  2. Select Unit Test Project for C#.
  3. Give it a name and a path and click OK.

Step 2 – Add an Xml file

  1. Create a folder in your visual studio project called Data.
  2. Right-click on the data folder and choose Add | New Item.
  3. Create new Xml file named: Data.xml
  4. Add the following to the Xml.
<?xml version="1.0" encoding="utf-8" ?>
<Rows xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:x="urn:Row">
  <!-- Schema -->
  <xsd:schema targetNamespace="urn:Row" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
    <xsd:element name="Row">
      <xsd:complexType>
        <xsd:sequence>
          <xsd:element type="xsd:int" name="Value1"/>
          <xsd:element type="xsd:int" name="Value2"/>
          <xsd:element type="xsd:int" name="ExpectedValue"/>
          <xsd:element type="xsd:string" name="Message"/>
        </xsd:sequence>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <!--End Schema-->
  <x:Row>
    <x:Value1>3</x:Value1>
    <x:Value2>2</x:Value2>
    <x:ExpectedValue>2</x:ExpectedValue>
    <x:Message>2 is less than 3</x:Message>
  </x:Row>
  <x:Row>
    <x:Value1>-1</x:Value1>
    <x:Value2>0</x:Value2>
    <x:ExpectedValue>-1</x:ExpectedValue>
    <x:Message>-1 less than 0</x:Message>
  </x:Row>
  <x:Row>
    <x:Value1>10</x:Value1>
    <x:Value2>5</x:Value2>
    <x:ExpectedValue>5</x:ExpectedValue>
    <x:Message>5 is less than 10</x:Message>
  </x:Row>
</Rows>

Note: This Xml is designed as such so the Schema is inline. That allows us to specify the data type.

Step 3 – Set Xml File Properties

The XML file needs to be copied on build.

  1. Right-click on the Xml file and choose Properties.
  2. Change the Copy to output directory to: Copy if newer

Step 4 – Add a Unit Test method

Note: We won’t have a real project to test. We will just test Math.Min() for an example.

  1. Add a reference to System.Data.
  2. Add the TestContext property. (See line 9 below)
  3. Add a DataSource attribute to the test method. (See line 12 below)
    Notice that is uses Row not Rows (it doesn’t use the root element but the second element).
  4. Use TestContext.DataRow[0] to get the first column. (See line 16 below)
    Note: You can also access the column by the column name we used: TestContext.DataRow[Value1]

  5. Assign variables for the rest of the columns. (See lines 16-19 below)
  6. Add the test and the assert. (See lines 22 and 25)
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MsTestRowTestXml
{
    [TestClass]
    public class UnitTest1
    {
        public TestContext TestContext { get; set; }

        [TestMethod]
        [DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", @"Data\Data.xml", "Row", DataAccessMethod.Sequential)]
        public void TestMethod1()
        {
            // Arrange
            int a = (int)TestContext.DataRow[0];
            int b = (int)TestContext.DataRow[1];
            int expected = (int)TestContext.DataRow[2];
            string message = TestContext.DataRow[3].ToString();

            // Act
            var actual = Math.Min(a, b);

            // Assert
            Assert.AreEqual(expected, actual, message);
        }
    }
}

You finished! Good job!.

Use Common Xml files for Parameter Value Coverage

While this method involved way more steps than anything with NUnit to set up, tt can actually be a bit quicker for subsequent tests and quite useful when testing larger projects. Once you have the Xml files setup, you can reuse them for many methods. For example, for every method that takes a long, you could use the same DataSource to get Parameter Value Coverage (PVC).

<?xml version="1.0" encoding="utf-8" ?>
<Rows xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:x="urn:Row">
  <!-- Schema -->
  <xsd:schema targetNamespace="urn:Row" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
    <xsd:element name="Row">
      <xsd:complexType>
        <xsd:sequence>
          <xsd:element type="xsd:long" name="Value"/>
          <xsd:element type="xsd:string" name="Message"/>
        </xsd:sequence>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <!--End Schema-->
  <x:Row>
    <x:Value>2147483648</x:Value>
    <x:Message>One more than int.MaxValue</x:Message>
  </x:Row>
  <x:Row>
    <x:Value>-2147483649</x:Value>
    <x:Message>One less than int.MinValue</x:Message>
  </x:Row>
  <x:Row>
    <x:Value>9223372036854775807</x:Value>
    <x:Message>long.MaxValue</x:Message>
  </x:Row>
  <x:Row>
    <x:Value>-9223372036854775808</x:Value>
    <x:Message>long.MinValue</x:Message>
  </x:Row>
  <x:Row>
    <x:Value>0</x:Value>
    <x:Message>0 (zero)</x:Message>
  </x:Row>
  <x:Row>
    <x:Value>1</x:Value>
    <x:Message>1 (one)</x:Message>
  </x:Row>
  <x:Row>
    <x:Value>2</x:Value>
    <x:Message>2 (one)</x:Message>
  </x:Row>
  <x:Row>
    <x:Value>-1</x:Value>
    <x:Message>-1 (minus one)</x:Message>
  </x:Row>
  <x:Row>
    <x:Value>-2</x:Value>
    <x:Message>-2, -2 (minus one)</x:Message>
  </x:Row>
</Rows>

Row Tests or Paramerterized Tests (MsTest) – CSV

In a previous post, I discussed Parameter Value Coverage (PVC). One of the easiest ways to add PVC to your test suite is to use Row Tests, sometimes called Parameterized Tests. Row test is the idea of writing a single unit test, but passing many different values in.

Different testing frameworks implement row tests differently.

MsTest uses an attribute called DataResourceAttribute. This supports anything from a csv, Excel file or xml, to a full-blown database.

For a single Unit Test, NUnit’s Row tests are far superior. However, for a larger test project, you will see that DataSourceAttribute with external data sources, scales nicely and compares to NUnits TestCaseSource. However, it is not as easy to get it right the first time. It needs a step by step tutorial.

Step 1 – Create a the Project

  1. In Visual Studio click File | New | Project.
  2. Select Unit Test Project for C#.
  3. Give it a name and a path and click OK.

Step 2 – Add a csv file

  1. Create a folder in your visual studio project called Data.
  2. Right-click on the data folder and choose Add | New Item.
  3. Create new text file named: Data.csv
  4. Add the following to the csv.
Value1, Value2, ExpectedMinValue, Message
1,10, 1, 1 is less th an 10.
192, 134, 134, 134 is less than 192.
101, 99, 99, 99 is less than 101.
77, 108, 77, 77 is less than 108.
45, 37, 37, 37 is less than 34.
12, 18, 12, 12 is less than 18.

Step 3 – Save the CSV file with the correct encoding

Note: The CSV file needs to be saved with an encoding that doesn’t add junk characters.

  1. Click File | Advanced Save Options.
  2. Choose this Encoding option: Unicode (UTF-8 without signature) – Codepage 65001
  3. Click OK and then click save.

Note: VS 2017 doesn’t have an Advance Save Options menu item.

  1. Click File | Save Data.csv as.
  2. Click the drop down on the Save button and choose Save with Encoding.
  3. Choose this Encoding option: Unicode (UTF-8 without signature) – Codepage 65001
  4. Click OK and then click save.

Step 4 – Set CSV File Properties

The CSV file needs to be copied on build.

  1. Right-click on the CSV file and choose Properties.
  2. Change the Copy to output directory to: Copy if newer

Step 5 – Add a Unit Test method

Note: We won’t have a real project to test. We will just test Math.Min() for an example.

  1. Add a reference to System.Data.
  2. Add the TestContext property. (See line 9 below)
  3. Add a DataSource attribute to the test method. (See line 12 below)
  4. Use TestContext.DataRow[0] to get the first column. (See line 16 below)
    Note: You can also access the column by the column name we used: TestContext.DataRow[Value1]

  5. Assign variables for the rest of the columns. (See lines 16-19 below)
  6. Add the test and the assert. (See lines 22 and 25)
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MsTestRowTestExample
{
    [TestClass]
    public class UnitTest1
    {
        public TestContext TestContext { get; set; }

        [TestMethod]
        [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", @"Data\Data.csv", "Data#csv", DataAccessMethod.Sequential)]
        public void TestMethod1()
        {
            // Arrange
            int a = Convert.ToInt32(TestContext.DataRow[0]);
            int b = Convert.ToInt32(TestContext.DataRow[1]);
            int expected = Convert.ToInt32(TestContext.DataRow[2]);
            string message = TestContext.DataRow[3].ToString();

            // Act
            var actual = Math.Min(a, b);

            // Assert
            Assert.AreEqual(expected, actual, message);
        }
    }
}

You finished! Good job!.

Use Common Csv files for Parameter Value Coverage

While this method involved way more steps than anything with NUnit to set up, tt can actually be a bit quicker for subsequent tests and quite useful when testing larger projects. Once you have the csv files setup, you can reuse them for many methods. For example, for every method that takes a string, you could use the same DataSource to get Parameter Value Coverage (PVC).

null, A null string
"", An empty string, String.Empty, or ""
" ", One or more spaces " "
"	", One or more tabs "	"
"
", A new line or Environment.NewLine
"Hello, world!", A valid string.
"&*^I#UYLdk1-KNnS1.,Dv0Hhfwelfnzsdase", An invalid or junk string
গঘ, Double-byte Unicode characters

Row Tests or Paramerterized Tests (NUnit)

In a previous post, I discussed Parameter Value Coverage (PVC). One of the easiest ways to add PVC to your test suite is to use Row Tests, sometimes called Parameterized Tests. Row test is the idea of writing a single unit test, but passing many different values in.

Different testing frameworks implement row tests differently.

NUnit has two options. The first implements them inline, with an attribute for each. Here is an example straight from NUnit’s website:

[TestCase(12,3,4)]
[TestCase(12,2,6)]
[TestCase(12,4,3)]
public void DivideTest(int n, int d, int q)
{
    Assert.AreEqual( q, n / d );
}

NUnit also implements a TestCaseSource attribute.

[Test, TestCaseSource("DivideCases")]
public void DivideTest(int n, int d, int q)
{
    Assert.AreEqual( q, n / d );
}

static object[] DivideCases =
{
    new object[] { 12, 3, 4 },
    new object[] { 12, 2, 6 },
    new object[] { 12, 4, 3 }
};

For a single Unit Test, NUnit’s Row tests are far superior. However, for a larger test project, you will see that TestCaseSource with with data sources, scales nicely. Imagine you have 10 test method that each take in the same 10 lines of data. With the TestCase attribute, you would have to write 10 attributes on all 10 test methods–that is 100 lines of attributes alone. Worse these are 10 exact code copies. That breaks the Don’t Repeat Yourself (DRY) principle of coding. With TestCaseSource, you implement the data for the Row tests in a single place and you add one attribute per test method.

Hint: Also, you might find many row test sources can be reused for other tests. Maybe storing them in a single data source repository would be a good idea, so they can be reused. Don’t do it for small tests. Only do it for large test projects that need to scale.


Combining multiple WSDLs for consumption in a C# client project

So I added a WebReference for nine different web services. These were all web services for the same product. I will call them from the same client code. So it makes sense to consume them all. Each service got it’s own namespace. Immediately there were problems. Multiple web services exposed the same object. Each instance of the object was in a different namespace. This created a bunch of ambiguous reference errors. Fixing those errors made a mess of the code as I then had to include the namespaces when calling the objects or else have object using statements to determine which object to use in which namespace.

The I got smart and researched combining WSDLs. I found this MSDN site: Web Services Description Language Tool (Wsdl.exe)

Turns out that Visual Studio comes with a WSDL.exe. It allows for easily combining multiple WSDLs into one large auto-generated code file. It also has a nice parameter called sharetypes. I bet you can guess what sharetypes does.

Step 1 – Create a wsdl parameters file

Here is an exmaple of mine.

  1. I left the settings from the MSN example for nologo, parsableerrors, and sharetypes.
    Note: Setting sharetypes to true is the feature I most needed.
  2. Set it to get the URL from the web.config or app.config.
  3. Set the namespace.
  4. Add a document for each wsdl file.
  5. Set out file.
    <wsdlParameters xmlns="http://microsoft.com/webReference/">
      <appSettingUrlKey>FnoSharpWebServiceUrl</appSettingUrlKey>
      <appSettingBaseUrl>FnoSharpWebServiceBaseUrl</appSettingBaseUrl>
      <namespace>FnoSharp</namespace>
      <nologo>true</nologo>
      <parsableerrors>true</parsableerrors>
      <sharetypes>true</sharetypes>
      <documents>
        <document>http://MyServer:8888/flexnet/services/ActivationService?wsdl</document>
        <document>http://MyServer:8888/flexnet/services/AdminService?wsdl</document>
        <document>http://MyServer:8888/flexnet/services/EntitlementOrderService?wsdl</document>
        <document>http://MyServer:8888/flexnet/services/FlexnetAuthentication?wsdl</document>
        <document>http://MyServer:8888/flexnet/services/LicenseService?wsdl</document>
        <document>http://MyServer:8888/flexnet/services/ManageDeviceService?wsdl</document>
        <document>http://MyServer:8888/flexnet/services/ProductPackagingService?wsdl</document>
        <document>http://MyServer:8888/flexnet/services/UserOrgHierarchyService?wsdl</document>
        <document>http://MyServer:8888/flexnet/services/Version?wsdl</document>
      </documents>
      <out>FnoSharpReference.cs</out>
    </wsdlParameters>
    

Step 2 – Run wsdl.exe

  1. Open a Developer Command Prompt.
  2. Run this command:
    wsdl.exe /Parameters:FnoSharpWsdls.xml
    

Now you have a single Reference.cs file that includes code for all your WSDLs.

Step 3 – Update your Visual Studio Project

  1. Delete all your web references.
  2. Add the Reference.cs to your project
  3. Fix your namespaces.

Step 4 – Update URL to use an appSetting

Having a hard coded URL in the code is not a good idea. The Reference.cs file you created will have static URLs. Unfortunately the wsdl.exe doesn’t seem to support doing this for multiple urls. So you should manually replace them.

  1. Add a variable to your appSettings in your web.config or app.config.
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="FnoSharpHost" value="http://MyServer:8888"/>
      </appSettings>
    
      <!-- Other config stuff -->
    
    <configuration>
    
  2. Find and replace all the lines that call your hard coded URL. They look like this. I had 9 WSDLs so I had 9 of these to replace.
        public ActivationService() {
            this.Url = "http://MyServer:8888/flexnet/services/ActivationService";
        }
    

    Here is your find and replace string:

       Find:  this.Url = "http://MyServer:8888
    Replace:  this.Url = ConfigurationManager.AppSettings["FnoSharpHost"] + "
    

    Your methods should now look like this:

        public ActivationService() {
            this.Url = ConfigurationManager.AppSettings["FnoSharpHost"] + "/flexnet/services/ActivationService";
        }
    

Your done. You now have all your WSDLs combined into one Reference.cs file.


AutoMapper versus Extension Methods versus Implicit Casts

Download Project
Imagine the database code is legacy, can’t be changed, and the Database Person object from the database namespace looks like this:

using System;
using System.ComponentModel.DataAnnotations;

namespace WcfToEntityAutomapperExample.DAL.Model
{
    /// <summary>
    /// Example of an Person object where properties are not defined in a way you want 
    /// to expose via WCF.
    /// </summary>
    class PersonRow
    {
        public int Id { get; set; }

        [Required]
        [StringLength(50)]
        public string FName { get; set; }

        [Required]
        [StringLength(50)]
        public string MName { get; set; }

        [Required]
        [StringLength(50)]
        public string LName { get; set; }

        [Required]
        public DateTime BD { get; set; }

        public DateTime? DD { get; set; }
    }
}

You can’t use this in your WCF service, and not just beccause PersonRow, FName and LName just look tacky, though that is reason alone. No, the real problem is ambiguity and confusion. MName isn’t exactly clear. Is it Maiden name, Mother’s last name, or middle name? And what is BD and DD? Such confusion and ambiguity isn’t acceptable in an exposed API.

So you create a Person DataContract to expose with WCF that looks like this:

using System;
using System.Runtime.Serialization;

namespace WcfToEntityAutomapperExample.Services.Model
{
    [DataContract]
    public class Person
    {
        [DataMember]
        public string FirstName { get; set; }
        [DataMember]
        public string MiddleName { get; set; }
        [DataMember]
        public string LastName { get; set; }
        [DataMember]
        public DateTime DateOfBirth { get; set; }
        [DataMember]
        public DateTime? DateOfDeath { get; set; }
    }
}

Wow. That will look much better in your exposed WCF API.

So now there is a problem. We need to convert Person to PersonRow.

Solving with extension methods

It would be easy to write extension methods to do this:

  1. Add an extension method
    using WcfToEntityAutomapperExample.DAL.Model;
    using WcfToEntityAutomapperExample.Services.Model;
    
    namespace WcfToEntityAutomapperExample.Extensions
    {
        static class PersonExtensions
        {
            public static PersonRow ToPersonRow(this Person person)
            {
                return new PersonRow
                {
                    FName = person.FirstName,
                    MName = person.MiddleName,
                    LName = person.LastName,
                    BD = person.DateOfBirth,
                    DD = person.DateOfDeath
                };
            }
        }
    }
    
  2. Add a reverse mapping extension method.

    OK. Now we have this extension method and we can use it anywhere we want. However, we forgot. We need to do this in reverse too. We need an extension method for PersonRow to Person. So add this method to PersonExtensions class.

    using WcfToEntityAutomapperExample.DAL.Model;
    using WcfToEntityAutomapperExample.Services.Model;
    
    namespace WcfToEntityAutomapperExample.Extensions
    {
        static class PersonExtensions
        {
            public static PersonRow ToPersonRow(this Person person)
            {
                return new PersonRow
                {
                    FName = person.FirstName,
                    MName = person.MiddleName,
                    LName = person.LastName,
                    BD = person.DateOfBirth,
                    DD = person.DateOfDeath
                };
            }
    
            public static Person ToPerson(this PersonRow personRow)
            {
                return new Person
                {
                    FirstName = personRow.FName,
                    MiddleName = personRow.MName,
                    LastName = personRow.LName,
                    DateOfBirth = personRow.BD,
                    DateOfDeath = personRow.DD
                };
            }
        }
    }
    
  3. Now, you have 40 other objects to do this too.
    Hint: Take a moment to compare this to the AutoMapper method below and ask yourself which is better.

  4. Use the extension method in the web service call.
    using System.Collections.Generic;
    using System.Linq;
    using WcfToEntityAutomapperExample.DAL;
    using WcfToEntityAutomapperExample.DAL.Model;
    using WcfToEntityAutomapperExample.Extensions;
    using WcfToEntityAutomapperExample.Services.Interfaces;
    using WcfToEntityAutomapperExample.Services.Model;
    
    namespace WcfToEntityAutomapperExample.Services
    {
         public class Service1 : IService1
        {
            public void AddPersonExtensionMethod(Person person)
            {
                using (var dbContext = new PersonDbContext())
                {
                    dbContext.People.Add(person.ToPersonRow());
                    dbContext.SaveChanges();
                }
            }
    
            public List<Person> FindExtensionMethod(string lastName)
            {
                using (var dbContext = new PersonDbContext())
                {
                    var foundPeopleFromDb = dbContext.People.Where(p => p.LName == lastName).ToList();
                    return foundPeopleFromDb.Select(p => p.ToPerson()).ToList();
                }
            }
        }
    }
    

Extension Method Conclusion

Simple. Easy to use. Easy to read. Makes sense. The extension method name is an important part of this clarity. I used ToPerson and ToPersonRow. But it would also work with AsPerson and AsPersonRow.

Anybody can read this code and understand it.

If another field is added it is easy to add to the extension method on a single place so code isn’t strewn about.

Using AutoMapper

Why is AutoMapper better than the above extension method? Let’s do the same thing with AutoMapper. You be the judge of whether it is a better solution.

Well, so far, I can’t find any benefit from AutoMapper.

Here is what I need to do:

  1. Add AutoMapper library from NuGet. That adds a dll and another dependency to maintain.
  2. Create a static class to configure AutoMapper mappings: AutoMapperConfig.cs.
  3. Add mappings both ways: From Person to PersonRow and from PersonRow to Person.
    using AutoMapper;
    using WcfToEntityAutomapperExample.DAL.Model;
    using WcfToEntityAutomapperExample.Services.Model;
    
    namespace WcfToEntityAutomapperExample.Map
    {
        public static class AutoMapperConfig
        {
            internal static void RegisterMappings()
            {
                Mapper.CreateMap<Person, PersonRow>()
                    .ForMember(dest => dest.FName, opt => opt.MapFrom(src => src.FirstName))
                    .ForMember(dest => dest.MName, opt => opt.MapFrom(src => src.MiddleName))
                    .ForMember(dest => dest.LName, opt => opt.MapFrom(src => src.LastName))
                    .ForMember(dest => dest.BD, opt => opt.MapFrom(src => src.DateOfBirth))
                    .ForMember(dest => dest.DD, opt => opt.MapFrom(src => src.DateOfDeath)).ReverseMap();
            }
        }
    }
    
    

    Now, you have 40 other objects to do this too.
    Hint: Take a moment to compare this to the extension method above and ask yourself which is better.

  4. Find a global location to call AutoMapperConfig.cs: Global.asax/Global.asax.cs.
    Note: If you don’t have a Global.asax/Global.asax.cs, then you need to add this.

    using System;
    using System.Web;
    using WcfToEntityAutomapperExample.Map;
    
    namespace WcfToEntityAutomapperExample
    {
        public class Global : HttpApplication
        {
            protected void Application_Start(object sender, EventArgs e)
            {
                AutoMapperConfig.RegisterMappings();
            }
    
            protected void Session_Start(object sender, EventArgs e)
            {
    
            }
    
            protected void Application_BeginRequest(object sender, EventArgs e)
            {
    
            }
    
            protected void Application_AuthenticateRequest(object sender, EventArgs e)
            {
    
            }
    
            protected void Application_Error(object sender, EventArgs e)
            {
    
            }
    
            protected void Session_End(object sender, EventArgs e)
            {
    
            }
    
            protected void Application_End(object sender, EventArgs e)
            {
    
            }
        }
    }
    
  5. Call it in your service.
    using System.Collections.Generic;
    using System.Linq;
    using AutoMapper;
    using WcfToEntityAutomapperExample.DAL;
    using WcfToEntityAutomapperExample.DAL.Model;
    using WcfToEntityAutomapperExample.Extensions;
    using WcfToEntityAutomapperExample.Services.Interfaces;
    using WcfToEntityAutomapperExample.Services.Model;
    
    namespace WcfToEntityAutomapperExample.Services
    {
         public class Service1 : IService1
        {
            public void AddPersonAutoMapper(Person person)
            {
                using (var dbContext = new PersonDbContext())
                {
                    dbContext.People.Add(Mapper.Map<PersonRow>(person));
                    dbContext.SaveChanges();
                }
            }
    
            public List<Person> FindAutoMapper(string lastName)
            {
                using (var dbContext = new PersonDbContext())
                {
                    var foundPeopleFromDb = dbContext.People.Where(p => p.LName == lastName).ToList();
                    return foundPeopleFromDb.Select(Mapper.Map<Person>).ToList();
                }
            }
        }
    }
    

AutoMapper conclusion
Something just isn’t right here. You have to call more complex code to get an object converted. The ReverseBack() method saves us from having to create the reverse copy manually. Still, there are two methods and three lambda’s per property to copy. Hardly saving code or making life easier.

The configuration code looks way more complex than the extension method code. I had a bug in my mapper config, and I couldn’t see it because the code is so busy.

The AutoMapper code also isn’t intuitive. The methods aren’t obvious and it is not clear what it is doing without reading the documentation. Mapper.Map(p) doesn’t not clearly tell me that I am converting from an object of type Person to an object of type PersonRow. To me a Map is a HashTable or a Dictionary. I assume at first glance, that I am calling some type of Dictionary. The syntax breaks the “code should be clear” and the “code should be self documenting” rules. Any developer not familiar with AutoMapper will have no idea what your code is doing.

Note: AutoMapper supposedly adds a feature that allows for a copy if the properties are the same with just one line of code: Mapper.CreateMap();

I can see how if you had a lot of objects with identical properties that AutoMapper would be tempting. Still, the naming and lack of readability gets to me. Mapping.Map(p) just isn’t clear. If all the properties of all the objects match, scripting a clear, self-documenting extension method pre-build would be the way to go. We need a pre-build solution, not a runtime solution.

If a field is added and named the same, nothing has to be done and AutoMapper works. However, if the fields are named differently, then you still have to add it to the Mapper config.

Implicit Casts

You could do this with Implicit casts.

  1. Add an implicit cast tot he object under your control, Person.
    using System;
    using System.Runtime.Serialization;
    using WcfToEntityAutomapperExample.DAL.Model;
    
    namespace WcfToEntityAutomapperExample.Services.Model
    {
        [DataContract]
        public class Person
        {
            [DataMember]
            public string FirstName { get; set; }
            [DataMember]
            public string MiddleName { get; set; }
            [DataMember]
            public string LastName { get; set; }
            [DataMember]
            public DateTime DateOfBirth { get; set; }
            [DataMember]
            public DateTime? DateOfDeath { get; set; }
    
            // User-defined conversion from Digit to double 
            public static implicit operator Person(PersonRow personRow)
            {
                return new Person
                {
                    FirstName = personRow.FName,
                    MiddleName = personRow.MName,
                    LastName = personRow.LName,
                    DateOfBirth = personRow.BD,
                    DateOfDeath = personRow.DD
                };
            }
            //  User-defined conversion from double to Digit 
            public static implicit operator PersonRow(Person person)
            {
                return new PersonRow
                {
                    FName = person.FirstName,
                    MName = person.MiddleName,
                    LName = person.LastName,
                    BD = person.DateOfBirth,
                    DD = person.DateOfDeath
                };
            }
        }
    }
    

    The implicit cast is not included in the client code so it is fine to add to the Person DataContract.

  2. Use it in your services.
    using System.Collections.Generic;
    using System.Linq;
    using AutoMapper;
    using WcfToEntityAutomapperExample.DAL;
    using WcfToEntityAutomapperExample.DAL.Model;
    using WcfToEntityAutomapperExample.Extensions;
    using WcfToEntityAutomapperExample.Services.Interfaces;
    using WcfToEntityAutomapperExample.Services.Model;
    
    namespace WcfToEntityAutomapperExample.Services
    {
        public class Service1 : IService1
        {
            public void AddPersonImplicitCast(Person person)
            {
                using (var dbContext = new PersonDbContext())
                {
                    dbContext.People.Add(person);
                    dbContext.SaveChanges();
                }
            }
    
            public List<Person> FindImplicitCast(string lastName)
            {
                using (var dbContext = new PersonDbContext())
                {
                    var foundPeopleFromDb = dbContext.People.Where(p => p.LName == lastName).ToList();
                    return foundPeopleFromDb.Select(p => (Person)p).ToList();
                }
            }
        }
    }
    

Implicit Cast Conclusion

Implicit Cast was pretty simple. I didn’t need any other classes. However, it muddied up a DataContract model class.

It is not obvious why you can add a Person where a PersonRow is needed, but it makes sense.

If I add a property or field, I’d have to add it to the cast.

My Winner

To me it is the extension method, with implicit casts a close second. I just like the simplicity of the code. A first year developer can understand and use it. I also like that it doesn’t muddy up the Model object iself like implicit operators do. Nor does it require me to create a mapping config, and initialize the mapping config.

A read a unit testing argument that unit tests won’t fail when a field is added. I had to disagree. I can put refection code in my unity test fail a test if a property is not copied. Now the reflection code is in a test project not in the production project.

My Loser

AutoMapper. It just doesn’t add the simplicity that it claims to. It by far the most complex in this scenario. Complexity != better. The gains of auto mapping Properties and Fields with the same name doesn’t outweigh the losses in readability.

Also, extension methods are far faster than AutoMapper. I didn’t do benchmarks but 7 times is what other have found. I have some data sets that take a couple of seconds to return. Times a couple of seconds by 7 and you will quickly see that such performance matters. The cost to use reflection when looping through can’t be good for you.

Also, I don’t buy into the argument that performance doesn’t matter. Performance issues pile up over time. I agree that you should not write unreadable code to optimize before you know know that readable code performs poorly. However, if two pieces of code are clear and readable and one is more performant, use the more performant. You shouldn’t make your code more complex and harder to understand to get unnecessary optimization. But with AutoMapper, you are making your code more complex and harder to understand to get less performance? How does that make sense?

Script the creation of the extension methods for objects with members named the same. You’ll be better off for it. You could even add the script to a pre-build command so the extension method is updated pre-build whenever a property is added.

Please comment and tell me which is your winner vs loser?


Logging an Xml SOAP Request from a C# client before sending it

OK. So I wanted to log the xml SOAP request from a C# client before the client actually sent it. The server is referenced using the Web Reference method with these steps:

  1. Right-click on References and select Add Service Reference…
  2. Click Advanced (bottom left of window)
  3. Click Add Web Reference… (bottom left of window)
  4. Enter the URL and click the arrow.
  5. Enter a namespace and click Add reference.

So this is NOT a WCF client hitting a WCF service, so I can’t use a ClientMessageInspector. However, I needed a similar feature. The first option I found output the Xml to the Visual Studio output window, though the output wasn’t clean. Fortunately, I found a more ClientMessageInspector-like method thanks to this stackoverflow post. It seems there is a SoapExtension object I can inherit from. The example in the stackoverflow post was for a server, but it worked from the client as well.

My steps:

  1. Create the project in Visual Studio.
  2. Add Log4Net from NuGet and add Log4Net settings in the Program.cs file.
  3. Add a WebRefence to the Service.
  4. Call the service in main().
    using log4net;
    using log4net.Appender;
    using log4net.Config;
    using log4net.Layout;
    using System.Reflection;
    using System.Text;
    using YourProject.Extensions;
    
    namespace YourProject
    {
        class Program
        {
            private static ILog Logger
            {
                get { return _Logger ?? (_Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType)); }
            } private static ILog _Logger;
    
            static void Main(string[] args)
            {
                ConfigureLog4Net();
                CallWebService();
            }
    
            private static void CallWebService()
            {
               // call service here
            }
    
            private static void ConfigureLog4Net()
            {
                var appender = new FileAppender()
                {
                    Layout = new SimpleLayout(),
                    File = Assembly.GetExecutingAssembly().Location + ".log",
                    Encoding = Encoding.UTF8,
                    AppendToFile = true,
                    LockingModel = new FileAppender.MinimalLock()
                };
                appender.ActivateOptions();
                BasicConfigurator.Configure(appender);
            }
        }
    }
    
  5. Add my Xml helper class so we can log the SOAP Xml with Pretty Xml. See this post: An Xml class to linearize xml, make pretty xml, and encoding in UTF-8 or UTF-16.
  6. Add the SoapLoggerExtension : SoapExtension class.
    using System;
    using System.IO;
    using System.Reflection;
    using System.Web.Services.Protocols;
    using log4net;
    
    namespace YourProject.Extensions
    {
        public class SoapLoggerExtension : SoapExtension
        {
            private static ILog Logger
            {
                get { return _Logger ?? (_Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType)); }
            } private static ILog _Logger;
    
            private Stream _OldStream;
            private Stream _NewStream;
    
            public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
            {
                return null;
            }
    
            public override object GetInitializer(Type serviceType)
            {
                return null;
            }
    
            public override void Initialize(object initializer)
            {
    
            }
    
            public override Stream ChainStream(Stream stream)
            {
                _OldStream = stream;
                _NewStream = new MemoryStream();
                return _NewStream;
            }
    
            public override void ProcessMessage(SoapMessage message)
            {
                switch (message.Stage)
                {
                    case SoapMessageStage.BeforeSerialize:
                        break;
                    case SoapMessageStage.AfterSerialize:
                        Log(message, "AfterSerialize");
                        CopyStream(_NewStream, _OldStream);
                        _NewStream.Position = 0;
                        break;
                    case SoapMessageStage.BeforeDeserialize:
                        CopyStream(_OldStream, _NewStream);
                        Log(message, "BeforeDeserialize");
                        break;
                    case SoapMessageStage.AfterDeserialize:
                        break;
                }
            }
    
            public void Log(SoapMessage message, string stage)
            {
                _NewStream.Position = 0;
                Logger.Debug(stage);
                var reader = new StreamReader(_NewStream);
                string requestXml = reader.ReadToEnd();
                _NewStream.Position = 0;
                if (!string.IsNullOrWhiteSpace(requestXml))
                    Logger.Debug(new Xml(requestXml).PrettyXml);
            }
    
            public void ReverseIncomingStream()
            {
                ReverseStream(_NewStream);
            }
    
            public void ReverseOutgoingStream()
            {
                ReverseStream(_NewStream);
            }
    
            public void ReverseStream(Stream stream)
            {
                TextReader tr = new StreamReader(stream);
                string str = tr.ReadToEnd();
                char[] data = str.ToCharArray();
                Array.Reverse(data);
                string strReversed = new string(data);
    
                TextWriter tw = new StreamWriter(stream);
                stream.Position = 0;
                tw.Write(strReversed);
                tw.Flush();
            }
    
            private void CopyStream(Stream fromStream, Stream toStream)
            {
                try
                {
                    StreamReader sr = new StreamReader(fromStream);
                    StreamWriter sw = new StreamWriter(toStream);
                    sw.WriteLine(sr.ReadToEnd());
                    sw.Flush();
                }
                catch (Exception ex)
                {
                    string message = String.Format("CopyStream failed because: {0}", ex.Message);
                    Logger.Error(message, ex);
                }
            }
        }
    }
    
  7. Add a the Soap to the App.config.
    <configuration>
    
      <!-- Other stuff here -->
    
      <system.web>
        <webServices>
          <soapExtensionTypes>
            <add type="YourProject.Extensions.SoapLoggerExtension, YourProjectAssembly" priority="2" group="Low" />
          </soapExtensionTypes>
        </webServices>
      </system.web>
    </configuration>
    
  8. Now make your web service call and the SOAP xml will be logged to a file.

Happy day.


Authenticating to Java web services with C# using SOAP authentication

Download ProjectWell, we did method 1, basic authentication in our last post: Authenticating to Java web services with C# using basic authentication (using FlexNet services as examples). Let’s do method 2 here.

Method 2 – SOAP Authentication

SOAP authentication is a bit tricky. We have to get to the SOAP request and add headers but we don’t have access to the SOAP header through our SOAP service clients. Once we have access, we need to create custom SoapHeader objects.

We have to use a SoapExtension. A SoapExtension will apply to all SAOP requests, and we may not want that, so we need to enable it based on service.

Step 1 – Create Custom SOAP Header objects for UserId and UserPassword

I created a base object. Notice the XmlText attribute.

using System.Web.Services.Protocols;
using System.Xml.Serialization;

namespace ConnectToFlexeraExample.Model
{
    public class BaseSoapHeader : SoapHeader
    {
        public BaseSoapHeader()
        {
            Actor = "http://schemas.xmlsoap.org/soap/actor/next";
            MustUnderstand = false;
        }

        [XmlText]
        public virtual string Value { get; set; }
    }
}

Then a UserIdSoapHeader object. Notice the XmlRoot attribute.

using System.Xml.Serialization;

namespace ConnectToFlexeraExample.Model
{
    [XmlRoot("UserId", Namespace = "urn:com.macrovision:flexnet/platform")]
    public class UserIdSoapHeader : BaseSoapHeader
    {

    }
}
using System;
using System.Text;
using System.Xml.Serialization;

namespace ConnectToFlexeraExample.Model
{
    [XmlRoot("UserPassword", Namespace = "urn:com.macrovision:flexnet/platform")]
    public class PasswordSoapHeader : BaseSoapHeader
    {
        [XmlIgnore]
        public string EncodedPassword
        {
            set { Value = Convert.ToBase64String(Encoding.UTF8.GetBytes(value)); }
        }
    }
}

Step 2 – Add a SoapHeaderInjectionExtension : SoapExtension

using ConnectToFlexeraExample.Model;
using System;
using System.Collections.Generic;
using System.Net;
using System.Web.Services.Protocols;

namespace ConnectToFlexeraExample.Extensions
{
    public class SoapHeaderInjectionExtension : SoapExtension
    {
        public static Dictionary<string, bool> EnabledServices = new Dictionary<string, bool>();
        public static Dictionary<string, NetworkCredential> UserAndPassword = new Dictionary<string, NetworkCredential>();

        public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
        {
            return null; // Unused
        }

        public override object GetInitializer(Type serviceType)
        {
            return null; // Unused
        }

        public override void Initialize(object initializer)
        {
            // Unused
        }

        public override void ProcessMessage(SoapMessage message)
        {
            if (!IsEnabledForUrl(message.Url))
                return;
            switch (message.Stage)
            {
                case SoapMessageStage.BeforeSerialize:
                    NetworkCredential creds;
                    if (UserAndPassword.TryGetValue(message.Url, out creds))
                    {
                        message.Headers.Add(new UserIdSoapHeader { Value = creds.UserName });
                        message.Headers.Add(new PasswordSoapHeader { EncodedPassword = creds.Password });
                    }
                    break;
                case SoapMessageStage.AfterSerialize:
                    break;
                case SoapMessageStage.BeforeDeserialize:
                    break;
                case SoapMessageStage.AfterDeserialize:
                    break;
            }
        }

        public bool IsEnabledForUrl(string url)
        {
            bool isEnabled;
            EnabledServices.TryGetValue(url, out isEnabled);
            return isEnabled;
        }
    }
}

Step 3 – Add the SoapExtension to the .config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <!-- Other stuff -->

  <system.web>
    <webServices>
      <soapExtensionTypes>
        <add type="ConnectToFlexeraExample.Extensions.SoapHeaderInjectionExtension, ConnectToFlexeraExample" priority="1" group="High" />
        <add type="ConnectToFlexeraExample.Extensions.SoapLoggerExtension, ConnectToFlexeraExample" priority="2" group="Low" />
      </soapExtensionTypes>
    </webServices>
  </system.web>
</configuration>

Step 4 – Update SetNetworkCredentials extension method

We now want this method to accept either SOAP or Basic auth. We are going to key off of PreAuthenticate.

    public static class WebClientProtocolExtensions
    {
        public static void SetNetworkCredentials(this WebClientProtocol client, string username, string password, string customUrl = null, bool preAuthenticate = true)
        {
            client.PreAuthenticate = preAuthenticate;
            client.Url = string.IsNullOrWhiteSpace(customUrl) ? client.Url : customUrl;
            var netCredential = new NetworkCredential(username, password);
            if (preAuthenticate)
            {
                ICredentials credentials = netCredential.GetCredential(new Uri(client.Url), "Basic");
                client.Credentials = credentials;
            }
            else
            {
                SoapHeaderInjectionExtension.EnabledServices[client.Url] = true;
                SoapHeaderInjectionExtension.UserAndPassword[client.Url] = netCredential;
            }
        }
    }

Step 5 – Use the new service clients with SOAP

    private static void TestAuthenticationService(string user, string pass)
    {
        // Basic Auth Method
        // authenticationServiceClient.SetNetworkCredentials(user, pass);
        // Soap Auth Method
        authenticationServiceClient.SetNetworkCredentials(user, pass, null, false);
        var userInputType = new AuthenticateUserInputType
        {
            userName = user,
            password = pass,
            domainName = "FLEXnet"
        };
        var result = authenticationServiceClient.authenticateUser(userInputType);
        Logger.Info(result.Success);
    }

And you are autenticating to Flexera SOAP-based java web services using C#!


Authenticating to Java web services with C# using basic authentication

Download ProjectMy work uses Flexera’s FlexNet for licensing. They use Java for all their services and it uses SOAP. If you have Flexera installed, you can see all their services here: http://yourserver.hostname.told:port/flexnet/services. According to the ‘FlexNet Operations 12.8 Web Services Guide’ (page 11) I can authentication to these services in one of two ways:

Passing the Web Service User
By default, FlexNet Operations Web services requires a client to provide credentials as BASIC HTTP user
authentication. BASIC authentication encrypts the user ID and password with Base64 encoding and passes it as an
HTTP request header parameter. FlexNet For example:

Authorization: Basic QWxhghwelhijhrcGVuIHNlc2FtZQ==

However, not all Web services client tools offer the ability to pass custom HTTP request header parameters in the
request. Therefore, FlexNet Operations supports an alternative mechanism to pass user credentials as SOAP
header parameters along with the SOAP message. The two case-sensitive parameters are UserId and Password.
The password must be Base64 encoded.

<soapenv:Header xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <flex:UserId soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" soapenv:mustUnderstand="0" xmlns:flex="urn:com.macrovision:flexnet/platform">admin
    <flex:UserPassword soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next"soapenv:mustUnderstand="0" xmlns:flex="urn:com.macrovision:flexnet/platform">YWRtaW4=
<!--<span class="hiddenSpellError" pre="" data-mce-bogus="1"-->soapenv:Header>

If the user is authenticated in a domain other than the FlexNet domain, the user ID must be passed as
userName##domain. domain is the name specified when the domain was added to FlexNet Operations. This syntax is
also valid for users in the FlexNet domain. For example, admin##FLEXnet.

The question is, how do I do this with SOAP?

Method 1 – Add Basic Authentication to Request

Step 1 – Add the Web References

First, I created old school Web References to my services.

  1. Right-click on References.
  2. Click Add Service Reference…
  3. Click Advanced (bottom left of window)
  4. Click Add Web Reference… (bottom left of window)
  5. Enter the URL: http://hostname.domain.tld:8888/flexnet/services/FlexnetAuthentication?wsdl
  6. Click the Arrow (right of the URL field)
  7. Set the Web Reference name: Flexera.Auth
  8. Click Add Reference
  9. Repeat these steps for:
    • Flexera.Entitlement – http://hostname.domain.tld:8888/flexnet/services/EntitlementOrderService?wsdl
    • Flexera.Organization – http://hostname.domain.tld:8888/flexnet/services/UserOrgHierarchyService?wsdl
    • . . .

Step 3 – Create a WebClientProtocol extension method to set Credentials

Since all services created with the Web Reference inherit from WebClientProtocol, we can add a single method to all our SOAP based services by using this extension method.

using System;
using System.Net;
using System.Web.Services.Protocols;

namespace ConnectToFlexeraExample.Extensions
{
    public static class WebClientProtocolExtensions
    {
        public static void SetNetworkCredentials(this WebClientProtocol client, string username, string password, string customUrl = null)
        {
            client.PreAuthenticate = true;
            var uri = string.IsNullOrWhiteSpace(customUrl) ? new Uri(client.Url) : new Uri(customUrl);
            var netCredential = new NetworkCredential(username, password);
            ICredentials credentials = netCredential.GetCredential(uri, "Basic");
            client.Credentials = credentials;
        }
    }
}

Step 3 – Create a WebRequest extension method to add basic auth

I created the following class. It assumes that the request has already been assigned the credentials (which we will do in the next step).

using System;
using System.Net;
using System.Text;

namespace ConnectToFlexeraExample.Extensions
{
    public static class WebRequestExtensions
    {
        public static WebRequest GetRequestWithBasicAuthorization(this WebRequest request, Uri uri)
        {
            var networkCredentials = request.Credentials.GetCredential(uri, "Basic");
            byte[] credentialBuffer = new UTF8Encoding().GetBytes(networkCredentials.UserName + ":" + networkCredentials.Password);
            request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(credentialBuffer);
            return request;
        }
    }
}

Step 4 – Inherit the Server Clients to override GetWebRequest

We need to override the GetWebRequest so we can return a request using the GetRequestWithBasicAuthorization extension method so let’s create child classes for our services to use. Also, we only want to use GetRequestWithBasicAuthorization if PreAuthenticate is set to true.

using ConnectToFlexeraExample.Extensions;
using ConnectToFlexeraExample.Flexera.Auth;
using System;
using System.Net;

namespace ConnectToFlexeraExample.Clients
{
    public class AuthenticationClient : FlexnetAuthenticationClient
    {
        protected override WebRequest GetWebRequest(Uri uri = null)
        {
            var actualUri = uri ?? new Uri(Url);
            var request = (HttpWebRequest)base.GetWebRequest(actualUri);
            return (PreAuthenticate) ? request.GetRequestWithBasicAuthorization(actualUri) : request;
        }
    }
}
using ConnectToFlexeraExample.Extensions;
using ConnectToFlexeraExample.Flexera.Organization;
using System;
using System.Net;

namespace ConnectToFlexeraExample.Clients
{
    public class OrganizationClient : UserOrgHierarchyService
    {
        protected override WebRequest GetWebRequest(Uri uri = null)
        {
            var actualUri = uri ?? new Uri(Url);
            var request = (HttpWebRequest)base.GetWebRequest(actualUri);
            return (PreAuthenticate) ? request.GetRequestWithBasicAuthorization(actualUri) : request;
        }
    }
}
using ConnectToFlexeraExample.Extensions;
using ConnectToFlexeraExample.Flexera.Entitlement;
using System;
using System.Net;

namespace ConnectToFlexeraExample.Clients
{
    public class EntitlementClient : EntitlementOrderService
    {
        protected override WebRequest GetWebRequest(Uri uri = null)
        {
            var actualUri = uri ?? new Uri(Url);
            var request = (HttpWebRequest)base.GetWebRequest(actualUri);
            return (PreAuthenticate) ? request.GetRequestWithBasicAuthorization(actualUri) : request;
        }
    }
}

Step 5 – Use the new service clients

    static void Main(string[] args)
    {
        string user = args[0];
        string pass = args[1];

        TestAuthenticationClient(user, pass);
        TestOrganizationClient(user, pass);
        TestEntitlementClient(user, pass);
    }

    private static void TestAuthenticationClient(string user, string pass)
    {
        var AuthenticationClientClient = new AuthenticationClient();
        // Basic Auth Method
        AuthenticationClientClient.SetNetworkCredentials(user, pass);
        var userInputType = new AuthenticateUserInputType
        {
            userName = user,
            password = pass,
            domainName = "FLEXnet"
        };
        var result = AuthenticationClientClient.authenticateUser(userInputType);
    }

    // ... other Test methods

You are now authenticating to FlexNet SOAP-based java web services with C#.

Read about Method 2 – SOAP Authentication here: Authenticating to Java web services with C# using Soap authentication (using FlexNet services as examples)


Authentication Token Service for WCF Services (Part 3 – Token Validation in IDispatchMessageInspector)

In Authentication Token Service for WCF Services (Part 2 – Database Authentication) we showed how to verify our token. However, we verified the token in the service itself.

WCF BTS Message Inspector

This is not ideal.

    [OperationContract]
    [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
    public string Test()
    {
        var token = HttpContext.Current.Request.Headers["Token"];
        using (var dbContext = new BasicTokenDbContext())
        {
            ITokenValidator validator = new DatabaseTokenValidator(dbContext);
            if (validator.IsValid(token))
            {
                // Do service work here . . . 
            }
        }
    }

This is fine for a one or two services. But what if there are going to have many services? The Don’t Repeat Yourself (DRY) principle would be broken if we repeated the same lines of code at the top of every service. If only we could validate the token in one place, right? Well, we can.

We could make a method that we could call at the top of every service, but even if we did that, we would still have to repeat one line for every service. Is there a way where we wouldn’t even have to repeat a single line of code? Yes, there is. Using Aspect-oriented programming (AOP). It turns out WCF services have some AOP capabilities built in.

IDispatchMessageInspector can be configured to do this.

To enable this, your really need to implement three Interfaces and configure it in the web.config. I am going to use separate classes for each interface.

The web config extension class:

using System;
using System.ServiceModel.Configuration;

namespace WcfSimpleTokenExample.Behaviors
{
    public class TokenValidationBehaviorExtension : BehaviorExtensionElement
    {
        #region BehaviorExtensionElement

        public override Type BehaviorType
        {
            get { return typeof(TokenValidationServiceBehavior); }
        }

        protected override object CreateBehavior()
        {
            return new TokenValidationServiceBehavior();
        }

        #endregion
    }
}

The Service Behavior class:

using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace WcfSimpleTokenExample.Behaviors
{
    public class TokenValidationServiceBehavior : IServiceBehavior
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (var t in serviceHostBase.ChannelDispatchers)
            {
                var channelDispatcher = t as ChannelDispatcher;
                if (channelDispatcher != null)
                {
                    foreach (var endpointDispatcher in channelDispatcher.Endpoints)
                    {
                        endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new TokenValidationInspector());
                    }
                }
            }
        }

        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }
    }
}

The message inspector class

using System.Net;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Web;
using WcfSimpleTokenExample.Business;
using WcfSimpleTokenExample.Database;
using WcfSimpleTokenExample.Interfaces;

namespace WcfSimpleTokenExample.Behaviors
{
    public class TokenValidationInspector : IDispatchMessageInspector
    {
        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            // Return BadRequest if request is null
            if (WebOperationContext.Current == null) { throw new WebFaultException(HttpStatusCode.BadRequest); }

            // Get Token from header
            var token = WebOperationContext.Current.IncomingRequest.Headers["Token"];

            // Validate the Token
            using (var dbContext = new BasicTokenDbContext())
            {
                ITokenValidator validator = new DatabaseTokenValidator(dbContext);
                if (!validator.IsValid(token))
                {
                    throw new WebFaultException(HttpStatusCode.Forbidden);
                }
                // Add User ids to the header so the service has them if needed
                WebOperationContext.Current.IncomingRequest.Headers.Add("User", validator.Token.User.Username);
                WebOperationContext.Current.IncomingRequest.Headers.Add("UserId", validator.Token.User.Id.ToString());
            }
            return null;
        }

        public void BeforeSendReply(ref Message reply, object correlationState)
        {
        }
    }
}

Basically, what happens is AfterReceiveRequest is called somewhere between when the actual packets arrive at the server and just before the service is called. This is perfect. We can validate our token here in a single place.

So let’s populate our AfterReceiveRequest.

        public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            // Return BadRequest if request is null
            if (WebOperationContext.Current == null) { throw new WebFaultException(HttpStatusCode.BadRequest); }

            // Get Token from header
            var token = WebOperationContext.Current.IncomingRequest.Headers["Token"];

            // Validate the Token
            using (var dbContext = new BasicTokenDbContext())
            {
                ITokenValidator validator = new DatabaseTokenValidator(dbContext);
                if (!validator.IsValid(token))
                {
                    throw new WebFaultException(HttpStatusCode.Forbidden);
                }
                // Add User ids to the header so the service has them if needed
                WebOperationContext.Current.IncomingRequest.Headers.Add("User", validator.Token.User.Username);
                WebOperationContext.Current.IncomingRequest.Headers.Add("UserId", validator.Token.User.Id.ToString());
            }
            return null;
        }

You might have noticed we made one change to the ITokenValidator. See the changes below. It now has a Token property, as does its implementation, DatabaseTokenValidator. Mostly I am getting Token.UserId, but since EF gets the User object for me too, I went ahead an added the User name as well.

using WcfSimpleTokenExample.Database;
namespace WcfSimpleTokenExample.Interfaces
{
    public interface ITokenValidator
    {
        bool IsValid(string token);
        Token Token { get; set; }
    }
}
using System;
using System.Linq;
using WcfSimpleTokenExample.Database;
using WcfSimpleTokenExample.Interfaces;

namespace WcfSimpleTokenExample.Business
{
    public class DatabaseTokenValidator : ITokenValidator
    {
        // Todo: Set this from a web.config appSettting value
        public static double DefaultSecondsUntilTokenExpires = 1800;

        private readonly BasicTokenDbContext _DbContext;

        public DatabaseTokenValidator(BasicTokenDbContext dbContext)
        {
            _DbContext = dbContext;
        }

        public bool IsValid(string tokentext)
        {
            Token = _DbContext.Tokens.SingleOrDefault(t => t.Text == tokentext);
            return Token != null && !IsExpired(Token);
        }

        internal bool IsExpired(Token token)
        {
            var span = DateTime.Now - token.CreateDate;
            return span.TotalSeconds > DefaultSecondsUntilTokenExpires;
        }

        public Token Token { get; set; }
    }
}

Now we don’t need all that Token validation code in our Service. We can clean it up. In fact, since all it does right now is return a string, our service only needs a single line of code. I also added the UserId and User to the output for fun.

    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Test1Service
    {
        [OperationContract]
        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
        public string Test()
        {
            return string.Format("Your token worked! User: {0} User Id: {1}",
                WebOperationContext.Current.IncomingRequest.Headers["UserId"],
                WebOperationContext.Current.IncomingRequest.Headers["User"]);
        }
    }

Well, now that it is all coded up, it won’t work until we enable the new behavior in the web.config. So let’s look at the new web.config. We create a new ServiceBehavior (lines 34-38) for all the services that validate the token. We leave the AuthenticationTokenService the same as we don’t have a token when we hit it because we hit it to get the token. We also need to make sure to add the behavior extension (lines 41-46). Then we need to tell our ServiceBehavior to use the new extension (line 37).

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name="WcfSimpleTokenExample.Services.AuthenticationTokenService" behaviorConfiguration="ServiceBehaviorHttp">
        <endpoint address="" behaviorConfiguration="AjaxEnabledBehavior" binding="webHttpBinding" contract="WcfSimpleTokenExample.Services.AuthenticationTokenService" />
      </service>
      <service name="WcfSimpleTokenExample.Services.Test1Service" behaviorConfiguration="ServiceAuthBehaviorHttp">
        <endpoint address="" behaviorConfiguration="AjaxEnabledBehavior" binding="webHttpBinding" contract="WcfSimpleTokenExample.Services.Test1Service" />
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="AjaxEnabledBehavior">
          <webHttp helpEnabled="true" />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehaviorHttp">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
        <behavior name="ServiceAuthBehaviorHttp">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <TokenValidationBehaviorExtension />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <extensions>
      <behaviorExtensions>
        <add name="TokenValidationBehaviorExtension"
          type="WcfSimpleTokenExample.Behaviors.TokenValidationBehaviorExtension, WcfSimpleTokenExample, Version=1.0.0.0, Culture=neutral"/>
      </behaviorExtensions>
    </extensions>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <directoryBrowse enabled="true" />
  </system.webServer>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
  <connectionStrings>
    <add name="BasicTokenDbConnection" connectionString="data source=(LocalDB)\v11.0;attachdbfilename=|DataDirectory|\BasicTokenDatabase.mdf;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

Go on and read part 4 here: Authentication Token Service for WCF Services (Part 4 – Supporting Basic Authentication)


AOP Custom Contract: ListNotEmptyAttribute

So I have a List and I need to make sure that the list has at least one value when it is passed in. If the list is empty, I should throw and exception. Here is an example of what the code would look like if you did NOT use an aspect:

using System;
using System.Collections.Generic;

namespace CustomContractsExample
{
    public class People
    {
        private readonly List<Person> _People;

        public People(List<Person> people)
        {
            if (people == null)
                throw new ArgumentNullException("people", "The list cannot be null.");
            if (people.Count == 0)
                throw new ArgumentException("people", "The list cannot be empty.");
            _People = people;
        }

        public List<Person> List
        {
            get { return _People; }
        }
    }
}

Note: My use case is not actually a People object with a List. It is instead something proprietary for my company and a far more valid use case. I am using the People class for simplicity in demonstration only.

I decided to handle this precondition checking not in the methods, but in an Aspect. Particularly, by using a PostSharp LocationContractAttribute. I recently wrote a post about this here:
AOP Contracts with PostSharp

So we need to create a new custom contract as I didn’t find one written by PostSharp. At first, I wondered why not. Why not create a quick generic attribute like this:

using System.Collections.Generic;
using PostSharp.Aspects;
using PostSharp.Patterns.Contracts;
using PostSharp.Reflection;

namespace CustomContractsExample
{
    public class ListNotEmptyAttribute<T> : LocationContractAttribute, ILocationValidationAspect<List<T>>
    {
        new public const string ErrorMessage = "The List<T> must not be empty.";

        protected override string GetErrorMessage()
        {
            return "The List<T> must not be empty: {2}";
        }

        public System.Exception ValidateValue(List<T> value, string locationName, LocationKind locationKind)
        {
            if (value == null)
                return CreateArgumentNullException(value, locationName, locationKind);
            if (value.Count == 0)
                return CreateArgumentException(value, locationName, locationKind);
            return null;
        }
    }
}

Well, the reason is because C# doesn’t support generic attributes. I get this error at compile time:

A generic type cannot derive from ‘LocationContractAttribute’ because it is an attribute class

This is a tragedy. What makes it more of a tragedy is that I could do this if I wrote directly in IL. It is simply a compiler limitation for C#. Arrrgggss!!!! Good thing MSBuild is going open source at https://github.com/Microsoft/msbuild. Hopefully, the DotNet team, or some interested party such as PostSharp, or maybe me, contributes a few changes to MSBuild and removes this limitation.

As for now, List also implements IList, so I will revert to using that. IList provided a workaround for this use case, however, such a work around won’t always be available.

using System.Collections;
using PostSharp.Aspects;
using PostSharp.Patterns.Contracts;
using PostSharp.Reflection;

namespace CustomContractsExample
{
    public class ListNotEmptyAttribute : LocationContractAttribute, ILocationValidationAspect<IList>
    {
        new public const string ErrorMessage = "The List must not be empty.";

        protected override string GetErrorMessage()
        {
            return "The list must not be empty: {2}";
        }

        public System.Exception ValidateValue(IList value, string locationName, LocationKind locationKind)
        {
            if (value == null)
                return CreateArgumentNullException(value, locationName, locationKind);
            if (value.Count == 0)
                return CreateArgumentException(value, locationName, locationKind);
            return null;
        }
    }
}

Now here is the new People class. See how it is much cleaner.

using System.Collections.Generic;

namespace CustomContractsExample
{
    public class People
    {
        private readonly List<Person> _People;

        public People([ListNotEmpty]List<Person> people)
        {
            _People = people;
        }

        public List<Person> List
        {
            get { return _People; }
        }
    }
}

The constructor is much cleaner and easier to read.

Also, my unit tests pass.

using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CustomContractsExample;

namespace CustomContractsExampleTests
{
    [TestClass]
    public class PeopleTests
    {
        // Arrange
        private const string Firstname = "Jared";
        private const string LastName = "Barneck";

        [TestMethod]
        public void TestNewPersonWorks()
        {
            var person = new Person(Firstname, LastName);
            var list = new List<Person> { person };
            var people = new People(list);

            Assert.IsNotNull(people);
            Assert.IsFalse(people.List.Count == 0);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestNewPersonThrowsExceptionIfFirstNameNull()
        {
            new People(null);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNewPersonThrowsExceptionIfLastNameNull()
        {
            new People(new List<Person>());
        }
    }
}

Maybe PostSharp can pick this up my ListNotEmptyAttribute and add it to their next released version.


AOP Contracts with PostSharp

So, I’ve been using Aspect Oriented Programming for a while. My company has a license for PostSharp. Recently I started using it more, in particularly, I started using the Contracts feature for checking the parameters of my methods. This is called precondition checking. Read more here: PostSharp Contracts

Here is a basic example of precondition checking. Imagine a Person class where the firstName and lastName should throw an exception if null, empty, or whitespace.
Your code might look like this:

using System;

namespace CustomContractsExample
{
    public class Person
    {
        private readonly string _FirstName;
        private readonly string _LastName;

        public Person(string firstName, string lastName)
        {
            // Validate first name
            if (string.IsNullOrWhiteSpace(firstName))
                throw new ArgumentException("Parameter cannot be a null, empty or whitespace string.", "firstName");

            // Validate last name
            if (lastName == string.Empty)
                throw new ArgumentException("Parameter cannot be an null, empty or whitespace string.", "lastName");

            // Initialize fields
            _FirstName = firstName;
            _LastName = lastName;
        }

        public string FirstName
        {
            get { return _FirstName; }
        }

        public string LastName
        {
            get { return _LastName; }
        }
    }
}

Ugh! Those lines to validate and throw exceptions are UGLY! Not to mention redundant. How many times might you write this same code. Probably over and over again. Of course this breaks the Don’t Repeat Yourself (DRY) principle.

Now, install PostSharp.Patterns.Model from NuGet.
(Note 1: This also installs PostSharp and PostSharp.Patterns.Common.)
(Note 2: This requires a paid license but is well worth it).

Looking at the Contracts, we particularly are interested in this one:

RequiredAttribute

RequiredAttribute is an attribute that, when added to a field, property or parameter, throws an ArgumentNullException if the target is assigned a null value or an empty or white-space string.

Here is the same class using PostSharp.Aspects.Contracts.

using PostSharp.Patterns.Contracts;

namespace CustomContractsExample
{
    public class Person
    {
        private readonly string _FirstName;
        private readonly string _LastName;

        public Person([Required]string firstName, [Required]string lastName)
        {
            _FirstName = firstName;
            _LastName = lastName;
        }

        public string FirstName
        {
            get { return _FirstName; }
        }

        public string LastName
        {
            get { return _LastName; }
        }
    }
}

Now, doesn’t that looks much nicer.

Yes, it does.

One issue:

It throws an ArgumentNullException if the string is empty or WhiteSpace. To me this is “Ok” but not preferred. If the data is not null, we shouldn’t say it is. Looking at the RequiredAttribute code, it is doing this:

        public Exception ValidateValue(string value, string locationName, LocationKind locationKind)
        {
            if (!string.IsNullOrWhiteSpace(value))
                return null;
            return CreateArgumentNullException(value, locationName, locationKind);
        }

It really should be doing this.

        public Exception ValidateValue(string value, string locationName, LocationKind locationKind)
        {
            if (value == null)
                return (Exception)this.CreateArgumentNullException((object)value, locationName, locationKind);
            if (string.IsNullOrWhiteSpace(value))
                return (Exception)this.CreateArgumentException((object)value, locationName, locationKind);
            return (Exception)null;
        }

We can easily roll our own class to fix this bug.

using System;
using PostSharp.Aspects;
using PostSharp.Patterns.Contracts;
using PostSharp.Reflection;

namespace CustomContractsExample
{
    public sealed class StringRequiredAttribute : LocationContractAttribute, ILocationValidationAspect<string>
    {
        protected override string GetErrorMessage()
        {
            return (ContractLocalizedTextProvider.Current).GetMessage("RequiredErrorMessage");
        }

        public Exception ValidateValue(string value, string locationName, LocationKind locationKind)
        {
            if (value == null)
                return CreateArgumentNullException(value, locationName, locationKind);
            if (string.IsNullOrWhiteSpace(value))
                return CreateArgumentException(value, locationName, locationKind);
            return null;
        }
    }
}

And here are my unit tests for what I expect. They all pass with my new StringRequired class.

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CustomContractsExample;

namespace CustomContractsExampleTests
{
    [TestClass]
    public class PersonTests
    {
        // Arrange
        private const string Firstname = "Jared";
        private const string LastName = "Barneck";

        [TestMethod]
        public void TestNewPersonWorks()
        {
            var person = new Person(Firstname, LastName);
            Assert.IsNotNull(person);
            Assert.IsFalse(string.IsNullOrWhiteSpace(person.FirstName));
            Assert.IsFalse(string.IsNullOrWhiteSpace(person.LastName));
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestNewPersonThrowsExceptionIfFirstNameNull()
        {
            new Person(null, LastName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestNewPersonThrowsExceptionIfLastNameNull()
        {
            new Person(Firstname, null);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNewPersonThrowsExceptionIfFirstNameEmpty()
        {
            new Person(string.Empty, LastName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNewPersonThrowsExceptionIfLastNameEmpty()
        {
            new Person(Firstname, "");
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNewPersonThrowsExceptionIfFirstNameWhiteSpace()
        {
            new Person("  ", LastName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void TestNewPersonThrowsExceptionIfLastNameWhiteSpace()
        {
            new Person(Firstname, "     ");
        }
    }
}

How to mock an Entity Framework DbContext and its DbSet properties

Entity Framework (EF) is a data access layer (DAL) that allows for easily accessing a database for your create, read, update, and delete (CRUD) actions. If you use Entity Framework, you don’t need to test your DAL CRUD actions. You just need to test your code that uses it.

With EF, you can mock your database, though it isn’t exactly easy. The database is interfaced through the DbContext. Tables are interfaces through a property of type DbSet where T is an object representing data in the table. For example, DbSet would represent your users. We can use a List to mock the database table. It would also be nice if we could easily have every table mocked by default.

Ok, now that we have established that EF 6 DbContext mocking isn’t easy, let’s change that. Let’s make it easy.

Using the following two classes, you can easily mock your DbContext with a single line of code:

var mockDbContext = EntityFrameworkMockHelper.GetMockContext<MyDbContext>();

Note: While this single line of code successfully mocks your DbContext, it doesn’t add any default data. You still have to do that work yourself, but now it should be easy because you can use the very easy to use Add method on any table.

MockDbContext.Object.People.Add(new Person{ FirstName = "John", LastName = "Doe" });

Or if you have a List of sample data already created, you can add that list with AddRange.

MockDbContext.Object.People.AddRange(SamplePeople);

And here are the two classes I wrote to help with this. I must admit, I spent over three days researching this and getting this working. So hopefully, this saves you from having to do the same.

using Moq;
using System.Collections.Generic;
using System.Data.Entity;

namespace LANDesk.Licensing.WebServices.Tests.Data
{
    public class MockedDbContext<T> : Mock<T> where T : DbContext
    {
        public Dictionary<string, object> Tables
        {
            get { return _Tables ?? (_Tables = new Dictionary<string, object>()); }
        } private Dictionary<string, object> _Tables;
    }
}
using System;
using Moq;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;

namespace LANDesk.Licensing.WebServices.Tests.Data
{
    public static class EntityFrameworkMockHelper
    {
        /// <summary>
        /// Returns a mock of a DbContext
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static MockedDbContext<T> GetMockContext<T>() where T : DbContext
        {
            var instance = new MockedDbContext<T>();
            instance.MockTables();
            return instance;
        }

        /// <summary>
        /// Use this method to mock a table, which is a DbSet{T} oject, in Entity Framework.
        /// Leave the second list null if no adds or deletes are used.
        /// </summary>
        /// <typeparam name="T">The table data type</typeparam>
        /// <param name="table">A List{T} that is being use to replace a database table.</param>
        /// <returns></returns>
        public static DbSet<T> MockDbSet<T>(List<T> table) where T : class
        {
            var dbSet = new Mock<DbSet<T>>();
            dbSet.As<IQueryable<T>>().Setup(q => q.Provider).Returns(() => table.AsQueryable().Provider);
            dbSet.As<IQueryable<T>>().Setup(q => q.Expression).Returns(() => table.AsQueryable().Expression);
            dbSet.As<IQueryable<T>>().Setup(q => q.ElementType).Returns(() => table.AsQueryable().ElementType);
            dbSet.As<IQueryable<T>>().Setup(q => q.GetEnumerator()).Returns(() => table.AsQueryable().GetEnumerator());
            dbSet.Setup(set => set.Add(It.IsAny<T>())).Callback<T>(table.Add);
            dbSet.Setup(set => set.AddRange(It.IsAny<IEnumerable<T>>())).Callback<IEnumerable<T>>(table.AddRange);
            dbSet.Setup(set => set.Remove(It.IsAny<T>())).Callback<T>(t => table.Remove(t));
            dbSet.Setup(set => set.RemoveRange(It.IsAny<IEnumerable<T>>())).Callback<IEnumerable<T>>(ts =>
            {
                foreach (var t in ts) { table.Remove(t); }
            });
            return dbSet.Object;
        }

        /// <summary>
        /// Mocks all the DbSet{T} properties that represent tables in a DbContext.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="mockedContext"></param>
        public static void MockTables<T>(this MockedDbContext<T> mockedContext) where T : DbContext
        {
            Type contextType = typeof(T);
            var dbSetProperties = contextType.GetProperties().Where(prop => (prop.PropertyType.IsGenericType) && prop.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>));
            foreach (var prop in dbSetProperties)
            {
                var dbSetGenericType = prop.PropertyType.GetGenericArguments()[0];
                Type listType = typeof(List<>).MakeGenericType(dbSetGenericType);
                var listForFakeTable = Activator.CreateInstance(listType);
                var parameter = Expression.Parameter(contextType);
                var body = Expression.PropertyOrField(parameter, prop.Name);
                var lambdaExpression = Expression.Lambda<Func<T, object>>(body, parameter);
                var method = typeof(EntityFrameworkMockHelper).GetMethod("MockDbSet").MakeGenericMethod(dbSetGenericType);
                mockedContext.Setup(lambdaExpression).Returns(method.Invoke(null, new[] { listForFakeTable }));
                mockedContext.Tables.Add(prop.Name, listForFakeTable);
            }
        }
    }
}

An Xml class to linearize xml, make pretty xml, and encoding in UTF-8 or UTF-16.

UPDATE: This is now part of the EasyXml NuGet package. There is also an EasyXml.Sources NuGet package.

OK, so I had to output an Xml for something I am doing for work. I need the Xml to be pretty. I decided I wanted a C# class that would do the equivalent of what the Xml plugin in Notepad++ does. It should create Linear Xml, Pretty Xml, etc.

I found a bunch of problems when doing this in C#:

  1. How to make an Xml linearized in C#?
  2. How to make the Xml pretty, including indents and cleaned up spacing? I could get the indents, but the spacing was a problem until I solved how to linearize the Xml.
  3. How to make the Xml declaration say UTF-8? It kept saying the Xml was in UTF-16, which was accurate because the file was UTF-16. Strings in C# are always Unicode (UTF-16).
  4. How to make UTF-8 uppercase? Once I got the Xml declaration to say UTF-8, the UTF-8 text was lowercase, utf-8, instead of uppercase. Lowercase should work, but it turns out uppercase is preferred.
  5. How to output the Xml as a file in actual UTF-8 format? It is one thing to have UTF-8 in the Xml declaration, it is quite another to actually output a file byte stream in UTF-8 vs UTF-16 (Unicode). A UTF-8 file should be 1/2 the size of a UTF-16 file.

So here is my class. I hope it helps you. All the questions are answered by this class.

using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;

namespace Rhyous.EasyXml
{
    public class Xml
    {
        public Xml(string text)
        {
            Text = text;
        }

        /// <summary>
        /// And enumeration to select UTF8 or UTF16 encoding. This is used because the defautl UTF8 
        /// and Unicode encoding types don't capitalize the UTF characters in the Xml declaration.
        /// </summary>
        public enum XmlEncoding
        {
            UTF8, // By being first it is the default
            UTF16
        };

        /// <summary>
        /// The original Xml text as is.
        /// </summary>
        public string Text { get; private set; }

        /// <summary>
        /// The Xml in a single line (no new lines or carriage returns). The data is trimmed and no more than a single space anywhere.
        /// </summary>
        public string LinearizeXml
        {
            get { return _LinearizeXml ?? (_LinearizeXml = Clean(Document, LinearizedSettings)); }
        } private string _LinearizeXml;

        /// <summary>
        /// And XDocument representation of the Xml. It uses the Linearized Xml not the original text.
        /// </summary>
        public XDocument Document
        {
            get { return _Document ?? (_Document = XDocument.Parse(GetLinearizedXml(Text))); }
        } private XDocument _Document;

        /// <summary>
        /// The Xml with each element properly indented on a separate line. The data is trimmed and no more than a single space anywhere.
        /// </summary>
        public string PrettyXml
        {
            get { return _PrettyXml ?? (_PrettyXml = Clean(Document, PrettySettings)); }
        } private string _PrettyXml;

        /// <summary>
        /// An enum that specifies whether to use UTF-8 or Unicode (UTF-16).
        /// Changing the encoding shouldn't change the original Text but pretty and linearized 
        /// versions of the Xml should change as well as the stream.
        /// </summary>
        public XmlEncoding Encoding { get; set; }

        /// <summary>
        /// A method that outputs the Xml as a stream. It outputs using the correct Encoding.
        /// It isn't enough to write encoding="UTF-8" in the Xml declaration if the output file
        /// is still UTF-16. Botht the labeling and the actually bits in the file should match.
        /// </summary>
        /// <returns>A file stream in the configured encoding.</returns>
        public Stream ToStream()
        {
            return new MemoryStream(ToByteArray());
        }

        /// <summary>
        /// This creates a byte array using the correct encoding.
        /// 
        /// Note: Naturally, UTF-8 has half as manay bytes as UTF-16, however,
        /// if UTF-8 is n bytes, UTF-16 will be 2*N+2 bytes. This is because
        /// "UTF-8" is five characters and "UTF-16" is six characters. 
        /// So a 100 byte UTF-8 file would be 202 bytes in UTF-16. 
        /// </summary>
        /// <returns>A byte[] array of the Xml string in the configured encoding.</returns>
        public byte[] ToByteArray()
        {
            return GetEncoding().GetBytes(PrettyXml ?? "");
        }

        /// <summary>
        /// A method to get the current encoding based on the Enum value.
        /// </summary>
        /// <returns>The correct Encoding.</returns>
        private Encoding GetEncoding()
        {
            switch (Encoding)
            {
                case XmlEncoding.UTF8:
                    return XmlUTF8Encoding.Instance;
                case XmlEncoding.UTF16:
                    return XmlUnicode.Instance;
                default:
                    return XmlUnicode.Instance;
            }
        }

        /// <summary>
        /// XmlWriterSettings for linearized Xml.
        /// </summary>
        private XmlWriterSettings LinearizedSettings
        {
            get
            {
                return new XmlWriterSettings
                    {
                        Encoding = GetEncoding(),
                        Indent = false,
                        NewLineOnAttributes = false
                    };
            }
        }

        /// <summary>
        /// XmlWriterSettings for Pretty Xml.
        /// </summary>
        private XmlWriterSettings PrettySettings
        {
            get
            {
                return new XmlWriterSettings
                {
                    Encoding = GetEncoding(),
                    Indent = true,
                    IndentChars = string.IsNullOrEmpty(IndentCharacters) ? "  " : IndentCharacters,
                    NewLineOnAttributes = false,
                    NewLineHandling = NewLineHandling.Replace
                };
            }
        }

        /// <summary>
        /// The characters to use for indenting Pretty Xml
        /// </summary>
        public string IndentCharacters { get; set; }

        /// <summary>
        /// The method that uses XDocument to do make clean (pretty or linearized) Xml
        /// </summary>
        /// <param name="doc">The XDcoument version of the Xml.</param>
        /// <param name="settings">The configured XmlWriterSettings.</param>
        /// <returns>A pretty Xml string.</returns>
        private string Clean(XDocument doc, XmlWriterSettings settings)
        {
            var sb = new StringBuilder();
            var stringWriter = new StringWriterWithEncoding(sb, GetEncoding());
            using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
            {
                doc.Save(xmlWriter);
                xmlWriter.Flush();
                return sb.ToString();
            }
        }

        /// <summary>
        /// A method that uses Regex to linearize Xml. The regex replaces methods are used.
        /// </summary>
        /// <param name="text">The Xml text</param>
        /// <returns>Linearized Xml string.</returns>
        private string GetLinearizedXml(string text)
        {
            // Replace all white space with a single space
            var halfclean = Regex.Replace(text, @"\s+", " ", RegexOptions.Singleline);

            // Trim after >.
            var clean75 = Regex.Replace(halfclean, @">\s+", ">");

            // Trim before <
            var fullclean = Regex.Replace(clean75, @"\s+<", "<");

            return fullclean;
        }

        /// <summary>
        /// This clas allows for the Xml to be created with the Xml declaration saying UTF-8
        /// </summary>
        private sealed class StringWriterWithEncoding : StringWriter
        {
            private readonly Encoding _Encoding;

            public StringWriterWithEncoding(StringBuilder builder, Encoding encoding)
                : base(builder)
            {
                _Encoding = encoding;
            }

            public override Encoding Encoding
            {
                get { return _Encoding; }
            }
        }

        /// <summary>
        /// This class makes the UTF-8 text in the Xml declaration show up capitalized.
        /// </summary>
        private sealed class XmlUTF8Encoding : UTF8Encoding
        {
            public override string WebName
            {
                get { return base.WebName.ToUpper(); }
            }

            public override string HeaderName
            {
                get { return base.HeaderName.ToUpper(); }
            }

            public override string BodyName
            {
                get { return base.BodyName.ToUpper(); }
            }

            public static XmlUTF8Encoding Instance
            {
                get { return _XmlUTF8Encoding ?? (_XmlUTF8Encoding = new XmlUTF8Encoding()); }
            } private static XmlUTF8Encoding _XmlUTF8Encoding;
        }

        /// <summary>
        /// This class makes the UTF-16 text in the Xml declaration show up capitalized.
        /// </summary>
        private sealed class XmlUnicode : UnicodeEncoding
        {
            public override string WebName
            {
                get { return base.WebName.ToUpper(); }
            }

            public override string HeaderName
            {
                get { return base.HeaderName.ToUpper(); }
            }

            public override string BodyName
            {
                get { return base.BodyName.ToUpper(); }
            }

            public static XmlUnicode Instance
            {
                get { return _XmlUnicode ?? (_XmlUnicode = new XmlUnicode()); }
            } private static XmlUnicode _XmlUnicode;
        }
    }
}

And here are some Unit Tests.

using LANDesk.Licensing.WebServices.Model;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Text;

namespace Rhyous.EasyXml.Tests
{
    [TestClass]
    public class XmlTests
    {
        public string LinearUtf8Xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Person><FirstName>John</FirstName><MiddleName>Al Leon</MiddleName><LastName>Doe</LastName></Person>";
        public string PrettyUtf8Xml =
@"<?xml version=""1.0"" encoding=""UTF-8""?>
<Person>
  <FirstName>John</FirstName>
  <MiddleName>Al Leon</MiddleName>
  <LastName>Doe</LastName>
</Person>";
        public string PrettyUtf8XmlWithTabs =
@"<?xml version=""1.0"" encoding=""UTF-8""?>
<Person>
	<FirstName>John</FirstName>
	<MiddleName>Al Leon</MiddleName>
	<LastName>Doe</LastName>
</Person>";
        public string UglyUtf8Xml =
@"<?xml version=""1.0""
encoding=""UTF-8""?>
<Person>

<FirstName>
    John
        </FirstName>

<MiddleName>
    Al
    Leon
                </MiddleName>
  <LastName>
    


Doe
        </LastName>


</Person>";

        public string LinearUtf16Xml = "<?xml version=\"1.0\" encoding=\"UTF-16\"?><Person><FirstName>John</FirstName><MiddleName>Al Leon</MiddleName><LastName>Doe</LastName></Person>";
        public string PrettyUtf16Xml =
@"<?xml version=""1.0"" encoding=""UTF-16""?>
<Person>
  <FirstName>John</FirstName>
  <MiddleName>Al Leon</MiddleName>
  <LastName>Doe</LastName>
</Person>";
        public string UglyUtf16Xml =
@"<?xml version=""1.0""
encoding=""UTF-16""?>
<Person>

<FirstName>
    John
        </FirstName>

<MiddleName>
    Al
    Leon
                </MiddleName>
  <LastName>
    


Doe
        </LastName>


</Person>";

        [TestMethod]
        public void TestMethodLinearize()
        {
            // Arrange
            Xml xml = new Xml(PrettyUtf8Xml);

            // Act
            var actual = xml.LinearizeXml;

            // Assert
            Assert.AreEqual(LinearUtf8Xml, actual);
        }

        [TestMethod]
        public void TestMethodPretty()
        {
            // Arrange
            Xml xml = new Xml(LinearUtf8Xml);

            // Act
            var actual = xml.PrettyXml;

            // Assert
            Assert.AreEqual(PrettyUtf8Xml, actual);
        }

        [TestMethod]
        public void TestMethodLinearizeUgly()
        {
            // Arrange
            Xml xml = new Xml(UglyUtf8Xml);

            // Act
            var actual = xml.LinearizeXml;

            // Assert
            Assert.AreEqual(LinearUtf8Xml, actual);
        }

        [TestMethod]
        public void TestMethodMakeUglyPretty()
        {
            // Arrange
            Xml xml = new Xml(UglyUtf8Xml);

            // Act
            var actual = xml.PrettyXml;

            // Assert
            Assert.AreEqual(PrettyUtf8Xml, actual);
        }

        [TestMethod]
        public void TestMethodLinearizeUglyUtf16()
        {
            // Arrange
            Xml xml = new Xml(UglyUtf16Xml)
            {
                Encoding = Xml.XmlEncoding.UTF16
            };

            // Act
            var actual = xml.LinearizeXml;

            // Assert
            Assert.AreEqual(LinearUtf16Xml, actual);
        }

        [TestMethod]
        public void TestMethodMakeUglyPrettyUtf16()
        {
            // Arrange
            Xml xml = new Xml(UglyUtf16Xml)
            {
                Encoding = Xml.XmlEncoding.UTF16
            };

            // Act
            var actual = xml.PrettyXml;

            // Assert
            Assert.AreEqual(PrettyUtf16Xml, actual);
        }

        [TestMethod]
        public void TestMethodStreamIsUtf8()
        {
            // Arrange
            Xml xml = new Xml(UglyUtf8Xml)
            {
                Encoding = Xml.XmlEncoding.UTF8
            };

            // Act
            var actual = xml.ToStream();
            using (var memoryStream = new MemoryStream())
            {
                actual.CopyTo(memoryStream);
                var bytes = memoryStream.ToArray();
                // Assert
                Assert.AreEqual(154, bytes.Length);
            }
        }

        [TestMethod]
        public void TestMethodStreamIsUtf16()
        {
            // Arrange
            Xml xml = new Xml(UglyUtf16Xml)
            {
                Encoding = Xml.XmlEncoding.UTF16
            };

            // Act
            var actual = xml.ToStream();
            using (var memoryStream = new MemoryStream())
            {
                actual.CopyTo(memoryStream);
                var bytes = memoryStream.ToArray();

                // Assert
                // 310 is twice the size of 154, 308, but add 2 bytes because
                // UTF-8 is 5 characters but UTF-16 is 6 characters so it is 
                // one character longer.John
                Assert.AreEqual(310, bytes.Length);
            }
        }

        [TestMethod]
        public void TestMethodPrettyWuthTabs()
        {
            // Arrange
            Xml xml = new Xml(LinearUtf8Xml)
            {
                IndentCharacters = "\t"
            };

            // Act
            var actual = xml.PrettyXml;

            // Assert
            Assert.AreEqual(PrettyUtf8XmlWithTabs, actual);
        }

        [TestMethod]
        public void TestMethodStreamUtf8IsDifferentThanStreamUtf16()
        {
            const string text = "Hello, world!";

            var utf8 = Encoding.UTF8.GetBytes(text);
            var utf16 = Encoding.Unicode.GetBytes(text);

            Assert.AreNotEqual(utf8.Length, utf16.Length);
        }
    }
}

Hello Paypal Here. Goodbye Square Up.

PayPal-HereI love my new Surface Pro 3. When I go to a conference, I want my Surface Pro 3 to be used as the Cash Registers. Alas, Square Up doesn’t support the Surface Pro 3. But guess what? Paypal Here, a direct competitor to Square Up does support the Surface Pro 3. My Paypal Here card reader is on its way.

I accepted, begrudgingly, the fact that you didn’t work with my Windows 7 laptop when I first got Square Up. But that was more than two years ago. There are 300 million windows devices out there. Why would you ignore that market share?

Thank you Squareup.com for being a good card reader. I enjoyed your server. I liked it. However, you haven’t kept up with the industry. The Surface Pro 3, as well as other similar 3rd party hybrid tablet/laptops, is turning iPads and Android tablets into paperweights. You’ll be fine without me. Hopefully you update your software soon before you lose more accounts than mine. Once I am up and working with PayPal Here, I doubt I will make the effort to come back.

So I tell you goodbye Square. And hello PayPal Here!

Get PayPal Here from the Windows Store.

Note: This isn’t an ad. I wasn’t paid to make this post. I am however, frustrated with Square Up for not providing an App for my Surface Pro 3.


A cryptographically random base95 string (the ascii printable characters)

using System;
using System.Security.Cryptography;
using System.Text;

namespace LANDesk.Licensing.WebServices.Business
{
    public class CryptoRandomString
    {
        public static string GetCryptoRandomBase64String(int length)
        {
            var buffer = new byte[length];
            using (var rngCryptoServiceProvider = new RNGCryptoServiceProvider())
            {
                rngCryptoServiceProvider.GetNonZeroBytes(buffer);
            }
            return Convert.ToBase64String(buffer);
        }
        
        public static string GetCryptoRandomBaseNString(int length, byte baseN)
        {
            if (length < 1)
                throw new ArgumentException("The string length must be greater than 0!");
            if (baseN < 2)
                throw new ArgumentException("The base must be 2 or greater!");

            var buffer = new byte[length];
            var builder = new StringBuilder();

            using (var rngCryptoServiceProvider = new RNGCryptoServiceProvider())
            {
                rngCryptoServiceProvider.GetBytes(buffer);
                foreach (var b in buffer)
                {
                    var tmpbuff = new byte[] { b };
                    int max = (baseN * (256 / baseN)) - 1; // minus 1 because we start at 0
                    while (tmpbuff[0] > max)
                    {
                        rngCryptoServiceProvider.GetBytes(tmpbuff);
                    }
                    var singleChar = ByteToBaseNChar(tmpbuff[0], baseN, 32); // Start at ascii 32 (space)
                    builder.Append(singleChar);
                }
            }
            return builder.ToString();
        }

        public static string GetCryptoRandomBase95String(int length)
        {
            return GetCryptoRandomBaseNString(length, 95);
        }

        public static char ByteToBaseNChar(byte b, int baseN, int asciiOffset)
        {
            return (char)(b % baseN + asciiOffset);
        }
    }
}

And here are a few tests for it. If you can think of a additional tests, please let me know.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using LANDesk.Licensing.WebServices.Business;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace LANDesk.Licensing.WebServices.Tests.Business
{
    [TestClass]
    public class CryptoRandomStringTests
    {
        [TestMethod]
        public void TestTestThatCorrectCharacterCountIsReturned()
        {
            const int length = 100;
            var randomString = CryptoRandomString.GetCryptoRandomBase95String(length);
            Assert.AreEqual(length, randomString.Length);
        }

        [TestMethod]
        public void TestAllCharactersAreUsed()
        {
            const int length = 1000000;
            var randomString = CryptoRandomString.GetCryptoRandomBase95String(length);
            for (int i = 32; i < 126; i++)
            {
                char c = (char)i;
                Assert.IsTrue(randomString.Contains(c.ToString()));
            }
        }

        [TestMethod]
        public void TestPerformanceTenMillionCharacters()
        {
            Stopwatch watch = new Stopwatch();
            watch.Start();
            const int length = 1000000;
            var randomString = CryptoRandomString.GetCryptoRandomBase95String(length);
            watch.Stop();
            Assert.IsTrue(watch.ElapsedMilliseconds < 1000);
        } // Elapsed Milliseconds 320 (it fluxuated a few milliseconds each run) 

        [TestMethod]
        public void TestPerformanceLoop()
        {
            Stopwatch watch = new Stopwatch();
            const int length = 16;
            watch.Start();
            for (int i = 0; i < 100000; i++)
            {
                var randomString = CryptoRandomString.GetCryptoRandomBase95String(length);
            }
            watch.Stop();
            Assert.IsTrue(watch.ElapsedMilliseconds < 1000);
        }

        [TestMethod]
        public void TestDistributionInTenMillionCharacters()
        {
            const int length = 1000000;
            const int distibution = length / 95;
            int[] margins = new int[9500];
            for (int j = 0; j < 100; j++)
            {
                var randomString = CryptoRandomString.GetCryptoRandomBase95String(length);
                for (int i = 32; i < 127; i++)
                {
                    //int count = randomString.Count(c => c == i);
                    int count = CountInstancesOfChar(randomString, (char)i);
                    margins[(j * 95) + i - 32] = count;
                }
            }
            Assert.IsTrue(Math.Abs(margins.Average() - distibution) < .5);
        }

        private int CountInstancesOfChar(string str, char c)
        {
            int count = 0;
            char[] strArray = str.ToCharArray();
            int length = str.Length;
            for (int n = length - 1; n >= 0; n--)
            {
                if (strArray[n] == c)
                    count++;
            }
            return count;
        }
    }
}