Advertisement
Guest User

Delta<TEntity> Validator

a guest
Sep 11th, 2013
440
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 3.36 KB | None | 0 0
  1. /// Provides validation logic for Delta<TEntity> paremeters for PATCH & MERGE actions.
  2. module WebApi.Infrastructure.Validation.DeltaOfTEntityTypeValidationProvider
  3.  
  4. open ImpromptuInterface.FSharp
  5. open System
  6. open System.Net.Http
  7. open System.Web.Http
  8. open System.Web.Http.Controllers
  9. open System.Web.Http.Metadata
  10. open System.Web.Http.OData
  11. open System.Web.Http.Validation
  12.  
  13. let [<Literal>] PatchMethod = "PATCH"
  14. let [<Literal>] MergeMethod = "MERGE"
  15.    
  16. /// Returns true if the given method is PATCH or MERGE.
  17. let isPatchOrMergeMethod (method' : HttpMethod) =
  18.    [ PatchMethod; MergeMethod ] |> Seq.exists method'.Method.Equals
  19.  
  20. /// Looks for an object of type Delta<TEntity> in the provided sequence.
  21. /// Returns None if the object could not be found.
  22. let tryFindDeltaParameter = Seq.tryFind (function
  23.     | null -> false
  24.     | arg ->  let argType = arg.GetType ()
  25.               argType.IsGenericType && typedefof<Delta<_>>.Equals (argType.GetGenericTypeDefinition ())
  26. )
  27.  
  28. /// Creates an instance of the entity type the Delta<TEntity> object encapsulates.
  29. let createEntityInstance deltaParameter =
  30.     deltaParameter?EntityType
  31.     |> (Activator.CreateInstance : Type -> Object)
  32.  
  33. /// Looks for validators that can validate the property represented by the passed metadata.
  34. let findPropertyValidators metadata = seq {
  35.     let validatorProviders = GlobalConfiguration.Configuration.Services.GetModelValidatorProviders ()
  36.     for validatorProvider in validatorProviders do
  37.         yield! validatorProvider.GetValidators (metadata, validatorProviders)
  38. }
  39.  
  40. /// Creates a ModelMetadata object representing the provided property of the entity object.
  41. let createMetadata entity propertyName =
  42.     let property = entity.GetType().GetProperty propertyName
  43.     ModelMetadata (
  44.         provider      = GlobalConfiguration.Configuration.Services.GetModelMetadataProvider (),
  45.         containerType = property.DeclaringType,
  46.         modelAccessor = Func<_> (fun () -> property.GetValue entity),
  47.         modelType     = property.PropertyType,
  48.         propertyName  = property.Name
  49.     )
  50.  
  51. /// Validates all changed properties of the provided Delta<TEntity> object and returns
  52. /// a sequence of validation results.
  53. let validateDelta deltaParameter = seq {
  54.     let entity = createEntityInstance deltaParameter
  55.     do deltaParameter?CopyChangedValues entity
  56.     for propertyName in deltaParameter?GetChangedPropertyNames () do
  57.         let metadata = createMetadata entity propertyName
  58.         for propertyValidator in findPropertyValidators metadata do
  59.             yield! propertyValidator.Validate (metadata, entity)
  60. }
  61.  
  62. /// Adds the provided validation results to the action context as model errors.
  63. let addModelErrors (actionContext : HttpActionContext) =
  64.     Seq.iter (fun (validationResult : ModelValidationResult) ->
  65.         actionContext.ModelState.AddModelError (validationResult.MemberName, validationResult.Message)
  66.     )
  67.  
  68. /// Looks for a Delta<TEntity> object passed as an argument to the action method
  69. /// and validates it. The validation results are added as model errors to the model state.
  70. let searchAndValidateDelta (actionContext : HttpActionContext) =
  71.     if isPatchOrMergeMethod actionContext.Request.Method then
  72.         tryFindDeltaParameter actionContext.ActionArguments.Values
  73.         |> Option.map validateDelta
  74.         |> Option.iter (addModelErrors actionContext)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement