Implementing Centralised Input Model Validation in a WCF Service Application

I have had to develop a fair few WCF service applications in my .Net development carrier. If you haven't taking a deep dive into WCF before, you might not be aware of the numerous extensibility points built into the framework. Every now and then, you need to understand one of these extensibility points well enough to use it to handle typical cross-cutting concerns in service applications like validation.

Even though I have implemented centralised validation on a few ocassions in WCF, I tend not to remember all the details and so left scratching my head the next time I have to implement it again so I thought why not write a post on it. 

Before we proceed, I am making an assumption here that you, my reader has basic knowledge of WCF and understand concepts like data contracts service contracts serialization, service instance etc.

Two main steps involved in achieving this: 

First we need to hook into the WCF infrastructure and have an AOP like interception of the service operation call. This is what the IParameterInspector interface was designed for. Some IoC containers support the concept of interception and provide an AOP like approach to run code before and after a method call and can equally be used to achieve the same result as the IParameterInspector but that will be like fighting the framework. If the framework has it built in then I prefer the built in approach to any other. You might do this like below:

public class ValidationParameterInspector : IParameterInspector
    {
        public object BeforeCall(string operationName, object[] inputs)
        {
            var validationResults = new List();
            inputs.ToList().ForEach(input => validationResults.AddRange(ValidationHelper.ValidateModel(input).ToList()));

            if (validationResults.Any())
            {
                var flattenedMessage = new StringBuilder();
                validationResults.ForEach(validationResult =>
                {
                    flattenedMessage.AppendFormat("{0},{1}", validationResult.MemberNames.FirstOrDefault(),
                        validationResult.ErrorMessage);
                    flattenedMessage.AppendLine();
                });
                throw new ValidationException(flattenedMessage.ToString());
            }

            return null;
        }

        public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
        {
        }
    }


If we want to plug our parameter inspector into an entire service class so all our operations, we can achieve this by implementing an IServiceBehavior interface. When implement the ApplyDispatchBehavior method and assign our parameter inspector to each channel. A sample implementation looks like the below code:

public class ValidationBehaviorAttribute : Attribute, IServiceBehavior 
    {

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

        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints,
            BindingParameterCollection bindingParameters)
        {                   
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
            {
                if (channelDispatcher == null)
                {
                    continue;
                }

                foreach (var endPoint in channelDispatcher.Endpoints)
                {
                    if (endPoint == null)
                    {
                        continue;
                    }

                    foreach (var opertaion in endPoint.DispatchRuntime.Operations)
                    {
                        opertaion.ParameterInspectors.Add(new ValidationParameterInspector());
                    }
                }
            }
        }
    }

The are a few ways of plugging the custom behavior into our service. The simplest approach being the use of an attribute hence why we derived our custom ValidationBehaviorAttribute from the base framework Attribute class. We apply the behavior by decorating our service class with the attribute like so:

  [ValidationBehaviorAttribute]
   public class SomeService 
    {
       public SomeService()
       {
       }
    }

Now to the actual validation. We leverage the very versatile data annotations validation library now a first class citizen of the .Net framework to perform the actual validation. The advantage we get from using a framework component like the data annotations library is the fact its built in and we don't need to wire up any external framework into our code base. The data annotations validation approach is also clean in the sense that the data contract objects serialized across the wire by WCF themselves are the only classes we focus on when writing our validation business logic. And we get to capture most of our logic by the use of attributes on properties. The below code shows the core requirements of such a basic validator. We create a validation context and use it to initialise the data annotations validator and use the TryValidate method to validate our input parameters. The input parameters to the service operation are passed in an array of objects so we iterate over all the objects and validate each one. We then accumulate the validation results into a list. The code is as below:

public class ValidationHelper
    {
        public static IEnumerable ValidateModel(TModel model) where TModel : class
        {
            var validationContext = new ValidationContext(model, null, null);
            var validationResults = new List();
            Validator.TryValidateObject(model, validationContext, validationResults, true);
            return validationResults;
        }
    }
public object BeforeCall(string operationName, object[] inputs)
        {
            var validationResults = new List();
            inputs.ToList().ForEach(input => validationResults.AddRange(ValidationHelper.ValidateModel(input).ToList()));

            if (validationResults.Any())
            {
                var flattenedMessage = new StringBuilder();
                validationResults.ForEach(validationResult =>
                {
                    flattenedMessage.AppendFormat("{0},{1}", validationResult.MemberNames.FirstOrDefault(),
                        validationResult.ErrorMessage);
                    flattenedMessage.AppendLine();
                });
                throw new ValidationException(flattenedMessage.ToString());
            }

            return inputs;
        }

We then check for the presence of at least one validation error and throw an exception appropriately. If there were no validation error, then we simply return our input objects from the BeforeCall method of our IParameterInspector implementation. The return value is passed into the AfterCall method by the framework as a correlation parameter.

The final piece of the puzzle is the IErrorHandler interface. This is another WCF extensibility endpoint and serves as a final catch all exception handling mechanism. We can intercept our validation exception in the Providefault method and convert it into a soap fault to be transmitted back to our calling client as demonstrated in the code below:

public class ErrorHandler : IErrorHandler
    {
        #region IErrorHandler Members

        public bool HandleError(Exception error)
        {
            return false;
        }

        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            if (error == null)
                return;

            if (HttpContext.Current == null) //In case we run outside of IIS 
                // see http://groups.google.com/group/elmah/browse_thread/thread/9ea4b51420fd5dfa
                ErrorLog.GetDefault(null).Log(new Error(error));
            else
                ErrorSignal.FromCurrentContext().Raise(error);

            if (error is ValidationException)
            {
                var faultEx = new FaultException(error.Message);
                MessageFault msgFault = faultEx.CreateMessageFault();
                fault = Message.CreateMessage(version, msgFault, faultEx.Action);
            }

            if (error is System.ApplicationException)
            {
                var faultEx = new FaultException(error.Message);
                MessageFault msgFault = faultEx.CreateMessageFault();
                fault = Message.CreateMessage(version, msgFault, faultEx.Action);
            }
        }

        #endregion
    }

Well so, that is it. Hope it helped you out.

Get PropertyName as string - simplified version

I realise there are quite a few ways of doing this online. A lot of the implementations cover all bases. This is an attempt to craft a lean mean version for simply returning properties as strings using a static class with reasonably named class and method:


private class PropertyName
        {
            public static string For(Expression> expression)
            {
                return (expression.Body is MemberExpression) ? ((MemberExpression)expression.Body).Member.Name
                     : ((MemberExpression)((UnaryExpression)expression.Body).Operand).Member.Name;
            }
        }
    

VS 2013 RIA Service serialise child entities

The code below is an example of how you can use data contract serializer to serialize child entities to send as a json string property on parent object and then de-serialise the child entity in the Insert method of the parent entity in the RIA implementation

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.ServiceModel.DomainServices.Server;
using System.Text;

namespace Commerce.Catalogue.SageServer
{    
    public class Kit
    {
        [Key]
        public long Id { get; set; }
        public string Description { get; set; }
        public string CompList { get; set; } 
        public decimal Price { get; set; }
        [Include]
        [Composition]
        [Association("Kit_Components", "Id", "KitId")]       
        public ICollection Component { get; set; }
    }

    [DataContract]
    public class Component
    {
        [Key]
        [DataMember]
        public long Id { get; set; }
        [DataMember]
        public long KitId { get; set; }
        [DataMember]
        public string ComponentItemNo { get; set; }
        [DataMember]
        public int Qty { get; set; }                
    }

    public class SageService : DomainService
    {
        [Query(IsDefault = true)]
        public IQueryable GetKits()
        {
            return Enumerable.Empty().AsQueryable();   
        }

        [Update]
        [Invoke]
        public void UpdateKit(Kit kit)
        {
            var desc = kit.Description;
            var test = "hello";
        }

        [Insert]
        [Invoke]
        public void InsertKit(Kit kit)
        {
            var desc = kit.Description;
            var kitComp = new List();
            var compList = kit.CompList.Split('|').ToList();
            foreach (var comp in compList)
            {
                kitComp.Add(ReadToObject(comp));
            }

            var test = "hello";
        }

        [Delete]
        [Invoke]
        public void DeleteKit(Kit kit)
        {
            
        }

        // Deserialize a JSON stream to object.
        public static Component ReadToObject(string json)
        {
            var deserializedComponent = new Component();
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json));
            DataContractJsonSerializer ser = new DataContractJsonSerializer(deserializedComponent.GetType());
            deserializedComponent = ser.ReadObject(ms) as Component;
            ms.Close();
            return deserializedComponent;
        }
    }
}

In the RIA service client environment (lightswitch or Silverlight), you can serialize the child entity as shown by the below code:


 partial void Publish_Execute()
        {
            foreach (var item in selectedStocks)
            {
                var comp = new List();
                comp.Add(new Component{ComponentItemNo = "AB12", Id=1, KitId = 1,Qty = 2});
                comp.Add(new Component { ComponentItemNo = "CD40", Id = 2, KitId = 1,Qty=3 });
                var compStringList = new List();
                comp.ForEach(x => compStringList.Add(WriteFromObject(x)));
                
                var kit = DataWorkspace.SageServiceData.Kits.AddNew();
                kit.Id = 1;
                kit.Description = "Test Kit";
                kit.Price = 2.20M;
                kit.CompList = string.Join("|", compStringList.AsEnumerable());
                DataWorkspace.SageServiceData.SaveChanges();               
            }
        }

        // Serialize object to a JSON stream.
        public static string WriteFromObject(Component comp)
        {
            //Create a stream to serialize the object to.
            MemoryStream ms = new MemoryStream();

            // Serializer the User object to the stream.
            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Component));
            ser.WriteObject(ms, comp);
            byte[] json = ms.ToArray();
            ms.Close();
            return Encoding.UTF8.GetString(json, 0, json.Length);

        }
HTH

Lightswitch many to many query filter format

If you have a lightswitch schema with a many to many relationship such as product-->productcategorymap<--category then you can add a parameter to your query such as categoryId (set as optional and not connected to a filter), link that parameter to the categories table (after adding it to your screen in the screen designer so you can display an auto complete list) and then add code similar to the below code in the query preprocessor handler of your query entity. Remember there is no need to implement query parameters mapped to entity properties. You just have to write code for the "free/unbound parameters":

In the code snippet below, a category entity is nested, so a  category references another category as its parent, so that specialised case where we match all sub categories of a given parent category Id is also handled.

 if (CategoryId.HasValue)
        query = query.Where(product => product.ProductCategoryMaps.Any(
			map => map.CategoryId == CategoryId 
			|| map.Category.ParentCategory.categoryID == CategoryId));

Sagepay server integration (.Net) with SSL pitfalls

Well, considering this took me a while to figure out, it might very well come in handy for you.

If you are integrating Sagepay server method on a Windows Server 2012 (IIS 8) server and in particular serving your payment pages over SSL, (this will imply the url you supply to sagepay aka NotificationUrl for handling the http POST response from Sagepay is an https url. I don't see why you wouldn't use SSL anyway), then one issue you might face is Server Name Indication. You may read all about SNI from here.

How does it affect your integration, well it turns out if your were to tick the server name indication checkbox shown below then Sagepay fails to contact your server and site with the notification response.

 

It gets particularly difficult to spot if your test/staging server runs IIS 7.x or IIS 6 which does not provide SNI support but your production server provides the support and you enable it without realising the problem.

So why does Sagepay's http POST fail under SNI? Well I don't know the inner workings/implementation details of Sagepays http post but SNI support is limited to specific browsers on specific operating systems as specified in the above linked wikipedia article so it is very likely Sagepay's implementation does not send the 'virtual server name' as part of the SSL client handshake request  (used loosely, you need to dig deeper into SNI to understand). This article might help.

Hopefully this helped you find the solution a bit quicker than I did. Sagepay's support sent me a list of things to check and this was not one of them so obviously they haven't noticed this one yet.

Cheers!

Html helper for list of hidden Inputs from Name Value Pair string

Recently, while working on a project to integrate a payment provider via the hosted payment page approach embedded within an Iframe, I needed a simple Html Helper for ASP.Net MVC which took in a name value pair string like FIRSTNAME=Mike&LASTNAME=Teye&Age=25 and generated a list of html hidden input tags for use as part of a form post whose response was then rendered in an Iframe tag.

I admit it's a specialised helper and so I don't forsee many people needing it, but then again should you be one of those few who needed it, the below class represents my attempt at such a helper:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Web.Mvc;

namespace Kraft.Web.Models.Extensions
{
    public static class HtmlHelperExtensions
    {
        public static MvcHtmlString HiddenFieldsListFor(this HtmlHelper htmlHelper, Expression> expression)
        {
            var name = ExpressionHelper.GetExpressionText(expression);
            var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            return HiddenFieldsList(htmlHelper, name, metadata.Model as string);
        }

        private static MvcHtmlString HiddenFieldsList(this HtmlHelper helper, string nameValuePairPropertyName, string nameValuePairPayload)
        {
            var stringBuilder = new StringBuilder();
            var nameValuePairs = nameValuePairPayload.Split('&').ToList();
            nameValuePairs.ForEach(nvp => stringBuilder.Append(CreateHiddenInput(nvp).ToString(TagRenderMode.SelfClosing)));
            var div = new TagBuilder("div");
            div.MergeAttribute("class", "hiddenFields");
            div.InnerHtml = stringBuilder.ToString();
            return MvcHtmlString.Create(div.ToString());

        }

        private static TagBuilder CreateHiddenInput(string nameValuePair)
        {
            var hiddenInput = new TagBuilder("input");
            var nvpPortions = nameValuePair.Split('=');
            hiddenInput.MergeAttribute("type", "hidden");
            hiddenInput.MergeAttribute("id", nvpPortions[0]);
            hiddenInput.MergeAttribute("name", nvpPortions[0]);
            hiddenInput.MergeAttribute("value", nvpPortions[1]);
            return hiddenInput;
        }
    }
}

You can use the helper in an MVC razor view like so (where NvpPayload is a view model property containing your name value pair string):

@Html.HiddenFieldsListFor(model => model.NvpPayload)

Hope you find it helpful.

Integrating SandCastle Help File Builder with TFS 2012 build

Sandcastle has been around for a while. Its usage has however been dificult and unappealing until Sandcastle Help File Builder codeplex project came into the picture.

The recent version of Sandcatsle help file builder makes it even more easier by providing a Visual Studio plugin which facilitates the management of the help file generation through familiar visual studio project properties and also allows referencing projects which are part of your solution in your SHFB project.

The only piece of the puzzle missing is the integration of the build of the document project as part of a CI build on Team Foundation Server TFS. There are a few outdated approaches to this available online when I googled. I felt there should be an easier integration now that there is a VS plugin, so I set out to check this out and in turns out it is very easy. So the below is how I did the simple integration:

To Create a visual studio SHFB project, download and install SHFB on your development machine using the guided installer. You will have to install the Visual Studio plugin as part of the install. Create a new project in Visual Studio by using the documentation subsection of your choice language. The details of configuring the help file builder are the same as that for the standalone Sandcastle Help file builder GUI.

First of all you will need to download the latest version of Sandcastle Help File builder (which ships with the VS plugin).

Extract the files from the zip archive and use the guided installer from the root folder to install sandcastle and help file compiler onto

the build controller machine.

You will have to restart the build controller machine to reload new path environment variables created by the installer (SHFBROOT).

This environment variable is used within a sandcastle help file project to locate the help file compiler executables and serves the same purpose on the build agent machine as it does on a local development machine.

You will need one final modification to the help file builder project. First unload the project by right clicking on the project name in solution explorer and select unload project. Then open the project file xml by right clicking and selecting open with xml editor. As per this post, replace the line immediately below the following line:


With the following code:

  

.\Help\
$(OutDir)

Ignore SignalR Persistent Connections in New Relic

I had a problem recently at work where the SignalR.Hosting.AspNet.AspNetHandler was displaying high response times in our New Relic monitoring. I came across this SO blog post which offerred some workarounds for the problem. I was however using an older version of SignalR (a pre 1.0 release) and the options listed in the blog post failed to resolve my particular case.

What worked for me eventually was to hook into the PostMapRequestHandler event of the Application class in global.asax and then check for the handler. Because that event fires after a handler has been selected to process the request, we are able to tell what type of handler has been selected and then use the NewRelic Agent API (You will need to add this to your project via Nuget, search for NewRelic.Api.Agent) to ignore monitoring as per the code below:

 protected void Application_PostMapRequestHandler()
 {
     if (HttpContext.Current.Handler is SignalR.Hosting.AspNet.AspNetHandler)
     {
          NewRelic.Api.Agent.NewRelic.IgnoreTransaction();
     }
}

This approach works even for later versions of SignalR (1.0+) in which case you have to match the OWIN based handler as shown below:

protected void Application_PostMapRequestHandler()
{
     if (HttpContext.Current.Handler is Microsoft.Owin.Host.SystemWeb.OwinHttpHandler)
     {
          NewRelic.Api.Agent.NewRelic.IgnoreTransaction();
     }
} 

Happy coding!

MvcSitemapProvider Implementation : Lessons learnt

1.If you happen to be using any active directory based role provider, make sure the website is running with default authentication turned off and windows authentication turned on. You can do this easily by configuring your website to run on IIS or IIS Express.

2. For any node configured in the sitemap file using the controller and action values, make sure the controller and action are actually available. The MvcSitemapProvider fails silently and does not throw any exceptions to make you aware of why it is failing. This means you cannot simply bash up some dummy routes and expect it to work.

3. If you enable security trimming by setting "securityTrimmingEnabled" to true on the provider node in web.config, then you need to specify a roles="*" for nodes accessible to all users.

4. If you use "#" for url values, they will not show up while security trimming is enabled.

5. I also think, parent nodes should be at a higher url level to child nodes otherwise the parent node is not displayed, I haven't thoroughly verified this so I might be wrong on this one.

6. I tried using resourceKey settings in the sitemap file and the corresponding nodes were not rendered by the menu helper.

Custom Validator IsValid Overload Precedence

 

When you derived a Custom DataAnnotations Validator from the default ValidationAttribute class, you have a choice of two overrides to implement your custom validation logic. You may override one of the following methods depending on your objectives.

  • public bool IsValid(object value)
  • protected ValidationResult(object value, ValidationContext validationContext)

Recently, I had a situation where I implemented custom validation (ie. The validator did not use the built in MVC DefaultModelBinder which implemented validation). I hooked up a custom model binder and also needed an accompanying custom validator. I ended up using the DataAnnotations Validator from within my code like so:

 var context = new ValidationContext(wizardBindModel, null, null) {MemberName = item.PropertyInfo.Name};
                        var validationResults = new Collection();
                        if (!Validator.TryValidateValue(value, context, validationResults, new Collection(){validationAttribute}))
                        {
                            validationResults.ToList().ForEach(r => modelState.AddModelError(r.MemberNames.First(), r.ErrorMessage));
                        }    
I was then wondering, what happened if my validation attribute implemented both IsValid(object) and IsValid(object, ValidationContext). I did not find an explanation through google, so I tried the code and found out by experience that the IsValid(object,ValidationContext) has precedence over the IsValid(object) method. If you override both methods, only the IsValid(object,ValidationContext) version will be invoked by the DataAnnotations TryValidateValue method. HTH.