DbGeometry serialization issue in Asp.net web api - asp.net-web-api

I'm building an OData v3 Web API with Entity Framework 6.0 Code First.
Everything works well and I can execute CRUD operations back to the api server.
However I'm using Spatial Types and some of my entities have DbGeometry properties. When I try to update/post an entity with a DbGeometry type from a client application (just a console application for tests) I get this DataServiceRequestException:
No parameterless constructor defined for this object.
It took me a while but I identified the DbGeometry type as the responsible. I already looked at this topic here and made a custom JsonConverter, where I applied to the property:
[Required]
[JsonConverter(typeof(DbGeometryConverter))]
[Column("geometria")]
public DbGeometry Geometria { get; set; }
That didn't worked. The object is not deserialized on the web api server unless I remove the DbGeometry property.
I also tried to change the Global json serializer behavior
var formatters = GlobalConfiguration.Configuration.Formatters;
var jsonFormatter = formatters.JsonFormatter;
jsonFormatter.SerializerSettings.Converters.Add(new DbGeometryConverter());
Also futile. I really need the DbGeometry properties. What else can I do to work around this issue?

A little late, but for those who'll seek an answer:
I've managed to do it with the exact same code on a controller level. The idea was taken from this SO Question&Answer.
So, here is the code including the DbGeometryConverter.
DbGeometryConverter.cs:
public class DbGeometryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsAssignableFrom(typeof(DbGeometry));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var location = JObject.Load(reader);
var token = location["Geometry"]["WellKnownText"];
string geom = token.ToString();
token = location["Geometry"]["CoordinateSystemId"];
int srid = token != null ? int.Parse(token.ToString()) : 0;
var converted = DbGeometry.FromText(geom, srid);
return converted;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanWrite => false;
}
CustomJsonAttribute.cs:
public class CustomJsonAttribute : Attribute, IControllerConfiguration
{
public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
{
var formatter = controllerSettings.Formatters.JsonFormatter;
formatter.SerializerSettings.Converters.Add(new DbGeometryConverter());
}
}
And [CustomJson] attribute on a controller that uses DbGeometry.

Related

How to handle enum as string binding failure when enum value does not parse

In our ASP.net Core Web API application I am looking for a way to catch binding errors when my controller method accepts a complex object which has an ENUM property when ENUMs are de/serialized as strings.
eg.
class Person
{
public string Name {get; set;}
public SexEnum Sex {get; set;}
}
enum SexEnum
{
Male,
Female,
Other
}
We use system wide StringEnumConverter so a JSON serialized instance of Person looks like so:
{
"name": "Ann",
"sex": "female"
}
Now if I post this JSON (note the typo in the sex property):
{
"name": "Ann",
"sex": "femal"
}
the whole object received by the controller method is NULL as binding failed.
I would like to catch that binding error and, instead of having the pipeline go into the controller as if nothing is wrong, return a BAD REQUEST to the client including the detail of which property value failed to bind.
I know the type I am trying to deserialize into, I know the property type I am trying to deserialize and I can see the value does not parse into the type. So I think there must be a way of providing that detail to the client. I just don't know where and how to plug this in.
I would like the solution to be system wide so that all enums are covered, without having to put attributes on the properties of the model or on the enums themselves. (This is because we distribute our API models as a nuget package which cannot have any dependencies.)
We had this issue recently and wrote our own attribute to handle it:
public class ValidEnumValueAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
Type enumType = value.GetType();
bool valid = Enum.IsDefined(enumType, value);
if(!valid)
{
return new ValidationResult($"{value} is not a valid value for type {enumType.Name}");
}
return ValidationResult.Success;
}
}
class Person
{
public string Name {get; set;}
[ValidEnumValue]
public SexEnum Sex {get; set;}
}
The error is then added to the ModelState so you can use ModelState.IsValid to check if the values are valid.
if(!ModelState.IsValid)
{
return BadRequest(ModelState);
}
EDIT
If you don't want to use an attribute then you can derive a new converter from NewtonSoft StringEnumConverter and have that check the value is valid before reading the json e.g.
public class validEnumConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if(!Enum.IsDefined(objectType, reader.Value))
{
throw new ArgumentException("Invalid enum value");
}
return base.ReadJson(reader, objectType, existingValue, serializer);
}
}
This is added to the JsonOptions in your startup class:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.Converters.Add(new validEnumConverter());
});
}
Following up on Simply Ged's answer above, AFAICS, this actually cannot be done as the model binding exceptions are swallowed (https://github.com/aspnet/Mvc/issues/3898)
ModelState contains model binding errors and you can get some information out of that. As we currently use only JSON serialization, I ended up implementing a filter to check the ModelState errors for JsonSerializationException. It is not perfect though as eg. to get the requested value (that failed the binding) out of the JsonSerializationException you need to parse the inner exception message.
If someone finds a better solution, I will be happy to hear.
Expanding on #Simply Ged's excellent answer, 2nd part, using a nullable enum produces System.ArgumentException: 'Type provided must be an Enum.' exception. An extra step is required to handle nullable enum, or a null value for the enum:
public class validEnumConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
Type enumType = (Nullable.GetUnderlyingType(objectType) ?? objectType);
if(!Enum.IsDefined(enumType, reader.Value ?? string.Empty))
{
throw new ArgumentException("Invalid enum value");
}
return base.ReadJson(reader, objectType, existingValue, serializer);
}
}
Just got this issue recently.
The way I overcome that was applying
[EnumDataType(typeof(YOUR_ENUM_TYPE))] above your model enum.
Example:
public class SaladModel
{
[EnumDataType(typeof(SauceTypeEnum))]
public SauceTypeEnum SauceType { get; set; }
}
Now once you post this to the WebAPI endpoint, its validated and returns as BadRequest by the framework.
You do this with the JsonStringEnumConverter converter.
public class PersonModel
{
public string Name { get; set; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public SexKind Sex { get; set; }
}
public enum SexKind
{
Male,
Female,
Confused
}

Validating deserialised object with Postsharp Contracts

[This is kind of an obvious question but I couldn't find anything about it - if someone could reference me, it'll be grand.]
In a WebAPI project:
public class MyObject
{
[PostSharp.Patterns.Contract.Required]
public string Name {get;set;}
}
public class MyController : ApiController
{
public HttpResponseMessage Post([FromBody]MyObject obj)
{
/// ...
}
}
During compilation, I guess PostSharp's validations put themselves in the setter of the property, so when obj is deserialised from the request's body, its fields aren't validated.
So, what's the best/clean way to validate that object?
Cheers
There is currently no clean way to achieve such validation as it is presumed that once-serialized object is already valid.
In order to force the validation logic, one would need to use ISerializationCallback interface's OnDeserialized method, go through properties and forcibly set them to their current value in order to enforce validation.
This can be done by a PostSharp aspect, but it would be certainly non-trivial. Other possibility is to use reflection/expression trees to achieve the same.
If you think that this would be a nice feature of PostSharp, you can vote PostSharp's UserVoice page.
As Daniel Balas wrote, there's no simple solution to trigger PostSharp's validations after deserializing an object, except implementing OnDeserialized method of ISerializationCallback interface. So I post an Aspect I wrote that deep copies public properties of objects one by one through reflection, and hence activating the validations in the setters.
[Serializable]
public sealed class ArgsValidationAspect : MethodInterceptionAspect
{
public override bool CompileTimeValidate(MethodBase method)
{
if (!method.GetParameters().Any(p => p.ParameterType.IsClass))
{
Message.Write(method, SeverityType.Error, "MY001", "Cannot apply HttpObjectValidationAspect to method '{0}'.", method);
return false;
}
return true;
}
public override void OnInvoke(MethodInterceptionArgs args)
{
foreach (var arg in args.Arguments)
{
try
{
RecursiveCopyInstance(arg);
}
catch (Exception e)
{
throw e.InnerException ?? e;
}
}
base.OnInvoke(args);
}
private static object RecursiveCopyInstance(object origin)
{
var type = origin.GetType();
var instance = Activator.CreateInstance(type);
foreach (var prop in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
{
var val = prop.GetValue(origin);
if (val != null && !prop.PropertyType.IsPrimitive && !prop.PropertyType.Equals(typeof(string)))
{
val = RecursiveCopyInstance(val);
}
prop.SetValue(instance, val);
}
return instance;
}
}

Web API ModelBinders - how to bind one property of your object differently

I have the following action signature
[ValidateInput(false)]
public HttpResponseMessage PostParam(Param param)
With Param looking something like this:
public class Param {
public int Id { get; set;}
public string Name { get; set; }
public string Choices { get; set; }
}
Here's the hitch - what comes over the wire is something like this
{
Id: 2,
Name: "blah",
Choices: [
{
foo: "bar"
},
{
blah: "blo"
something: 123
}
]
}
I don't want "Choices" to deserialize - I want it stored as a string (yes, I understand the security implications). Understandably, I get an error because since the default binder does not know this.
Now with Asp Mvc creating a specific ModelBinder would be fairly simple. I'd
inherit DefaultModelBinder
override the property deserialization with my own
set the binder in my Application_Start using Binders.Add
Seems like with Web Api this is a different process - the System.Web.DefaultModelBinder doesn't have anything to override and that I can't hook things up using Binders.Add. I've tried looking around but couldn't find much on how to actually do what I want. This is further complicated since apparently the ModelBinders api changed quite a bit over Beta and RTM so there's a lot of outdated information out there.
In Web API you have to distinguish three concepts - ModelBinding, Formatters and ParameterBinding. That is quite confusing to people moving from/used to MVC, where we only talk about ModelBinding.
ModelBinding, contrary to MVC, is responsible only for pulling data out of URI. Formatters deal with reading the body, and ParameterBinding (HttpParameterBinding) encompasses both of the former concepts.
ParameterBinding is really only useful when you want to revolutionize the whole mechanism (i.e. allow two objects to be bound from body, implement MVC-style binding and so on) - for simpler tasks modifying binders (for URI specific data) or formatters (for body data) is almost always more than enough.
Anyway, to the point - what you want to achieve can very easily be done with a custom JSON.NET converter (JSON.NET is the default serialization library behind Web API JSON formatting engine).
All you need to do is:
public class Param
{
public int Id { get; set; }
public string Name { get; set; }
[JsonConverter(typeof(CustomArrayConverter))]
public string Choices { get; set; }
}
And then add the converter:
internal class CustomArrayConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
var array = JArray.Load(reader);
return JsonConvert.SerializeObject(array);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, JArray.Parse(value as string));
}
}
In this case we are telling JSON.NET in the converter to store Choices as string (in the read method), and when you return the Param object with the Choices property to the client (in the write method) we take the string and serialize to an array so that the output JSON looks identical to the input one.
You can test it now like this:
public Param PostParam(Param param)
{
return param;
}
And verify that the data coming in is like you wished, and the data coming out is identical to the original JSON.

asp.net MVC 2 - View Model / Model Validation - Is there a way to map validation attributes from model to ViewModel via AutoMapper? [duplicate]

I use AutoMapper to map my domain objects to my view models. I have metadata in my domain layer, that I would like to carry over to the view layer and into ModelMetadata. (This metadata is not UI logic, but provides necessary information to my views).
Right now, my solution is to use a separate MetadataProvider (independently of ASP.NET MVC), and use conventions to apply the relevant metadata to the ModelMetadata object via an AssociatedMetadataProvider. The problem with this approach is that I have to test for the same conventions when binding the ModelMetadata from the domain as I do with my AutoMapping, and it seems like there should be a way to make this more orthogonal. Can anyone recommend a better way to accomplish this?
I use the approach below to automatically copy data annotations from my entities to my view model. This ensures that things like StringLength and Required values are always the same for entity/viewmodel.
It works using the Automapper configuration, so works if the properties are named differently on the viewmodel as long as AutoMapper is setup correctly.
You need to create a custom ModelValidatorProvider and custom ModelMetadataProvider to get this to work. My memory on why is a little foggy, but I believe it's so both server and client side validation work, as well as any other formatting you do based on the metadata (eg an asterix next to required fields).
Note: I have simplified my code slightly as I added it below, so there may be a few small issues.
Metadata Provider
public class MetadataProvider : DataAnnotationsModelMetadataProvider
{
private IConfigurationProvider _mapper;
public MetadataProvider(IConfigurationProvider mapper)
{
_mapper = mapper;
}
protected override System.Web.Mvc.ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
//Grab attributes from the entity columns and copy them to the view model
var mappedAttributes = _mapper.GetMappedAttributes(containerType, propertyName, attributes);
return base.CreateMetadata(mappedAttributes, containerType, modelAccessor, modelType, propertyName);
}
}
Validator Provivder
public class ValidatorProvider : DataAnnotationsModelValidatorProvider
{
private IConfigurationProvider _mapper;
public ValidatorProvider(IConfigurationProvider mapper)
{
_mapper = mapper;
}
protected override System.Collections.Generic.IEnumerable<ModelValidator> GetValidators(System.Web.Mvc.ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
var mappedAttributes = _mapper.GetMappedAttributes(metadata.ContainerType, metadata.PropertyName, attributes);
return base.GetValidators(metadata, context, mappedAttributes);
}
}
Helper Method Referenced in above 2 classes
public static IEnumerable<Attribute> GetMappedAttributes(this IConfigurationProvider mapper, Type sourceType, string propertyName, IEnumerable<Attribute> existingAttributes)
{
if (sourceType != null)
{
foreach (var typeMap in mapper.GetAllTypeMaps().Where(i => i.SourceType == sourceType))
{
foreach (var propertyMap in typeMap.GetPropertyMaps())
{
if (propertyMap.IsIgnored() || propertyMap.SourceMember == null)
continue;
if (propertyMap.SourceMember.Name == propertyName)
{
foreach (ValidationAttribute attribute in propertyMap.DestinationProperty.GetCustomAttributes(typeof(ValidationAttribute), true))
{
if (!existingAttributes.Any(i => i.GetType() == attribute.GetType()))
yield return attribute;
}
}
}
}
}
if (existingAttributes != null)
{
foreach (var attribute in existingAttributes)
{
yield return attribute;
}
}
}
Other Notes
If you're using dependency injection, make sure your container isn't already replacing the built in metadata provider or validator provider. In my case I was using the Ninject.MVC3 package which bound one of them after creating the kernel, I then had to rebind it afterwards so my class was actually used. I was getting exceptions about Required only being allowed to be added once, took most of a day to track it down.
if your metadata are provided with attributes define the attributes in MetaDataTypes, then apply the same MetaDataType to both your domain class and to your viewmodels. You can define all MetaDataTypes in a separate dll that is reference by both layers. There are some issues with this approach if your ViewModel classes have not some properties that is used in the MetaDataType, but this can be fixed with a custom Provider(I have the code if youlike this approach).
Betty's solution is excellent for "inheriting" data annotations. I have extended this idea to also include validation provided by IValidatableObject.
public class MappedModelValidatorProvider : DataAnnotationsModelValidatorProvider
{
private readonly IMapper _mapper;
public MappedModelValidatorProvider(IMapper mapper)
{
_mapper = mapper;
}
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
var mappedAttributes = _mapper.ConfigurationProvider.GetMappedAttributes(metadata.ContainerType, metadata.PropertyName, attributes);
foreach (var validator in base.GetValidators(metadata, context, mappedAttributes))
{
yield return validator;
}
foreach (var typeMap in _mapper.ConfigurationProvider.GetAllTypeMaps().Where(i => i.SourceType == metadata.ModelType))
{
if (typeof(IValidatableObject).IsAssignableFrom(typeMap.DestinationType))
{
var model = _mapper.Map(metadata.Model, typeMap.SourceType, typeMap.DestinationType);
var modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeMap.DestinationType);
yield return new ValidatableObjectAdapter(modelMetadata, context);
}
}
}
}
Then in Global.asax.cs:
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new MappedModelValidatorProvider(Mapper.Instance));

Issues with my MVC repository pattern and StructureMap

I have a repository pattern i created on top of the ado.net entity framework. When i tried to implement StructureMap to decouple my objects, i kept getting StackOverflowException (infinite loop?). Here is what the pattern looks like:
IEntityRepository where TEntity : class
Defines basic CRUD members
MyEntityRepository : IEntityRepository
Implements CRUD members
IEntityService where TEntity : class
Defines CRUD members which return common types for each member.
MyEntityService : IEntityService
Uses the repository to retrieve data and return a common type as a result (IList, bool and etc)
The problem appears to be with my Service layer. More specifically with the constructors.
public PostService(IValidationDictionary validationDictionary)
: this(validationDictionary, new PostRepository())
{ }
public PostService(IValidationDictionary validationDictionary, IEntityRepository<Post> repository)
{
_validationDictionary = validationDictionary;
_repository = repository;
}
From the controller, i pass an object that implements IValidationDictionary. And i am explicitly calling the second constructor to initialize the repository.
This is what the controller constructors look like (the first one creates an instance of the validation object):
public PostController()
{
_service = new PostService(new ModelStateWrapper(this.ModelState));
}
public PostController(IEntityService<Post> service)
{
_service = service;
}
Everything works if i don't pass my IValidationDictionary object reference, in which case the first controller constructor would be removed and the service object would only have one constructor which accepts the repository interface as the parameter.
I appreciate any help with this :) Thanks.
It looks like the circular reference had to do with the fact that the service layer was dependent on the Controller's ModelState and the Controller dependent on the Service layer.
I had to rewrite my validation layer to get this to work. Here is what i did.
Define generic validator interface like below:
public interface IValidator<TEntity>
{
ValidationState Validate(TEntity entity);
}
We want to be able to return an instance of ValidationState which, obviously, defines the state of validation.
public class ValidationState
{
private readonly ValidationErrorCollection _errors;
public ValidationErrorCollection Errors
{
get
{
return _errors;
}
}
public bool IsValid
{
get
{
return Errors.Count == 0;
}
}
public ValidationState()
{
_errors = new ValidationErrorCollection();
}
}
Notice that we have an strongly typed error collection which we need to define as well. The collection is going to consist of ValidationError objects containing the property name of the entity we're validating and the error message associated with it. This just follows the standard ModelState interface.
public class ValidationErrorCollection : Collection<ValidationError>
{
public void Add(string property, string message)
{
Add(new ValidationError(property, message));
}
}
And here is what the ValidationError looks like:
public class ValidationError
{
private string _property;
private string _message;
public string Property
{
get
{
return _property;
}
private set
{
_property = value;
}
}
public string Message
{
get
{
return _message;
}
private set
{
_message = value;
}
}
public ValidationError(string property, string message)
{
Property = property;
Message = message;
}
}
The rest of this is StructureMap magic. We need to create validation service layer which will locate validation objects and validate our entity. I'd like to define an interface for this, since i want anyone using validation service to be completely unaware of the StructureMap presence. Besides, i think sprinkling ObjectFactory.GetInstance() anywhere besides the bootstrapper logic a bad idea. Keeping it centralized is a good way to insure good maintainability. Anyway, i use the decorator pattern here:
public interface IValidationService
{
ValidationState Validate<TEntity>(TEntity entity);
}
And we finally implement it:
public class ValidationService : IValidationService
{
#region IValidationService Members
public IValidator<TEntity> GetValidatorFor<TEntity>(TEntity entity)
{
return ObjectFactory.GetInstance<IValidator<TEntity>>();
}
public ValidationState Validate<TEntity>(TEntity entity)
{
IValidator<TEntity> validator = GetValidatorFor(entity);
if (validator == null)
{
throw new Exception("Cannot locate validator");
}
return validator.Validate(entity);
}
#endregion
}
I'm going to be using validation service in my controller. We could move it to the service layer and have StructureMap use property injection to inject an instance of controller's ModelState to the service layer, but i don't want the service layer to be coupled with ModelState. What if we decide to use another validation technique? This is why i'd rather put it in the controller. Here is what my controller looks like:
public class PostController : Controller
{
private IEntityService<Post> _service = null;
private IValidationService _validationService = null;
public PostController(IEntityService<Post> service, IValidationService validationService)
{
_service = service;
_validationService = validationService;
}
}
Here i am injecting my service layer and validaton service instances using StructureMap. So, we need to register both in StructureMap registry:
ForRequestedType<IValidationService>()
.TheDefaultIsConcreteType<ValidationService>();
ForRequestedType<IValidator<Post>>()
.TheDefaultIsConcreteType<PostValidator>();
That's it. I don't show how i implement my PostValidator, but it's simply implementing IValidator interface and defining validation logic in the Validate() method. All that's left to do is call your validation service instance to retrieve the validator, call the validate method on your entity and write any errors to ModelState.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "PostId")] Post post)
{
ValidationState vst = _validationService.Validate<Post>(post);
if (!vst.IsValid)
{
foreach (ValidationError error in vst.Errors)
{
this.ModelState.AddModelError(error.Property, error.Message);
}
return View(post);
}
...
}
Hope i helped somebody out with this :)
I used a similar solution involving a generic implementor of IValidationDictionary uses a StringDictionary and then copied the errors from this back into the model state in the controller.
Interface for validationdictionary
public interface IValidationDictionary
{
bool IsValid{get;}
void AddError(string Key, string errorMessage);
StringDictionary errors { get; }
}
Implementation of validation dictionary with no reference to model state or anything else so structuremap can create it easily
public class ValidationDictionary : IValidationDictionary
{
private StringDictionary _errors = new StringDictionary();
#region IValidationDictionary Members
public void AddError(string key, string errorMessage)
{
_errors.Add(key, errorMessage);
}
public bool IsValid
{
get { return (_errors.Count == 0); }
}
public StringDictionary errors
{
get { return _errors; }
}
#endregion
}
Code in the controller to copy the errors from the dictionary into the model state. This would probably be best as an extension function of Controller.
protected void copyValidationDictionaryToModelState()
{
// this copies the errors into viewstate
foreach (DictionaryEntry error in _service.validationdictionary.errors)
{
ModelState.AddModelError((string)error.Key, (string)error.Value);
}
}
thus bootstrapping code is like this
public static void BootstrapStructureMap()
{
// Initialize the static ObjectFactory container
ObjectFactory.Initialize(x =>
{
x.For<IContactRepository>().Use<EntityContactManagerRepository>();
x.For<IValidationDictionary>().Use<ValidationDictionary>();
x.For<IContactManagerService>().Use<ContactManagerService>();
});
}
and code to create controllers is like this
public class IocControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return (Controller)ObjectFactory.GetInstance(controllerType);
}
}
Just a quick query on this. It's helped me out quite a lot so thanks for putting the answer up, but I wondered which namespace TEntity exists in? I see Colletion(TEntity) needs System.Collections.ObjectModel. My file compiles without anything further but I see your TEntity reference highlighted in Blue which suggests it has a class type, mine is Black in Visual Studio. Hope you can help. I'm pretty keen to get this working.
Have you found any way to seperate validation into the service layer at all? My gut tells me that validating in the Controller is a bit smelly but I've looked high and low to find a way to pass validation error messages back to the controller without tightly coupling the service layer to the controller and can't find anything. :(
Again, thanks for the great post!
Lloyd

Resources