independer / wcfdataannotations Goto Github PK
View Code? Open in Web Editor NEWThis repository is a fork of DevTrends WCF DataAnnotations
License: MIT License
This repository is a fork of DevTrends WCF DataAnnotations
License: MIT License
Please, sign your assembly with a strong name to be usable in strong-named projects. I can't reference your NuGet package directly in my WCF library, I get the following error:
System.IO.FileLoadException: Could not load file or assembly 'Independer.WCFDataAnnotations, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. A strongly-named assembly is required. (Exception from HRESULT: 0x80131044)
File name: 'Independer.WCFDataAnnotations, Version=1.1.0.0, Culture=neutral, PublicKeyToken=null'
at System.ModuleHandle.ResolveType(RuntimeModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)
at System.ModuleHandle.ResolveTypeHandleInternal(RuntimeModule module, Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(CustomAttributeRecord caRecord, MetadataImport scope, Assembly& lastAptcaOkAssembly, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, Object[] attributes, IList derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctor, Boolean& ctorHasParameters, Boolean& isVarArg)
at System.Reflection.CustomAttribute.IsCustomAttributeDefined(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Int32 attributeCtorToken, Boolean mustBeInheritable)
at System.Reflection.CustomAttribute.IsDefined(RuntimeType type, RuntimeType caType, Boolean inherit)
at Microsoft.Tools.Common.ServiceReflectionUtility.HasServiceContractAttribute(Type type)
at Microsoft.Tools.Common.ServiceReflectionUtility.IsWcfServiceClass(Type type)
at Microsoft.Tools.SvcHost.ServiceHostHelper.CheckServiceKind(Type type)
at Microsoft.Tools.SvcHost.ServiceHostHelper.LoadServiceAssembly(String svcAssemblyPath)
at Microsoft.Tools.SvcHost.ServiceHostHelper.LoadServiceAssembly(String svcAssemblyPath)
at Microsoft.Tools.SvcHost.CrossAppDomainSvcHost..ctor(String svcAssemblyPath, String svcConfigPath)
Thanks,
Moski
Hi,
I got very happy when i saw your fork as i need to validate nested collections within my serviceoperation argument types. But im not getting it to work. i have the following class.
[DataContract(IsReference = true)]
public class MyDto : MyBase
{
[DataMember]
[Required]
public string OrderNo { get; set; }
[DataMember]
public ICollection<MySubDto> MySubDtoCollection = new List<MySubDto>();
}
And my subcollection class:
[DataContract(IsReference = true)]
public class MySubDto : IValidatableObject
{
[DataMember]
[Required]
public string IssueNo { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
throw new NotImplementedException();
}
}
My service implements [ValidateDataAnnotationsBehavior] and my required attributes etc. work, but only for for MyDto but not for MySubDto. The Validate method is never called on MySubDto, i tried declaring the collectionproperty as IEnumerable, List etc but it does not work.
Thanks you
Hi,
I've written some code to expose the Data Annotation rules via the WSDL. Maybe you could add this to WfcDataAnnotations for completeness sake? I guess the code can be in co-operated into the ValidateDataAnnotationsBehaviorAttribute.
/// <summary>
/// Make DataAnnotations visible in the Wsdl.
/// Place attribute on service implementation class.
/// Use togehter with https://github.com/Independer/wcfdataannotations also get data annotations validation.
///
/// Example:
///
/// [ValidateDataAnnotationsBehavior]
/// [WsdlExportDataAnnotationsBehavior]
/// public class Service : IService
/// {
/// ...
/// }
///
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class WsdlExportDataAnnotationsBehaviorAttribute : Attribute, IContractBehavior, IWsdlExportExtension
{
private const string XmlDatatypeNamespace = "http://www.w3.org/2001/XMLSchema";
private const string ValidateEmailPattern = @"(?i)^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$";
public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context) { }
public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
{
if (context.ContractConversionContext.Contract == null)
return;
// Check all operations for properties
foreach (OperationDescription op in context.ContractConversionContext.Contract.Operations)
{
foreach (ParameterInfo parameter in op.SyncMethod.GetParameters())
{
AddPropertyAttributes(parameter.ParameterType, exporter.GeneratedXmlSchemas);
}
}
}
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) { }
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) { }
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) { }
private void AddPropertyAttributes(Type type, XmlSchemaSet schemaSet)
{
if (type == null)
return;
if (type.IsArray)
type = type.GetElementType();
if (type.IsGenericType)
type = type.GenericTypeArguments[0];
foreach (PropertyInfo property in type.GetProperties())
{
// Handle sub properties
if (property.PropertyType.Assembly == type.Assembly || property.PropertyType.Namespace.StartsWith("System.Collections"))
{
AddPropertyAttributes(property.PropertyType, schemaSet);
}
// There should at least exist DataMemberAttribute + a DataAnnotationAttribute
var attributes = property.GetCustomAttributes();
var attributeList = attributes as IList<Attribute> ?? attributes.ToList();
if (attributeList.Count() < 2)
continue;
// Only process properties with the Data Member attribute
if (!attributeList.Any(x => x is DataMemberAttribute))
continue;
// Find the property in the WSDL schema to update
XmlSchemaElement propertyElement = null;
foreach (var value in schemaSet.GlobalTypes.Values)
{
var complexType = value as XmlSchemaComplexType;
if (complexType != null && complexType.ContentTypeParticle is XmlSchemaSequence)
{
if (property.DeclaringType == null || complexType.Name != property.DeclaringType.Name)
continue;
var sequence = (XmlSchemaSequence)complexType.ContentTypeParticle;
propertyElement = sequence.Items.Cast<XmlSchemaElement>().ToList().SingleOrDefault(x => x.Name == property.Name);
break;
}
}
// Handle different types of annotations
foreach (var attribute in attributeList)
{
if (attribute is DataMemberAttribute)
continue;
if (attribute is RequiredAttribute)
{
ApplyRequiredAttribute(propertyElement);
}
else if (attribute is StringLengthAttribute)
{
ApplyStringLengthAttribute(propertyElement, ((StringLengthAttribute)attribute));
}
else if (attribute is MinLengthAttribute)
{
ApplyMinLengthAttribute(propertyElement, ((MinLengthAttribute)attribute));
}
else if (attribute is MaxLengthAttribute)
{
ApplyMaxLengthAttribute(propertyElement, ((MaxLengthAttribute)attribute));
}
else if (attribute is RangeAttribute)
{
ApplyRangeAttribute(propertyElement, ((RangeAttribute)attribute));
}
else if (attribute is RegularExpressionAttribute)
{
ApplyRegularExpressionAttribute(propertyElement, ((RegularExpressionAttribute)attribute));
}
else if (attribute is EmailAddressAttribute)
{
ApplyEmailAddressAttribute(propertyElement);
}
else
{
// Don't let anything slipp through without us knowing
throw new Exception("Unhandled annotation exception!");
}
}
}
}
private XmlSchemaSimpleTypeRestriction GetSimpleTypeRestriction(XmlSchemaElement element, XmlQualifiedName baseTypeName)
{
var simpleType = element.SchemaType as XmlSchemaSimpleType;
if (simpleType == null)
element.SchemaType = simpleType = new XmlSchemaSimpleType();
var simpleTypeRestriction = simpleType.Content as XmlSchemaSimpleTypeRestriction;
if (simpleTypeRestriction == null)
simpleType.Content = simpleTypeRestriction = new XmlSchemaSimpleTypeRestriction { BaseTypeName = baseTypeName };
element.SchemaTypeName = null;
return simpleTypeRestriction;
}
private void ApplyRequiredAttribute(object item)
{
var element = item as XmlSchemaElement;
if (element != null)
{
element.IsNillable = false;
element.MinOccurs = 1;
}
}
private void ApplyStringLengthAttribute(object item, StringLengthAttribute attribute)
{
var element = item as XmlSchemaElement;
if (element != null && element.ElementSchemaType.Datatype.TypeCode == XmlTypeCode.String)
{
var simpleTypeRestriction = GetSimpleTypeRestriction(element, new XmlQualifiedName("string", XmlDatatypeNamespace));
simpleTypeRestriction.Facets.Add(new XmlSchemaMinLengthFacet { Value = attribute.MinimumLength.ToString() });
simpleTypeRestriction.Facets.Add(new XmlSchemaMaxLengthFacet { Value = attribute.MaximumLength.ToString() });
}
}
private void ApplyMinLengthAttribute(object item, MinLengthAttribute attribute)
{
var element = item as XmlSchemaElement;
if (element != null && element.ElementSchemaType.Datatype.TypeCode == XmlTypeCode.String)
{
var simpleTypeRestriction = GetSimpleTypeRestriction(element, new XmlQualifiedName("string", XmlDatatypeNamespace));
simpleTypeRestriction.Facets.Add(new XmlSchemaMinLengthFacet { Value = attribute.Length.ToString() });
}
}
private void ApplyMaxLengthAttribute(object item, MaxLengthAttribute attribute)
{
var element = item as XmlSchemaElement;
if (element != null && element.ElementSchemaType.Datatype.TypeCode == XmlTypeCode.String)
{
var simpleTypeRestriction = GetSimpleTypeRestriction(element, new XmlQualifiedName("string", XmlDatatypeNamespace));
simpleTypeRestriction.Facets.Add(new XmlSchemaMaxLengthFacet { Value = attribute.Length.ToString() });
}
}
private void ApplyRangeAttribute(object item, RangeAttribute attribute)
{
var element = item as XmlSchemaElement;
if (element != null)
{
dynamic minimum = attribute.Minimum;
dynamic maximum = attribute.Maximum;
var simpleTypeRestriction = GetSimpleTypeRestriction(element, new XmlQualifiedName(element.ElementSchemaType.Datatype.TypeCode.ToString().ToLower(), XmlDatatypeNamespace));
simpleTypeRestriction.Facets.Add(new XmlSchemaMinInclusiveFacet { Value = XmlConvert.ToString(minimum) });
simpleTypeRestriction.Facets.Add(new XmlSchemaMaxInclusiveFacet { Value = XmlConvert.ToString(maximum) });
}
}
private void ApplyRegularExpressionAttribute(object item, RegularExpressionAttribute attribute)
{
var element = item as XmlSchemaElement;
if (element != null)
{
var simpleTypeRestriction = GetSimpleTypeRestriction(element, new XmlQualifiedName(element.ElementSchemaType.Datatype.TypeCode.ToString().ToLower(), XmlDatatypeNamespace));
simpleTypeRestriction.Facets.Add(new XmlSchemaPatternFacet() { Value = attribute.Pattern });
}
}
private void ApplyEmailAddressAttribute(object item)
{
var element = item as XmlSchemaElement;
if (element != null)
{
// Regexp pattern taken from http://referencesource.microsoft.com/#System.ComponentModel.DataAnnotations/DataAnnotations/EmailAddressAttribute.cs
var simpleTypeRestriction = GetSimpleTypeRestriction(element, new XmlQualifiedName("string", XmlDatatypeNamespace));
simpleTypeRestriction.Facets.Add(new XmlSchemaPatternFacet() { Value = ValidateEmailPattern });
}
}
}
Independer.WCFDataAnnotations.ValidateDataAnnotationsBehavior.GetParameterInfo(String operationName, IEnumerable`1 contractOperations)
I am having multiple types of binding for same contract
the old codeplex is gone, as I am sure you are aware. Maybe mention this site in the readme https://www.devtrends.co.uk/blog/validating-wcf-service-operations-using-system.componentmodel.dataannotations
The new release of Independer.WCFDataAnnotations-Signed 1.2.0 actually doesn't have any strong name.
Thanks,
Moski
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.